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