All:
[reactos.git] / reactos / drivers / fs / vfat / volume.c
1 /* $Id: volume.c,v 1.15 2002/03/18 22:37:13 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(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 */