[EXT2] Upgrade to 0.69
[reactos.git] / drivers / filesystems / ext2 / src / volinfo.c
1 /*
2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4 * FILE: volinfo.c
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "ext2fs.h"
13
14 /* GLOBALS ***************************************************************/
15
16 extern PEXT2_GLOBAL Ext2Global;
17
18 /* DEFINITIONS *************************************************************/
19
20 #ifdef ALLOC_PRAGMA
21 #pragma alloc_text(PAGE, Ext2QueryVolumeInformation)
22 #pragma alloc_text(PAGE, Ext2SetVolumeInformation)
23 #endif
24
25
26 NTSTATUS
27 Ext2QueryVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
28 {
29 PDEVICE_OBJECT DeviceObject;
30 PEXT2_VCB Vcb = NULL;
31 PIRP Irp = NULL;
32 PIO_STACK_LOCATION IoStackLocation = NULL;
33 PVOID Buffer;
34 ULONG Length;
35 NTSTATUS Status = STATUS_UNSUCCESSFUL;
36 FS_INFORMATION_CLASS FsInformationClass;
37 BOOLEAN VcbResourceAcquired = FALSE;
38
39 _SEH2_TRY {
40
41 ASSERT(IrpContext != NULL);
42 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
43 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
44
45 DeviceObject = IrpContext->DeviceObject;
46
47 //
48 // This request is not allowed on the main device object
49 //
50 if (IsExt2FsDevice(DeviceObject)) {
51 Status = STATUS_INVALID_DEVICE_REQUEST;
52 _SEH2_LEAVE;
53 }
54
55 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
56 ASSERT(Vcb != NULL);
57 ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
58 (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
59
60 if (!IsMounted(Vcb)) {
61 Status = STATUS_VOLUME_DISMOUNTED;
62 _SEH2_LEAVE;
63 }
64
65 if (!ExAcquireResourceSharedLite(
66 &Vcb->MainResource,
67 IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)
68 )) {
69
70 Status = STATUS_PENDING;
71 _SEH2_LEAVE;
72 }
73 VcbResourceAcquired = TRUE;
74
75 Irp = IrpContext->Irp;
76 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
77 FsInformationClass =
78 IoStackLocation->Parameters.QueryVolume.FsInformationClass;
79
80 Length = IoStackLocation->Parameters.QueryVolume.Length;
81 Buffer = Irp->AssociatedIrp.SystemBuffer;
82
83 RtlZeroMemory(Buffer, Length);
84
85 switch (FsInformationClass) {
86
87 case FileFsVolumeInformation:
88 {
89 PFILE_FS_VOLUME_INFORMATION FsVolInfo;
90 ULONG VolumeLabelLength;
91 ULONG RequiredLength;
92
93 if (Length < sizeof(FILE_FS_VOLUME_INFORMATION)) {
94 Status = STATUS_BUFFER_OVERFLOW;
95 _SEH2_LEAVE;
96 }
97
98 FsVolInfo = (PFILE_FS_VOLUME_INFORMATION) Buffer;
99 FsVolInfo->VolumeCreationTime.QuadPart = 0;
100 FsVolInfo->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
101 VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
102 FsVolInfo->VolumeLabelLength = VolumeLabelLength;
103 /* We don't support ObjectId */
104 FsVolInfo->SupportsObjects = FALSE;
105
106 RequiredLength = sizeof(FILE_FS_VOLUME_INFORMATION)
107 + VolumeLabelLength - sizeof(WCHAR);
108
109 if (Length < RequiredLength) {
110 Irp->IoStatus.Information =
111 sizeof(FILE_FS_VOLUME_INFORMATION);
112 Status = STATUS_BUFFER_OVERFLOW;
113 _SEH2_LEAVE;
114 }
115
116 RtlCopyMemory(FsVolInfo->VolumeLabel, Vcb->Vpb->VolumeLabel, Vcb->Vpb->VolumeLabelLength);
117
118 Irp->IoStatus.Information = RequiredLength;
119 Status = STATUS_SUCCESS;
120 }
121 break;
122
123 case FileFsSizeInformation:
124 {
125 PFILE_FS_SIZE_INFORMATION FsSizeInfo;
126
127 if (Length < sizeof(FILE_FS_SIZE_INFORMATION)) {
128 Status = STATUS_BUFFER_OVERFLOW;
129 _SEH2_LEAVE;
130 }
131
132 FsSizeInfo = (PFILE_FS_SIZE_INFORMATION) Buffer;
133 FsSizeInfo->TotalAllocationUnits.QuadPart =
134 ext3_blocks_count(SUPER_BLOCK);
135 FsSizeInfo->AvailableAllocationUnits.QuadPart =
136 ext3_free_blocks_count(SUPER_BLOCK);
137 FsSizeInfo->SectorsPerAllocationUnit =
138 Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
139 FsSizeInfo->BytesPerSector =
140 Vcb->DiskGeometry.BytesPerSector;
141
142 Irp->IoStatus.Information = sizeof(FILE_FS_SIZE_INFORMATION);
143 Status = STATUS_SUCCESS;
144 }
145 break;
146
147 case FileFsDeviceInformation:
148 {
149 PFILE_FS_DEVICE_INFORMATION FsDevInfo;
150
151 if (Length < sizeof(FILE_FS_DEVICE_INFORMATION)) {
152 Status = STATUS_BUFFER_OVERFLOW;
153 _SEH2_LEAVE;
154 }
155
156 FsDevInfo = (PFILE_FS_DEVICE_INFORMATION) Buffer;
157 FsDevInfo->DeviceType =
158 Vcb->TargetDeviceObject->DeviceType;
159
160 if (FsDevInfo->DeviceType != FILE_DEVICE_DISK) {
161 DbgBreak();
162 }
163
164 FsDevInfo->Characteristics =
165 Vcb->TargetDeviceObject->Characteristics;
166
167 if (IsVcbReadOnly(Vcb)) {
168 SetFlag( FsDevInfo->Characteristics,
169 FILE_READ_ONLY_DEVICE );
170 }
171
172 Irp->IoStatus.Information = sizeof(FILE_FS_DEVICE_INFORMATION);
173 Status = STATUS_SUCCESS;
174 }
175 break;
176
177 case FileFsAttributeInformation:
178 {
179 PFILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
180 ULONG RequiredLength;
181
182 if (Length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION)) {
183 Status = STATUS_BUFFER_OVERFLOW;
184 _SEH2_LEAVE;
185 }
186
187 FsAttrInfo =
188 (PFILE_FS_ATTRIBUTE_INFORMATION) Buffer;
189 FsAttrInfo->FileSystemAttributes = FILE_SUPPORTS_HARD_LINKS |
190 FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
191 FILE_SUPPORTS_REPARSE_POINTS | FILE_SUPPORTS_EXTENDED_ATTRIBUTES;
192 if (IsVcbReadOnly(Vcb)) {
193 FsAttrInfo->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
194 }
195 FsAttrInfo->MaximumComponentNameLength = EXT2_NAME_LEN;
196 FsAttrInfo->FileSystemNameLength = 8;
197
198 RequiredLength = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +
199 8 - sizeof(WCHAR);
200
201 if (Length < RequiredLength) {
202 Irp->IoStatus.Information =
203 sizeof(FILE_FS_ATTRIBUTE_INFORMATION);
204 Status = STATUS_BUFFER_OVERFLOW;
205 _SEH2_LEAVE;
206 }
207
208 if (IsFlagOn(SUPER_BLOCK->s_feature_incompat, EXT4_FEATURE_INCOMPAT_EXTENTS)) {
209 RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT4\0", 10);
210 } else if (Vcb->IsExt3fs) {
211 RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT3\0", 10);
212 } else {
213 RtlCopyMemory(FsAttrInfo->FileSystemName, L"EXT2\0", 10);
214 }
215
216 Irp->IoStatus.Information = RequiredLength;
217 Status = STATUS_SUCCESS;
218 }
219 break;
220
221 #if (_WIN32_WINNT >= 0x0500)
222
223 case FileFsFullSizeInformation:
224 {
225 PFILE_FS_FULL_SIZE_INFORMATION PFFFSI;
226
227 if (Length < sizeof(FILE_FS_FULL_SIZE_INFORMATION)) {
228 Status = STATUS_BUFFER_OVERFLOW;
229 _SEH2_LEAVE;
230 }
231
232 PFFFSI = (PFILE_FS_FULL_SIZE_INFORMATION) Buffer;
233
234 /*
235 typedef struct _FILE_FS_FULL_SIZE_INFORMATION {
236 LARGE_INTEGER TotalAllocationUnits;
237 LARGE_INTEGER CallerAvailableAllocationUnits;
238 LARGE_INTEGER ActualAvailableAllocationUnits;
239 ULONG SectorsPerAllocationUnit;
240 ULONG BytesPerSector;
241 } FILE_FS_FULL_SIZE_INFORMATION, *PFILE_FS_FULL_SIZE_INFORMATION;
242 */
243
244 {
245 PFFFSI->TotalAllocationUnits.QuadPart =
246 ext3_blocks_count(SUPER_BLOCK);
247
248 PFFFSI->CallerAvailableAllocationUnits.QuadPart =
249 ext3_free_blocks_count(SUPER_BLOCK);
250
251 /* - Vcb->SuperBlock->s_r_blocks_count; */
252 PFFFSI->ActualAvailableAllocationUnits.QuadPart =
253 ext3_free_blocks_count(SUPER_BLOCK);
254 }
255
256 PFFFSI->SectorsPerAllocationUnit =
257 Vcb->BlockSize / Vcb->DiskGeometry.BytesPerSector;
258
259 PFFFSI->BytesPerSector = Vcb->DiskGeometry.BytesPerSector;
260
261 Irp->IoStatus.Information = sizeof(FILE_FS_FULL_SIZE_INFORMATION);
262 Status = STATUS_SUCCESS;
263 }
264 break;
265
266 #endif // (_WIN32_WINNT >= 0x0500)
267
268 default:
269 Status = STATUS_INVALID_INFO_CLASS;
270 break;
271 }
272
273 } _SEH2_FINALLY {
274
275 if (VcbResourceAcquired) {
276 ExReleaseResourceLite(&Vcb->MainResource);
277 }
278
279 if (!IrpContext->ExceptionInProgress) {
280 if (Status == STATUS_PENDING) {
281 Ext2QueueRequest(IrpContext);
282 } else {
283 Ext2CompleteIrpContext(IrpContext, Status);
284 }
285 }
286 } _SEH2_END;
287
288 return Status;
289 }
290
291 NTSTATUS
292 Ext2SetVolumeInformation (IN PEXT2_IRP_CONTEXT IrpContext)
293 {
294 PDEVICE_OBJECT DeviceObject;
295 NTSTATUS Status = STATUS_UNSUCCESSFUL;
296 PEXT2_VCB Vcb = NULL;
297 PIRP Irp;
298 PIO_STACK_LOCATION IoStackLocation;
299 FS_INFORMATION_CLASS FsInformationClass;
300 BOOLEAN VcbResourceAcquired = FALSE;
301
302 _SEH2_TRY {
303
304 ASSERT(IrpContext != NULL);
305
306 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
307 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
308
309 DeviceObject = IrpContext->DeviceObject;
310
311 //
312 // This request is not allowed on the main device object
313 //
314 if (IsExt2FsDevice(DeviceObject)) {
315 Status = STATUS_INVALID_DEVICE_REQUEST;
316 _SEH2_LEAVE;
317 }
318
319 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
320 ASSERT(Vcb != NULL);
321 ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
322 (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
323 ASSERT(IsMounted(Vcb));
324
325 if (IsVcbReadOnly(Vcb)) {
326 Status = STATUS_MEDIA_WRITE_PROTECTED;
327 _SEH2_LEAVE;
328 }
329
330 if (!ExAcquireResourceExclusiveLite(
331 &Vcb->MainResource, TRUE)) {
332 Status = STATUS_PENDING;
333 _SEH2_LEAVE;
334 }
335 VcbResourceAcquired = TRUE;
336
337 Ext2VerifyVcb(IrpContext, Vcb);
338
339 Irp = IrpContext->Irp;
340 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
341
342 //Notes: SetVolume is not defined in ntddk.h of win2k ddk,
343 // But it's same to QueryVolume ....
344 FsInformationClass =
345 IoStackLocation->Parameters./*SetVolume*/QueryVolume.FsInformationClass;
346
347 switch (FsInformationClass) {
348
349 case FileFsLabelInformation:
350 {
351 PFILE_FS_LABEL_INFORMATION VolLabelInfo = NULL;
352 ULONG VolLabelLen;
353 UNICODE_STRING LabelName ;
354
355 OEM_STRING OemName;
356
357 VolLabelInfo = (PFILE_FS_LABEL_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
358 VolLabelLen = VolLabelInfo->VolumeLabelLength;
359
360 if (VolLabelLen > (16 * sizeof(WCHAR))) {
361 Status = STATUS_INVALID_VOLUME_LABEL;
362 _SEH2_LEAVE;
363 }
364
365 RtlCopyMemory( Vcb->Vpb->VolumeLabel,
366 VolLabelInfo->VolumeLabel,
367 VolLabelLen );
368
369 RtlZeroMemory(Vcb->SuperBlock->s_volume_name, 16);
370 LabelName.Buffer = VolLabelInfo->VolumeLabel;
371 LabelName.MaximumLength = (USHORT)16 * sizeof(WCHAR);
372 LabelName.Length = (USHORT)VolLabelLen;
373
374 OemName.Buffer = SUPER_BLOCK->s_volume_name;
375 OemName.Length = 0;
376 OemName.MaximumLength = 16;
377
378 Ext2UnicodeToOEM(Vcb, &OemName, &LabelName);
379 Vcb->Vpb->VolumeLabelLength = (USHORT) VolLabelLen;
380
381 if (Ext2SaveSuper(IrpContext, Vcb)) {
382 Status = STATUS_SUCCESS;
383 }
384
385 Irp->IoStatus.Information = 0;
386 }
387 break;
388
389 default:
390 Status = STATUS_INVALID_INFO_CLASS;
391 }
392
393 } _SEH2_FINALLY {
394
395 if (VcbResourceAcquired) {
396 ExReleaseResourceLite(&Vcb->MainResource);
397 }
398
399 if (!IrpContext->ExceptionInProgress) {
400 if (Status == STATUS_PENDING) {
401 Ext2QueueRequest(IrpContext);
402 } else {
403 Ext2CompleteIrpContext(IrpContext, Status);
404 }
405 }
406 } _SEH2_END;
407
408 return Status;
409 }