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