:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / fs / vfat / volume.c
1 /* $Id$
2  *
3  * COPYRIGHT:        See COPYING in the top level directory
4  * PROJECT:          ReactOS kernel
5  * FILE:             services/fs/vfat/volume.c
6  * PURPOSE:          VFAT Filesystem
7  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
8  */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ddk/ntddk.h>
13 #include <wchar.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 #include "vfat.h"
19
20 /* FUNCTIONS ****************************************************************/
21
22 static NTSTATUS
23 FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
24                           PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
25                           PULONG BufferLength)
26 {
27   ULONG LabelLength;
28
29   DPRINT("FsdGetFsVolumeInformation()\n");
30   DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
31   DPRINT("BufferLength %lu\n", *BufferLength);
32
33   LabelLength = DeviceObject->Vpb->VolumeLabelLength;
34
35   DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)));
36   DPRINT("LabelLength %lu\n", LabelLength);
37   DPRINT("Label %S\n", DeviceObject->Vpb->VolumeLabel);
38
39   if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
40     return STATUS_INFO_LENGTH_MISMATCH;
41
42   if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength*sizeof(WCHAR)))
43     return STATUS_BUFFER_OVERFLOW;
44
45   /* valid entries */
46   FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
47   FsVolumeInfo->VolumeLabelLength = LabelLength * sizeof (WCHAR);
48   wcscpy(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
49
50   /* dummy entries */
51   FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
52   FsVolumeInfo->SupportsObjects = FALSE;
53
54   DPRINT("Finished FsdGetFsVolumeInformation()\n");
55
56   *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + LabelLength * sizeof(WCHAR));
57
58   DPRINT("BufferLength %lu\n", *BufferLength);
59
60   return(STATUS_SUCCESS);
61 }
62
63
64 static NTSTATUS
65 FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
66                              PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
67                              PULONG BufferLength)
68 {
69   ULONG Length = DeviceExt->FatInfo.FatType == FAT32 ? 10 : 6;
70
71   DPRINT("FsdGetFsAttributeInformation()\n");
72   DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
73   DPRINT("BufferLength %lu\n", *BufferLength);
74   DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length));
75
76   if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
77     return STATUS_INFO_LENGTH_MISMATCH;
78
79   if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length))
80     return STATUS_BUFFER_OVERFLOW;
81
82   FsAttributeInfo->FileSystemAttributes =
83     FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
84   FsAttributeInfo->MaximumComponentNameLength = 255;
85   FsAttributeInfo->FileSystemNameLength = Length;
86   if (DeviceExt->FatInfo.FatType == FAT32)
87   {
88     memcpy(FsAttributeInfo->FileSystemName, L"FAT32", 10);
89   }
90   else
91   {
92     memcpy(FsAttributeInfo->FileSystemName, L"FAT", 6);
93   }
94
95   DPRINT("Finished FsdGetFsAttributeInformation()\n");
96
97   *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length);
98   DPRINT("BufferLength %lu\n", *BufferLength);
99
100   return(STATUS_SUCCESS);
101 }
102
103
104 static NTSTATUS
105 FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
106                         PFILE_FS_SIZE_INFORMATION FsSizeInfo,
107                         PULONG BufferLength)
108 {
109   PDEVICE_EXTENSION DeviceExt;
110   NTSTATUS Status;
111
112   DPRINT("FsdGetFsSizeInformation()\n");
113   DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
114
115   if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
116     return(STATUS_BUFFER_OVERFLOW);
117
118   DeviceExt = DeviceObject->DeviceExtension;
119   Status = CountAvailableClusters(DeviceExt, &FsSizeInfo->AvailableAllocationUnits);
120
121   FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->FatInfo.NumberOfClusters;
122   FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->FatInfo.SectorsPerCluster;
123   FsSizeInfo->BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
124
125   DPRINT("Finished FsdGetFsSizeInformation()\n");
126   if (NT_SUCCESS(Status))
127     *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
128
129   return(Status);
130 }
131
132
133 static NTSTATUS
134 FsdGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
135                           PULONG BufferLength)
136 {
137   DPRINT("FsdGetFsDeviceInformation()\n");
138   DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
139   DPRINT("BufferLength %lu\n", *BufferLength);
140   DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
141
142   if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
143     return(STATUS_BUFFER_OVERFLOW);
144
145   FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
146   FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */
147
148   DPRINT("FsdGetFsDeviceInformation() finished.\n");
149
150   *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
151   DPRINT("BufferLength %lu\n", *BufferLength);
152
153   return(STATUS_SUCCESS);
154 }
155
156
157 static NTSTATUS
158 FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject,
159                          PFILE_FS_LABEL_INFORMATION FsLabelInfo)
160 {
161   DPRINT("FsdSetFsLabelInformation()\n");
162
163   return(STATUS_NOT_IMPLEMENTED);
164 }
165
166
167 NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
168 /*
169  * FUNCTION: Retrieve the specified volume information
170  */
171 {
172   FS_INFORMATION_CLASS FsInformationClass;
173   NTSTATUS RC = STATUS_SUCCESS;
174   PVOID SystemBuffer;
175   ULONG BufferLength;
176
177   /* PRECONDITION */
178   assert(IrpContext);
179
180   DPRINT("VfatQueryVolumeInformation(IrpContext %x)\n", IrpContext);
181
182   if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
183   {
184      return VfatQueueRequest (IrpContext);
185   }
186
187   /* INITIALIZATION */
188   FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass;
189   BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length;
190   SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
191
192
193   DPRINT ("FsInformationClass %d\n", FsInformationClass);
194   DPRINT ("SystemBuffer %x\n", SystemBuffer);
195
196   switch (FsInformationClass)
197     {
198     case FileFsVolumeInformation:
199       RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject,
200                                      SystemBuffer,
201                                      &BufferLength);
202       break;
203
204     case FileFsAttributeInformation:
205       RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension,
206                                         SystemBuffer,
207                                         &BufferLength);
208       break;
209
210     case FileFsSizeInformation:
211       RC = FsdGetFsSizeInformation(IrpContext->DeviceObject,
212                                    SystemBuffer,
213                                    &BufferLength);
214       break;
215
216     case FileFsDeviceInformation:
217       RC = FsdGetFsDeviceInformation(SystemBuffer,
218                                      &BufferLength);
219       break;
220
221     default:
222       RC = STATUS_NOT_SUPPORTED;
223     }
224
225   ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
226   IrpContext->Irp->IoStatus.Status = RC;
227   if (NT_SUCCESS(RC))
228     IrpContext->Irp->IoStatus.Information =
229       IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength;
230   else
231     IrpContext->Irp->IoStatus.Information = 0;
232   IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
233   VfatFreeIrpContext(IrpContext);
234
235   return RC;
236 }
237
238
239 NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
240 /*
241  * FUNCTION: Set the specified volume information
242  */
243 {
244   FS_INFORMATION_CLASS FsInformationClass;
245   NTSTATUS Status = STATUS_SUCCESS;
246   PVOID SystemBuffer;
247   ULONG BufferLength;
248
249   /* PRECONDITION */
250   assert(IrpContext);
251
252   DPRINT1("VfatSetVolumeInformation(IrpContext %x)\n", IrpContext);
253
254   if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
255   {
256      return VfatQueueRequest (IrpContext);
257   }
258
259   FsInformationClass = IrpContext->Stack->Parameters.SetVolume.FsInformationClass;
260   BufferLength = IrpContext->Stack->Parameters.SetVolume.Length;
261   SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
262
263   DPRINT1("FsInformationClass %d\n", FsInformationClass);
264   DPRINT1("BufferLength %d\n", BufferLength);
265   DPRINT1("SystemBuffer %x\n", SystemBuffer);
266
267   switch(FsInformationClass)
268     {
269     case FileFsLabelInformation:
270       Status = FsdSetFsLabelInformation(IrpContext->DeviceObject,
271                                         SystemBuffer);
272       break;
273
274     default:
275       Status = STATUS_NOT_SUPPORTED;
276     }
277
278   ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
279   IrpContext->Irp->IoStatus.Status = Status;
280   IrpContext->Irp->IoStatus.Information = 0;
281   IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
282   VfatFreeIrpContext(IrpContext);
283
284   return(Status);
285 }
286
287 /* EOF */