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