xref: /reactos/drivers/filesystems/cdfs/volinfo.c (revision 50cf16b3)
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 #ifndef __REACTOS__
422     Buffer->DeviceType = FILE_DEVICE_CD_ROM;
423 #else
424     Buffer->DeviceType = Vcb->TargetDeviceObject->DeviceType;
425 #endif
426 
427     //
428     //  Adjust the length variable
429     //
430 
431     *Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
432 
433     //
434     //  And return success to our caller
435     //
436 
437     return STATUS_SUCCESS;
438 }
439 
440 
441 //
442 //  Local support routine
443 //
444 
445 NTSTATUS
446 CdQueryFsAttributeInfo (
447     _In_ PIRP_CONTEXT IrpContext,
448     _In_ PVCB Vcb,
449     _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
450     _Inout_ PULONG Length
451     )
452 
453 /*++
454 
455 Routine Description:
456 
457     This routine implements the query volume attribute call.
458 
459 Arguments:
460 
461     Vcb - Vcb for this volume.
462 
463     Buffer - Supplies a pointer to the output buffer where the information
464         is to be returned
465 
466     Length - Supplies the length of the buffer in byte.  This variable
467         upon return recieves the remaining bytes free in the buffer
468 
469 Return Value:
470 
471     NTSTATUS - Returns the status for the query
472 
473 --*/
474 
475 {
476     ULONG BytesToCopy;
477 
478     NTSTATUS Status = STATUS_SUCCESS;
479 
480     PAGED_CODE();
481 
482     UNREFERENCED_PARAMETER( Vcb );
483 
484     //
485     //  Fill out the fixed portion of the buffer.
486     //
487 
488     Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
489                                    FILE_READ_ONLY_VOLUME |
490                                    FILE_SUPPORTS_OPEN_BY_FILE_ID;
491 
492     if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
493 
494         SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );
495 
496         Buffer->MaximumComponentNameLength = 110;
497 
498     } else {
499 
500         Buffer->MaximumComponentNameLength = 221;
501     }
502 
503     *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
504 
505     //
506     //  Make sure we can copy full unicode characters.
507     //
508 
509     ClearFlag( *Length, 1 );
510 
511     //
512     //  Determine how much of the file system name will fit.
513     //
514 
515     if (*Length >= 8) {
516 
517         BytesToCopy = 8;
518 
519     } else {
520 
521         BytesToCopy = *Length;
522         Status = STATUS_BUFFER_OVERFLOW;
523     }
524 
525     *Length -= BytesToCopy;
526 
527     //
528     //  Do the file system name.
529     //
530 
531     Buffer->FileSystemNameLength = BytesToCopy;
532 
533     RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );
534 
535     //
536     //  And return to our caller
537     //
538 
539     return Status;
540 }
541 
542 #if (NTDDI_VERSION >= NTDDI_WIN8)
543 
544 NTSTATUS
545 CdQueryFsSectorSizeInfo (
546     _In_ PIRP_CONTEXT IrpContext,
547     _In_ PVCB Vcb,
548     _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
549     _Inout_ PULONG Length
550     )
551 
552 /*++
553 
554 Routine Description:
555 
556     This routine implements the query sector size information call
557     This operation will work on any handle and requires no privilege.
558 
559 Arguments:
560 
561     Vcb - Supplies the Vcb being queried
562 
563     Buffer - Supplies a pointer to the output buffer where the information
564         is to be returned
565 
566     Length - Supplies the length of the buffer in byte.  This variable
567         upon return receives the remaining bytes free in the buffer
568 
569 Return Value:
570 
571     NTSTATUS - Returns the status for the query
572 
573 --*/
574 
575 {
576     NTSTATUS Status;
577 
578     PAGED_CODE();
579     UNREFERENCED_PARAMETER( IrpContext );
580 
581     //
582     //  Sufficient buffer size is guaranteed by the I/O manager or the
583     //  originating kernel mode driver.
584     //
585 
586     ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
587     _Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
588 
589     //
590     //  Retrieve the sector size information
591     //
592 
593     Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice,
594                                             Buffer );
595 
596     //
597     //  Adjust the length variable
598     //
599 
600     if (NT_SUCCESS( Status )) {
601 
602         *Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION );
603     }
604 
605     return Status;
606 }
607 
608 #endif
609 
610