6640fd8aebe9311dc0b009c7f8923ffa12c6ac1b
[reactos.git] / drivers / filesystems / cdfs_new / volinfo.c
1 /*++
2
3 Copyright (c) 1989-2000 Microsoft Corporation
4
5 Module Name:
6
7 VolInfo.c
8
9 Abstract:
10
11 This module implements the volume information routines for Cdfs called by
12 the dispatch driver.
13
14
15 --*/
16
17 #include "CdProcs.h"
18
19 //
20 // The Bug check file id for this module
21 //
22
23 #define BugCheckFileId (CDFS_BUG_CHECK_VOLINFO)
24
25 //
26 // Local support routines
27 //
28
29 _Requires_lock_held_(_Global_critical_region_)
30 NTSTATUS
31 CdQueryFsVolumeInfo (
32 _In_ PIRP_CONTEXT IrpContext,
33 _In_ PVCB Vcb,
34 _Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
35 _Inout_ PULONG Length
36 );
37
38 NTSTATUS
39 CdQueryFsSizeInfo (
40 _In_ PIRP_CONTEXT IrpContext,
41 _In_ PVCB Vcb,
42 _Out_ PFILE_FS_SIZE_INFORMATION Buffer,
43 _Inout_ PULONG Length
44 );
45
46 NTSTATUS
47 CdQueryFsDeviceInfo (
48 _In_ PIRP_CONTEXT IrpContext,
49 _In_ PVCB Vcb,
50 _Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
51 _Inout_ PULONG Length
52 );
53
54 NTSTATUS
55 CdQueryFsAttributeInfo (
56 _In_ PIRP_CONTEXT IrpContext,
57 _In_ PVCB Vcb,
58 _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
59 _Inout_ PULONG Length
60 );
61
62 NTSTATUS
63 CdQueryFsSectorSizeInfo (
64 _In_ PIRP_CONTEXT IrpContext,
65 _In_ PVCB Vcb,
66 _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
67 _Inout_ PULONG Length
68 );
69
70 #ifdef ALLOC_PRAGMA
71 #pragma alloc_text(PAGE, CdCommonQueryVolInfo)
72 #pragma alloc_text(PAGE, CdQueryFsAttributeInfo)
73 #pragma alloc_text(PAGE, CdQueryFsDeviceInfo)
74 #pragma alloc_text(PAGE, CdQueryFsSizeInfo)
75 #pragma alloc_text(PAGE, CdQueryFsVolumeInfo)
76 #pragma alloc_text(PAGE, CdQueryFsSectorSizeInfo)
77 #endif
78
79 \f
80 _Requires_lock_held_(_Global_critical_region_)
81 NTSTATUS
82 CdCommonQueryVolInfo (
83 _Inout_ PIRP_CONTEXT IrpContext,
84 _Inout_ PIRP Irp
85 )
86
87 /*++
88
89 Routine Description:
90
91 This is the common routine for querying volume information called by both
92 the fsd and fsp threads.
93
94 Arguments:
95
96 Irp - Supplies the Irp being processed
97
98 Return Value:
99
100 NTSTATUS - The return status for the operation
101
102 --*/
103
104 {
105 NTSTATUS Status = STATUS_INVALID_PARAMETER;
106 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
107
108 ULONG Length;
109
110 TYPE_OF_OPEN TypeOfOpen;
111 PFCB Fcb;
112 PCCB Ccb;
113
114 PAGED_CODE();
115
116 //
117 // Reference our input parameters to make things easier
118 //
119
120 Length = IrpSp->Parameters.QueryVolume.Length;
121
122 //
123 // Decode the file object and fail if this an unopened file object.
124 //
125
126 TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
127
128 if (TypeOfOpen == UnopenedFileObject) {
129
130 CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
131 return STATUS_INVALID_PARAMETER;
132 }
133
134 //
135 // Acquire the Vcb for this volume.
136 //
137
138 CdAcquireVcbShared( IrpContext, Fcb->Vcb, FALSE );
139
140 //
141 // Use a try-finally to facilitate cleanup.
142 //
143
144 try {
145
146 //
147 // Verify the Vcb.
148 //
149
150 CdVerifyVcb( IrpContext, Fcb->Vcb );
151
152 //
153 // Based on the information class we'll do different actions. Each
154 // of the procedures that we're calling fills up the output buffer
155 // if possible and returns true if it successfully filled the buffer
156 // and false if it couldn't wait for any I/O to complete.
157 //
158
159 switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
160
161 case FileFsSizeInformation:
162
163 Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
164 break;
165
166 case FileFsVolumeInformation:
167
168 Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
169 break;
170
171 case FileFsDeviceInformation:
172
173 Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
174 break;
175
176 case FileFsAttributeInformation:
177
178 Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
179 break;
180
181 #if (NTDDI_VERSION >= NTDDI_WIN8)
182 case FileFsSectorSizeInformation:
183
184 Status = CdQueryFsSectorSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
185 break;
186 #endif
187 }
188
189 //
190 // Set the information field to the number of bytes actually filled in
191 //
192
193 Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
194
195 } finally {
196
197 //
198 // Release the Vcb.
199 //
200
201 CdReleaseVcb( IrpContext, Fcb->Vcb );
202 }
203
204 //
205 // Complete the request if we didn't raise.
206 //
207
208 CdCompleteRequest( IrpContext, Irp, Status );
209
210 return Status;
211 }
212
213 \f
214 //
215 // Local support routine
216 //
217
218 _Requires_lock_held_(_Global_critical_region_)
219 NTSTATUS
220 CdQueryFsVolumeInfo (
221 _In_ PIRP_CONTEXT IrpContext,
222 _In_ PVCB Vcb,
223 _Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
224 _Inout_ PULONG Length
225 )
226
227 /*++
228
229 Routine Description:
230
231 This routine implements the query volume info call
232
233 Arguments:
234
235 Vcb - Vcb for this volume.
236
237 Buffer - Supplies a pointer to the output buffer where the information
238 is to be returned
239
240 Length - Supplies the length of the buffer in byte. This variable
241 upon return recieves the remaining bytes free in the buffer
242
243 Return Value:
244
245 NTSTATUS - Returns the status for the query
246
247 --*/
248
249 {
250 ULONG BytesToCopy;
251
252 NTSTATUS Status = STATUS_SUCCESS;
253
254 PAGED_CODE();
255
256 UNREFERENCED_PARAMETER( IrpContext );
257
258 //
259 // Fill in the data from the Vcb.
260 //
261
262 Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime);
263 Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
264
265 Buffer->SupportsObjects = FALSE;
266
267 *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
268
269 //
270 // Check if the buffer we're given is long enough
271 //
272
273 if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) {
274
275 BytesToCopy = Vcb->Vpb->VolumeLabelLength;
276
277 } else {
278
279 BytesToCopy = *Length;
280
281 Status = STATUS_BUFFER_OVERFLOW;
282 }
283
284 //
285 // Copy over what we can of the volume label, and adjust *Length
286 //
287
288 Buffer->VolumeLabelLength = BytesToCopy;
289
290 if (BytesToCopy) {
291
292 RtlCopyMemory( &Buffer->VolumeLabel[0],
293 &Vcb->Vpb->VolumeLabel[0],
294 BytesToCopy );
295 }
296
297 *Length -= BytesToCopy;
298
299 //
300 // Set our status and return to our caller
301 //
302
303 return Status;
304 }
305
306 \f
307 //
308 // Local support routine
309 //
310
311 NTSTATUS
312 CdQueryFsSizeInfo (
313 _In_ PIRP_CONTEXT IrpContext,
314 _In_ PVCB Vcb,
315 _Out_ PFILE_FS_SIZE_INFORMATION Buffer,
316 _Inout_ PULONG Length
317 )
318
319 /*++
320
321 Routine Description:
322
323 This routine implements the query volume size call.
324
325 Arguments:
326
327 Vcb - Vcb for this volume.
328
329 Buffer - Supplies a pointer to the output buffer where the information
330 is to be returned
331
332 Length - Supplies the length of the buffer in byte. This variable
333 upon return recieves the remaining bytes free in the buffer
334
335 Return Value:
336
337 NTSTATUS - Returns the status for the query
338
339 --*/
340
341 {
342 PAGED_CODE();
343
344 UNREFERENCED_PARAMETER( IrpContext );
345
346 //
347 // Fill in the output buffer.
348 //
349
350 Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart );
351
352 Buffer->AvailableAllocationUnits.QuadPart = 0;
353 Buffer->SectorsPerAllocationUnit = 1;
354 Buffer->BytesPerSector = SECTOR_SIZE;
355
356 //
357 // Adjust the length variable
358 //
359
360 *Length -= sizeof( FILE_FS_SIZE_INFORMATION );
361
362 //
363 // And return success to our caller
364 //
365
366 return STATUS_SUCCESS;
367 }
368
369 \f
370 //
371 // Local support routine
372 //
373
374 NTSTATUS
375 CdQueryFsDeviceInfo (
376 _In_ PIRP_CONTEXT IrpContext,
377 _In_ PVCB Vcb,
378 _Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
379 _Inout_ PULONG Length
380 )
381
382 /*++
383
384 Routine Description:
385
386 This routine implements the query volume device call.
387
388 Arguments:
389
390 Vcb - Vcb for this volume.
391
392 Buffer - Supplies a pointer to the output buffer where the information
393 is to be returned
394
395 Length - Supplies the length of the buffer in byte. This variable
396 upon return recieves the remaining bytes free in the buffer
397
398 Return Value:
399
400 NTSTATUS - Returns the status for the query
401
402 --*/
403
404 {
405 PAGED_CODE();
406
407 UNREFERENCED_PARAMETER( IrpContext );
408
409 //
410 // Update the output buffer.
411 //
412
413 Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
414 Buffer->DeviceType = FILE_DEVICE_CD_ROM;
415
416 //
417 // Adjust the length variable
418 //
419
420 *Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
421
422 //
423 // And return success to our caller
424 //
425
426 return STATUS_SUCCESS;
427 }
428
429 \f
430 //
431 // Local support routine
432 //
433
434 NTSTATUS
435 CdQueryFsAttributeInfo (
436 _In_ PIRP_CONTEXT IrpContext,
437 _In_ PVCB Vcb,
438 _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
439 _Inout_ PULONG Length
440 )
441
442 /*++
443
444 Routine Description:
445
446 This routine implements the query volume attribute call.
447
448 Arguments:
449
450 Vcb - Vcb for this volume.
451
452 Buffer - Supplies a pointer to the output buffer where the information
453 is to be returned
454
455 Length - Supplies the length of the buffer in byte. This variable
456 upon return recieves the remaining bytes free in the buffer
457
458 Return Value:
459
460 NTSTATUS - Returns the status for the query
461
462 --*/
463
464 {
465 ULONG BytesToCopy;
466
467 NTSTATUS Status = STATUS_SUCCESS;
468
469 PAGED_CODE();
470
471 UNREFERENCED_PARAMETER( Vcb );
472
473 //
474 // Fill out the fixed portion of the buffer.
475 //
476
477 Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
478 FILE_READ_ONLY_VOLUME |
479 FILE_SUPPORTS_OPEN_BY_FILE_ID;
480
481 if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
482
483 SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );
484
485 Buffer->MaximumComponentNameLength = 110;
486
487 } else {
488
489 Buffer->MaximumComponentNameLength = 221;
490 }
491
492 *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
493
494 //
495 // Make sure we can copy full unicode characters.
496 //
497
498 ClearFlag( *Length, 1 );
499
500 //
501 // Determine how much of the file system name will fit.
502 //
503
504 if (*Length >= 8) {
505
506 BytesToCopy = 8;
507
508 } else {
509
510 BytesToCopy = *Length;
511 Status = STATUS_BUFFER_OVERFLOW;
512 }
513
514 *Length -= BytesToCopy;
515
516 //
517 // Do the file system name.
518 //
519
520 Buffer->FileSystemNameLength = BytesToCopy;
521
522 RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );
523
524 //
525 // And return to our caller
526 //
527
528 return Status;
529 }
530
531 #if (NTDDI_VERSION >= NTDDI_WIN8)
532
533 NTSTATUS
534 CdQueryFsSectorSizeInfo (
535 _In_ PIRP_CONTEXT IrpContext,
536 _In_ PVCB Vcb,
537 _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
538 _Inout_ PULONG Length
539 )
540
541 /*++
542
543 Routine Description:
544
545 This routine implements the query sector size information call
546 This operation will work on any handle and requires no privilege.
547
548 Arguments:
549
550 Vcb - Supplies the Vcb being queried
551
552 Buffer - Supplies a pointer to the output buffer where the information
553 is to be returned
554
555 Length - Supplies the length of the buffer in byte. This variable
556 upon return receives the remaining bytes free in the buffer
557
558 Return Value:
559
560 NTSTATUS - Returns the status for the query
561
562 --*/
563
564 {
565 NTSTATUS Status;
566
567 PAGED_CODE();
568 UNREFERENCED_PARAMETER( IrpContext );
569
570 //
571 // Sufficient buffer size is guaranteed by the I/O manager or the
572 // originating kernel mode driver.
573 //
574
575 ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
576 _Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
577
578 //
579 // Retrieve the sector size information
580 //
581
582 Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice,
583 Buffer );
584
585 //
586 // Adjust the length variable
587 //
588
589 if (NT_SUCCESS( Status )) {
590
591 *Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION );
592 }
593
594 return Status;
595 }
596
597 #endif
598