xref: /reactos/drivers/filesystems/cdfs/volinfo.c (revision 5c7ce447)
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 #ifdef __REACTOS__
164         RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, Length);
165 #endif // __REACTOS__
166 
167         switch (IrpSp->Parameters.QueryVolume.FsInformationClass) {
168 
169         case FileFsSizeInformation:
170 
171             Status = CdQueryFsSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
172             break;
173 
174         case FileFsVolumeInformation:
175 
176             Status = CdQueryFsVolumeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
177             break;
178 
179         case FileFsDeviceInformation:
180 
181             Status = CdQueryFsDeviceInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
182             break;
183 
184         case FileFsAttributeInformation:
185 
186             Status = CdQueryFsAttributeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
187             break;
188 
189 #if (NTDDI_VERSION >= NTDDI_WIN8)
190         case FileFsSectorSizeInformation:
191 
192             Status = CdQueryFsSectorSizeInfo( IrpContext, Fcb->Vcb, Irp->AssociatedIrp.SystemBuffer, &Length );
193             break;
194 #endif
195 
196         /* ReactOS Change: GCC "enumeration value not handled in switch" */
197         default: break;
198         }
199 
200         //
201         //  Set the information field to the number of bytes actually filled in
202         //
203 
204         Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
205 
206     } _SEH2_FINALLY {
207 
208         //
209         //  Release the Vcb.
210         //
211 
212         CdReleaseVcb( IrpContext, Fcb->Vcb );
213     } _SEH2_END;
214 
215     //
216     //  Complete the request if we didn't raise.
217     //
218 
219     CdCompleteRequest( IrpContext, Irp, Status );
220 
221     return Status;
222 }
223 
224 
225 //
226 //  Local support routine
227 //
228 
229 _Requires_lock_held_(_Global_critical_region_)
230 NTSTATUS
231 CdQueryFsVolumeInfo (
232     _In_ PIRP_CONTEXT IrpContext,
233     _In_ PVCB Vcb,
234     _Out_ PFILE_FS_VOLUME_INFORMATION Buffer,
235     _Inout_ PULONG Length
236     )
237 
238 /*++
239 
240 Routine Description:
241 
242     This routine implements the query volume info call
243 
244 Arguments:
245 
246     Vcb - Vcb for this volume.
247 
248     Buffer - Supplies a pointer to the output buffer where the information
249         is to be returned
250 
251     Length - Supplies the length of the buffer in byte.  This variable
252         upon return recieves the remaining bytes free in the buffer
253 
254 Return Value:
255 
256     NTSTATUS - Returns the status for the query
257 
258 --*/
259 
260 {
261     ULONG BytesToCopy;
262 
263     NTSTATUS Status = STATUS_SUCCESS;
264 
265     PAGED_CODE();
266 
267     UNREFERENCED_PARAMETER( IrpContext );
268 
269     //
270     //  Fill in the data from the Vcb.
271     //
272 
273     Buffer->VolumeCreationTime = *((PLARGE_INTEGER) &Vcb->VolumeDasdFcb->CreationTime);
274     Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
275 
276     Buffer->SupportsObjects = FALSE;
277 
278     *Length -= FIELD_OFFSET( FILE_FS_VOLUME_INFORMATION, VolumeLabel[0] );
279 
280     //
281     //  Check if the buffer we're given is long enough
282     //
283 
284     if (*Length >= (ULONG) Vcb->Vpb->VolumeLabelLength) {
285 
286         BytesToCopy = Vcb->Vpb->VolumeLabelLength;
287 
288     } else {
289 
290         BytesToCopy = *Length;
291 
292         Status = STATUS_BUFFER_OVERFLOW;
293     }
294 
295     //
296     //  Copy over what we can of the volume label, and adjust *Length
297     //
298 
299     Buffer->VolumeLabelLength = BytesToCopy;
300 
301     if (BytesToCopy) {
302 
303         RtlCopyMemory( &Buffer->VolumeLabel[0],
304                        &Vcb->Vpb->VolumeLabel[0],
305                        BytesToCopy );
306     }
307 
308     *Length -= BytesToCopy;
309 
310     //
311     //  Set our status and return to our caller
312     //
313 
314     return Status;
315 }
316 
317 
318 //
319 //  Local support routine
320 //
321 
322 NTSTATUS
323 CdQueryFsSizeInfo (
324     _In_ PIRP_CONTEXT IrpContext,
325     _In_ PVCB Vcb,
326     _Out_ PFILE_FS_SIZE_INFORMATION Buffer,
327     _Inout_ PULONG Length
328     )
329 
330 /*++
331 
332 Routine Description:
333 
334     This routine implements the query volume size call.
335 
336 Arguments:
337 
338     Vcb - Vcb for this volume.
339 
340     Buffer - Supplies a pointer to the output buffer where the information
341         is to be returned
342 
343     Length - Supplies the length of the buffer in byte.  This variable
344         upon return recieves the remaining bytes free in the buffer
345 
346 Return Value:
347 
348     NTSTATUS - Returns the status for the query
349 
350 --*/
351 
352 {
353     PAGED_CODE();
354 
355     UNREFERENCED_PARAMETER( IrpContext );
356 
357     //
358     //  Fill in the output buffer.
359     //
360 
361     Buffer->TotalAllocationUnits.QuadPart = LlSectorsFromBytes( Vcb->VolumeDasdFcb->AllocationSize.QuadPart );
362 
363     Buffer->AvailableAllocationUnits.QuadPart = 0;
364     Buffer->SectorsPerAllocationUnit = 1;
365     Buffer->BytesPerSector = SECTOR_SIZE;
366 
367     //
368     //  Adjust the length variable
369     //
370 
371     *Length -= sizeof( FILE_FS_SIZE_INFORMATION );
372 
373     //
374     //  And return success to our caller
375     //
376 
377     return STATUS_SUCCESS;
378 }
379 
380 
381 //
382 //  Local support routine
383 //
384 
385 NTSTATUS
386 CdQueryFsDeviceInfo (
387     _In_ PIRP_CONTEXT IrpContext,
388     _In_ PVCB Vcb,
389     _Out_ PFILE_FS_DEVICE_INFORMATION Buffer,
390     _Inout_ PULONG Length
391     )
392 
393 /*++
394 
395 Routine Description:
396 
397     This routine implements the query volume device call.
398 
399 Arguments:
400 
401     Vcb - Vcb for this volume.
402 
403     Buffer - Supplies a pointer to the output buffer where the information
404         is to be returned
405 
406     Length - Supplies the length of the buffer in byte.  This variable
407         upon return recieves the remaining bytes free in the buffer
408 
409 Return Value:
410 
411     NTSTATUS - Returns the status for the query
412 
413 --*/
414 
415 {
416     PAGED_CODE();
417 
418     UNREFERENCED_PARAMETER( IrpContext );
419 
420     //
421     //  Update the output buffer.
422     //
423 
424     Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
425 #ifndef __REACTOS__
426     Buffer->DeviceType = FILE_DEVICE_CD_ROM;
427 #else
428     Buffer->DeviceType = Vcb->TargetDeviceObject->DeviceType;
429 #endif
430 
431     //
432     //  Adjust the length variable
433     //
434 
435     *Length -= sizeof( FILE_FS_DEVICE_INFORMATION );
436 
437     //
438     //  And return success to our caller
439     //
440 
441     return STATUS_SUCCESS;
442 }
443 
444 
445 //
446 //  Local support routine
447 //
448 
449 NTSTATUS
450 CdQueryFsAttributeInfo (
451     _In_ PIRP_CONTEXT IrpContext,
452     _In_ PVCB Vcb,
453     _Out_ PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
454     _Inout_ PULONG Length
455     )
456 
457 /*++
458 
459 Routine Description:
460 
461     This routine implements the query volume attribute call.
462 
463 Arguments:
464 
465     Vcb - Vcb for this volume.
466 
467     Buffer - Supplies a pointer to the output buffer where the information
468         is to be returned
469 
470     Length - Supplies the length of the buffer in byte.  This variable
471         upon return recieves the remaining bytes free in the buffer
472 
473 Return Value:
474 
475     NTSTATUS - Returns the status for the query
476 
477 --*/
478 
479 {
480     ULONG BytesToCopy;
481 
482     NTSTATUS Status = STATUS_SUCCESS;
483 
484     PAGED_CODE();
485 
486     UNREFERENCED_PARAMETER( Vcb );
487 
488     //
489     //  Fill out the fixed portion of the buffer.
490     //
491 
492     Buffer->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH |
493                                    FILE_READ_ONLY_VOLUME |
494                                    FILE_SUPPORTS_OPEN_BY_FILE_ID;
495 
496     if (FlagOn( IrpContext->Vcb->VcbState, VCB_STATE_JOLIET )) {
497 
498         SetFlag( Buffer->FileSystemAttributes, FILE_UNICODE_ON_DISK );
499 
500         Buffer->MaximumComponentNameLength = 110;
501 
502     } else {
503 
504         Buffer->MaximumComponentNameLength = 221;
505     }
506 
507     *Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName );
508 
509     //
510     //  Make sure we can copy full unicode characters.
511     //
512 
513     ClearFlag( *Length, 1 );
514 
515     //
516     //  Determine how much of the file system name will fit.
517     //
518 
519     if (*Length >= 8) {
520 
521         BytesToCopy = 8;
522 
523     } else {
524 
525         BytesToCopy = *Length;
526         Status = STATUS_BUFFER_OVERFLOW;
527     }
528 
529     *Length -= BytesToCopy;
530 
531     //
532     //  Do the file system name.
533     //
534 
535     Buffer->FileSystemNameLength = BytesToCopy;
536 
537     RtlCopyMemory( &Buffer->FileSystemName[0], L"CDFS", BytesToCopy );
538 
539     //
540     //  And return to our caller
541     //
542 
543     return Status;
544 }
545 
546 #if (NTDDI_VERSION >= NTDDI_WIN8)
547 
548 NTSTATUS
549 CdQueryFsSectorSizeInfo (
550     _In_ PIRP_CONTEXT IrpContext,
551     _In_ PVCB Vcb,
552     _Out_writes_bytes_(*Length) PFILE_FS_SECTOR_SIZE_INFORMATION Buffer,
553     _Inout_ PULONG Length
554     )
555 
556 /*++
557 
558 Routine Description:
559 
560     This routine implements the query sector size information call
561     This operation will work on any handle and requires no privilege.
562 
563 Arguments:
564 
565     Vcb - Supplies the Vcb being queried
566 
567     Buffer - Supplies a pointer to the output buffer where the information
568         is to be returned
569 
570     Length - Supplies the length of the buffer in byte.  This variable
571         upon return receives the remaining bytes free in the buffer
572 
573 Return Value:
574 
575     NTSTATUS - Returns the status for the query
576 
577 --*/
578 
579 {
580     NTSTATUS Status;
581 
582     PAGED_CODE();
583     UNREFERENCED_PARAMETER( IrpContext );
584 
585     //
586     //  Sufficient buffer size is guaranteed by the I/O manager or the
587     //  originating kernel mode driver.
588     //
589 
590     ASSERT( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
591     _Analysis_assume_( *Length >= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION ));
592 
593     //
594     //  Retrieve the sector size information
595     //
596 
597     Status = FsRtlGetSectorSizeInformation( Vcb->Vpb->RealDevice,
598                                             Buffer );
599 
600     //
601     //  Adjust the length variable
602     //
603 
604     if (NT_SUCCESS( Status )) {
605 
606         *Length -= sizeof( FILE_FS_SECTOR_SIZE_INFORMATION );
607     }
608 
609     return Status;
610 }
611 
612 #endif
613 
614