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