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