Reworked code for handling of asynchonous i/o requests.
[reactos.git] / reactos / drivers / fs / vfat / volume.c
1 /* $Id: volume.c,v 1.14 2001/11/02 22:47:36 hbirr Exp $
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(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
66 PULONG BufferLength)
67 {
68 DPRINT("FsdGetFsAttributeInformation()\n");
69 DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
70 DPRINT("BufferLength %lu\n", *BufferLength);
71 DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6));
72
73 if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
74 return STATUS_INFO_LENGTH_MISMATCH;
75
76 if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6))
77 return STATUS_BUFFER_OVERFLOW;
78
79 FsAttributeInfo->FileSystemAttributes =
80 FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
81 FsAttributeInfo->MaximumComponentNameLength = 255;
82 FsAttributeInfo->FileSystemNameLength = 6;
83 wcscpy(FsAttributeInfo->FileSystemName, L"FAT");
84
85 DPRINT("Finished FsdGetFsAttributeInformation()\n");
86
87 *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 6);
88 DPRINT("BufferLength %lu\n", *BufferLength);
89
90 return(STATUS_SUCCESS);
91 }
92
93
94 static NTSTATUS
95 FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
96 PFILE_FS_SIZE_INFORMATION FsSizeInfo,
97 PULONG BufferLength)
98 {
99 PDEVICE_EXTENSION DeviceExt;
100 NTSTATUS Status;
101
102 DPRINT("FsdGetFsSizeInformation()\n");
103 DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
104
105 if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
106 return(STATUS_BUFFER_OVERFLOW);
107
108 DeviceExt = DeviceObject->DeviceExtension;
109
110 if (DeviceExt->FatType == FAT32)
111 {
112 struct _BootSector32 *BootSect =
113 (struct _BootSector32 *) DeviceExt->Boot;
114
115 FsSizeInfo->TotalAllocationUnits.QuadPart = ((BootSect->Sectors ? BootSect->Sectors : BootSect->SectorsHuge)-DeviceExt->dataStart)/BootSect->SectorsPerCluster;
116
117 Status = FAT32CountAvailableClusters(DeviceExt,
118 &FsSizeInfo->AvailableAllocationUnits);
119
120 FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
121 FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
122 }
123 else
124 {
125 struct _BootSector *BootSect = (struct _BootSector *) DeviceExt->Boot;
126
127 FsSizeInfo->TotalAllocationUnits.QuadPart = ((BootSect->Sectors ? BootSect->Sectors : BootSect->SectorsHuge)-DeviceExt->dataStart)/BootSect->SectorsPerCluster;
128
129 if (DeviceExt->FatType == FAT16)
130 Status = FAT16CountAvailableClusters(DeviceExt,
131 &FsSizeInfo->AvailableAllocationUnits);
132 else
133 Status = FAT12CountAvailableClusters(DeviceExt,
134 &FsSizeInfo->AvailableAllocationUnits);
135 FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
136 FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
137 }
138
139 DPRINT("Finished FsdGetFsSizeInformation()\n");
140 if (NT_SUCCESS(Status))
141 *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
142
143 return(Status);
144 }
145
146
147 static NTSTATUS
148 FsdGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
149 PULONG BufferLength)
150 {
151 DPRINT("FsdGetFsDeviceInformation()\n");
152 DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
153 DPRINT("BufferLength %lu\n", *BufferLength);
154 DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
155
156 if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
157 return(STATUS_BUFFER_OVERFLOW);
158
159 FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
160 FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */
161
162 DPRINT("FsdGetFsDeviceInformation() finished.\n");
163
164 *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
165 DPRINT("BufferLength %lu\n", *BufferLength);
166
167 return(STATUS_SUCCESS);
168 }
169
170
171 static NTSTATUS
172 FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject,
173 PFILE_FS_LABEL_INFORMATION FsLabelInfo)
174 {
175 DPRINT("FsdSetFsLabelInformation()\n");
176
177 return(STATUS_NOT_IMPLEMENTED);
178 }
179
180
181 NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
182 /*
183 * FUNCTION: Retrieve the specified volume information
184 */
185 {
186 FS_INFORMATION_CLASS FsInformationClass;
187 NTSTATUS RC = STATUS_SUCCESS;
188 PVOID SystemBuffer;
189 ULONG BufferLength;
190
191 /* PRECONDITION */
192 assert(IrpContext);
193
194 DPRINT("VfatQueryVolumeInformation(IrpContext %x)\n", IrpContext);
195
196 if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
197 {
198 return VfatQueueRequest (IrpContext);
199 }
200
201 /* INITIALIZATION */
202 FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass;
203 BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length;
204 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
205
206
207 DPRINT ("FsInformationClass %d\n", FsInformationClass);
208 DPRINT ("SystemBuffer %x\n", SystemBuffer);
209
210 switch (FsInformationClass)
211 {
212 case FileFsVolumeInformation:
213 RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject,
214 SystemBuffer,
215 &BufferLength);
216 break;
217
218 case FileFsAttributeInformation:
219 RC = FsdGetFsAttributeInformation(SystemBuffer,
220 &BufferLength);
221 break;
222
223 case FileFsSizeInformation:
224 RC = FsdGetFsSizeInformation(IrpContext->DeviceObject,
225 SystemBuffer,
226 &BufferLength);
227 break;
228
229 case FileFsDeviceInformation:
230 RC = FsdGetFsDeviceInformation(SystemBuffer,
231 &BufferLength);
232 break;
233
234 default:
235 RC = STATUS_NOT_SUPPORTED;
236 }
237
238 ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
239 IrpContext->Irp->IoStatus.Status = RC;
240 if (NT_SUCCESS(RC))
241 IrpContext->Irp->IoStatus.Information =
242 IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength;
243 else
244 IrpContext->Irp->IoStatus.Information = 0;
245 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
246 VfatFreeIrpContext(IrpContext);
247
248 return RC;
249 }
250
251
252 NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
253 /*
254 * FUNCTION: Set the specified volume information
255 */
256 {
257 FS_INFORMATION_CLASS FsInformationClass;
258 NTSTATUS Status = STATUS_SUCCESS;
259 PVOID SystemBuffer;
260 ULONG BufferLength;
261
262 /* PRECONDITION */
263 assert(IrpContext);
264
265 DPRINT1("VfatSetVolumeInformation(IrpContext %x)\n", IrpContext);
266
267 if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource, IrpContext->Flags & IRPCONTEXT_CANWAIT))
268 {
269 return VfatQueueRequest (IrpContext);
270 }
271
272 FsInformationClass = IrpContext->Stack->Parameters.SetVolume.FsInformationClass;
273 BufferLength = IrpContext->Stack->Parameters.SetVolume.Length;
274 SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
275
276 DPRINT1("FsInformationClass %d\n", FsInformationClass);
277 DPRINT1("BufferLength %d\n", BufferLength);
278 DPRINT1("SystemBuffer %x\n", SystemBuffer);
279
280 switch(FsInformationClass)
281 {
282 case FileFsLabelInformation:
283 Status = FsdSetFsLabelInformation(IrpContext->DeviceObject,
284 SystemBuffer);
285 break;
286
287 default:
288 Status = STATUS_NOT_SUPPORTED;
289 }
290
291 ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
292 IrpContext->Irp->IoStatus.Status = Status;
293 IrpContext->Irp->IoStatus.Information = 0;
294 IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
295 VfatFreeIrpContext(IrpContext);
296
297 return(Status);
298 }
299
300 /* EOF */