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