1 //////////////////////////////////////////////////////////////////// 2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3 // All rights reserved 4 // This file was released under the GPLv2 on June 2015. 5 //////////////////////////////////////////////////////////////////// 6 /* 7 8 Module Name: FsCntrl.cpp 9 10 Abstract: 11 12 Contains code to handle the "File System IOCTL" dispatch entry point. 13 14 Environment: 15 16 Kernel mode only 17 18 */ 19 20 #include "udffs.h" 21 22 // define the file specific bug-check id 23 #define UDF_BUG_CHECK_ID UDF_FILE_FS_CONTROL 24 25 NTSTATUS UDFBlankMount(IN PVCB Vcb); 26 27 PDIR_INDEX_HDR UDFDirIndexAlloc(IN uint_di i); 28 29 /* 30 Function: UDFFSControl() 31 32 Description: 33 The I/O Manager will invoke this routine to handle a File System 34 Control request (this is IRP_MJ_FILE_SYSTEM_CONTROL dispatch point) 35 36 */ 37 NTSTATUS 38 NTAPI 39 UDFFSControl( 40 PDEVICE_OBJECT DeviceObject, // the logical volume device object 41 PIRP Irp // I/O Request Packet 42 ) 43 { 44 NTSTATUS RC = STATUS_SUCCESS; 45 PtrUDFIrpContext PtrIrpContext; 46 BOOLEAN AreWeTopLevel = FALSE; 47 48 UDFPrint(("\nUDFFSControl: \n\n")); 49 50 FsRtlEnterFileSystem(); 51 ASSERT(DeviceObject); 52 ASSERT(Irp); 53 54 // set the top level context 55 AreWeTopLevel = UDFIsIrpTopLevel(Irp); 56 57 _SEH2_TRY { 58 59 // get an IRP context structure and issue the request 60 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject); 61 if(PtrIrpContext) { 62 RC = UDFCommonFSControl(PtrIrpContext, Irp); 63 } else { 64 RC = STATUS_INSUFFICIENT_RESOURCES; 65 Irp->IoStatus.Status = RC; 66 Irp->IoStatus.Information = 0; 67 // complete the IRP 68 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 69 } 70 71 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) { 72 73 UDFPrintErr(("UDFFSControl: exception ***")); 74 RC = UDFExceptionHandler(PtrIrpContext, Irp); 75 76 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC); 77 } _SEH2_END; 78 79 if(AreWeTopLevel) { 80 IoSetTopLevelIrp(NULL); 81 } 82 83 FsRtlExitFileSystem(); 84 85 return(RC); 86 } // end UDFFSControl() 87 88 /* 89 Function: UDFCommonFSControl() 90 91 Description: 92 The actual work is performed here. 93 94 Expected Interrupt Level (for execution) : 95 IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution 96 to be deferred to a worker thread context) 97 98 Return Value: STATUS_SUCCESS/Error 99 */ 100 101 NTSTATUS 102 NTAPI 103 UDFCommonFSControl( 104 PtrUDFIrpContext PtrIrpContext, 105 PIRP Irp // I/O Request Packet 106 ) 107 { 108 NTSTATUS RC = STATUS_UNRECOGNIZED_VOLUME; 109 PIO_STACK_LOCATION IrpSp = NULL; 110 // PDEVICE_OBJECT PtrTargetDeviceObject = NULL; 111 112 UDFPrint(("\nUDFCommonFSControl\n\n")); 113 // BrutePoint(); 114 115 _SEH2_TRY { 116 117 IrpSp = IoGetCurrentIrpStackLocation(Irp); 118 ASSERT(IrpSp); 119 120 switch ((IrpSp)->MinorFunction) 121 { 122 case IRP_MN_USER_FS_REQUEST: 123 UDFPrint((" UDFFSControl: UserFsReq request ....\n")); 124 125 RC = UDFUserFsCtrlRequest(PtrIrpContext,Irp); 126 break; 127 case IRP_MN_MOUNT_VOLUME: 128 129 UDFPrint((" UDFFSControl: MOUNT_VOLUME request ....\n")); 130 131 RC = UDFMountVolume(PtrIrpContext,Irp); 132 break; 133 case IRP_MN_VERIFY_VOLUME: 134 135 UDFPrint((" UDFFSControl: VERIFY_VOLUME request ....\n")); 136 137 RC = UDFVerifyVolume(Irp); 138 break; 139 default: 140 UDFPrintErr((" UDFFSControl: STATUS_INVALID_DEVICE_REQUEST MinorFunction %x\n", (IrpSp)->MinorFunction)); 141 RC = STATUS_INVALID_DEVICE_REQUEST; 142 143 Irp->IoStatus.Status = RC; 144 Irp->IoStatus.Information = 0; 145 // complete the IRP 146 IoCompleteRequest(Irp, IO_DISK_INCREMENT); 147 break; 148 } 149 150 //try_exit: NOTHING; 151 } _SEH2_FINALLY { 152 if (!_SEH2_AbnormalTermination()) { 153 // Free up the Irp Context 154 UDFPrint((" UDFCommonFSControl: finally\n")); 155 UDFReleaseIrpContext(PtrIrpContext); 156 } else { 157 UDFPrint((" UDFCommonFSControl: finally after exception ***\n")); 158 } 159 } _SEH2_END; 160 161 return(RC); 162 } // end UDFCommonFSControl() 163 164 /* 165 Routine Description: 166 This is the common routine for implementing the user's requests made 167 through NtFsControlFile. 168 169 Arguments: 170 Irp - Supplies the Irp being processed 171 172 Return Value: 173 NTSTATUS - The return status for the operation 174 175 */ 176 NTSTATUS 177 NTAPI 178 UDFUserFsCtrlRequest( 179 PtrUDFIrpContext IrpContext, 180 PIRP Irp 181 ) 182 { 183 NTSTATUS RC; 184 PEXTENDED_IO_STACK_LOCATION IrpSp = (PEXTENDED_IO_STACK_LOCATION) IoGetCurrentIrpStackLocation( Irp ); 185 186 // Case on the control code. 187 switch ( IrpSp->Parameters.FileSystemControl.FsControlCode ) { 188 189 case FSCTL_REQUEST_OPLOCK_LEVEL_1 : 190 case FSCTL_REQUEST_OPLOCK_LEVEL_2 : 191 case FSCTL_REQUEST_BATCH_OPLOCK : 192 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE : 193 case FSCTL_OPBATCH_ACK_CLOSE_PENDING : 194 case FSCTL_OPLOCK_BREAK_NOTIFY : 195 case FSCTL_OPLOCK_BREAK_ACK_NO_2 : 196 case FSCTL_REQUEST_FILTER_OPLOCK : 197 198 UDFPrint(("UDFUserFsCtrlRequest: OPLOCKS\n")); 199 RC = STATUS_INVALID_DEVICE_REQUEST; 200 201 Irp->IoStatus.Information = 0; 202 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 203 break; 204 /* 205 RC = UDFOplockRequest( IrpContext, Irp ); 206 break; 207 */ 208 case FSCTL_INVALIDATE_VOLUMES : 209 210 RC = UDFInvalidateVolumes( IrpContext, Irp ); 211 break; 212 /* 213 case FSCTL_MOVE_FILE: 214 215 case FSCTL_QUERY_ALLOCATED_RANGES: 216 case FSCTL_SET_ZERO_DATA: 217 case FSCTL_SET_SPARSE: 218 219 case FSCTL_MARK_VOLUME_DIRTY: 220 221 RC = UDFDirtyVolume( IrpContext, Irp ); 222 break; 223 224 */ 225 case FSCTL_IS_VOLUME_DIRTY: 226 227 RC = UDFIsVolumeDirty(IrpContext, Irp); 228 break; 229 230 case FSCTL_ALLOW_EXTENDED_DASD_IO: 231 232 UDFPrint(("UDFUserFsCtrlRequest: FSCTL_ALLOW_EXTENDED_DASD_IO\n")); 233 // DASD i/o is always permitted 234 // So, no-op this call 235 RC = STATUS_SUCCESS; 236 237 Irp->IoStatus.Information = 0; 238 Irp->IoStatus.Status = STATUS_SUCCESS; 239 break; 240 241 case FSCTL_DISMOUNT_VOLUME: 242 243 RC = UDFDismountVolume( IrpContext, Irp ); 244 break; 245 246 case FSCTL_IS_VOLUME_MOUNTED: 247 248 RC = UDFIsVolumeMounted( IrpContext, Irp ); 249 break; 250 251 case FSCTL_FILESYSTEM_GET_STATISTICS: 252 253 RC = UDFGetStatistics( IrpContext, Irp ); 254 break; 255 256 case FSCTL_LOCK_VOLUME: 257 258 RC = UDFLockVolume( IrpContext, Irp ); 259 break; 260 261 case FSCTL_UNLOCK_VOLUME: 262 263 RC = UDFUnlockVolume( IrpContext, Irp ); 264 break; 265 266 case FSCTL_IS_PATHNAME_VALID: 267 268 RC = UDFIsPathnameValid( IrpContext, Irp ); 269 break; 270 271 case FSCTL_GET_VOLUME_BITMAP: 272 273 UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_VOLUME_BITMAP\n")); 274 RC = UDFGetVolumeBitmap( IrpContext, Irp ); 275 break; 276 277 case FSCTL_GET_RETRIEVAL_POINTERS: 278 279 UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_RETRIEVAL_POINTERS\n")); 280 RC = UDFGetRetrievalPointers( IrpContext, Irp, 0 ); 281 break; 282 283 284 // We don't support any of the known or unknown requests. 285 default: 286 287 UDFPrintErr(("UDFUserFsCtrlRequest: STATUS_INVALID_DEVICE_REQUEST for %x\n", 288 IrpSp->Parameters.FileSystemControl.FsControlCode)); 289 RC = STATUS_INVALID_DEVICE_REQUEST; 290 291 Irp->IoStatus.Information = 0; 292 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 293 break; 294 } 295 296 IoCompleteRequest(Irp,IO_DISK_INCREMENT); 297 return RC; 298 299 } // end UDFUserFsCtrlRequest() 300 301 302 /* 303 Routine Description: 304 This is the common routine for implementing the mount requests 305 306 Arguments: 307 Irp - Supplies the Irp being processed 308 309 Return Value: 310 NTSTATUS - The return status for the operation 311 312 */ 313 NTSTATUS 314 NTAPI 315 UDFMountVolume( 316 IN PtrUDFIrpContext PtrIrpContext, 317 IN PIRP Irp 318 ) 319 { 320 NTSTATUS RC; 321 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); 322 PDEVICE_OBJECT TargetDeviceObject = NULL; 323 PFILTER_DEV_EXTENSION filterDevExt; 324 PDEVICE_OBJECT fsDeviceObject; 325 PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb; 326 PVCB Vcb = NULL; 327 // PVCB OldVcb = NULL; 328 PDEVICE_OBJECT VolDo = NULL; 329 IO_STATUS_BLOCK Iosb; 330 ULONG MediaChangeCount = 0; 331 ULONG Characteristics; 332 DEVICE_TYPE FsDeviceType; 333 BOOLEAN RestoreDoVerify = FALSE; 334 BOOLEAN WrongMedia = FALSE; 335 BOOLEAN RemovableMedia = TRUE; 336 BOOLEAN CompleteIrp = FALSE; 337 ULONG Mode; 338 TEST_UNIT_READY_USER_OUT TestUnitReadyBuffer; 339 ULONG i; 340 LARGE_INTEGER delay; 341 BOOLEAN VcbAcquired = FALSE; 342 BOOLEAN DeviceNotTouched = TRUE; 343 BOOLEAN Locked = FALSE; 344 int8* ioBuf = NULL; 345 346 ASSERT(IrpSp); 347 UDFPrint(("\n !!! UDFMountVolume\n")); 348 // UDFPrint(("Build " VER_STR_PRODUCT "\n\n")); 349 350 fsDeviceObject = PtrIrpContext->TargetDeviceObject; 351 UDFPrint(("Mount on device object %x\n", fsDeviceObject)); 352 filterDevExt = (PFILTER_DEV_EXTENSION)fsDeviceObject->DeviceExtension; 353 if (filterDevExt->NodeIdentifier.NodeType == UDF_NODE_TYPE_FILTER_DEVOBJ && 354 filterDevExt->NodeIdentifier.NodeSize == sizeof(FILTER_DEV_EXTENSION)) { 355 CompleteIrp = FALSE; 356 } else 357 if (filterDevExt->NodeIdentifier.NodeType == UDF_NODE_TYPE_UDFFS_DEVOBJ && 358 filterDevExt->NodeIdentifier.NodeSize == sizeof(UDFFS_DEV_EXTENSION)) { 359 CompleteIrp = TRUE; 360 } else { 361 UDFPrintErr(("Invalid node type in FS or FILTER DeviceObject\n")); 362 ASSERT(FALSE); 363 } 364 // Get a pointer to the target physical/virtual device object. 365 TargetDeviceObject = IrpSp->Parameters.MountVolume.DeviceObject; 366 367 if(((Characteristics = TargetDeviceObject->Characteristics) & FILE_FLOPPY_DISKETTE) || 368 (UDFGlobalData.UDFFlags & UDF_DATA_FLAGS_BEING_UNLOADED) ) { 369 WrongMedia = TRUE; 370 } else { 371 RemovableMedia = (Characteristics & FILE_REMOVABLE_MEDIA) ? TRUE : FALSE; 372 if(TargetDeviceObject->DeviceType != FILE_DEVICE_CD_ROM) { 373 if(UDFGetRegParameter(NULL, REG_MOUNT_ON_CDONLY_NAME, TRUE)) { 374 WrongMedia = TRUE; 375 } 376 } 377 if(TargetDeviceObject->DeviceType == FILE_DEVICE_CD_ROM) { 378 FsDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM; 379 #ifdef UDF_HDD_SUPPORT 380 } else 381 if (TargetDeviceObject->DeviceType == FILE_DEVICE_DISK) { 382 if(RemovableMedia) { 383 if(!UDFGetRegParameter(NULL, REG_MOUNT_ON_ZIP_NAME, FALSE)) { 384 WrongMedia = TRUE; 385 } 386 } else { 387 if(!UDFGetRegParameter(NULL, REG_MOUNT_ON_HDD_NAME, FALSE)) { 388 WrongMedia = TRUE; 389 } 390 } 391 FsDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM; 392 #endif //UDF_HDD_SUPPORT 393 } else { 394 WrongMedia = TRUE; 395 } 396 } 397 398 // Acquire GlobalDataResource 399 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE); 400 401 _SEH2_TRY { 402 403 UDFScanForDismountedVcb(PtrIrpContext); 404 405 if(WrongMedia) try_return(RC = STATUS_UNRECOGNIZED_VOLUME); 406 407 if(RemovableMedia) { 408 UDFPrint(("UDFMountVolume: removable media\n")); 409 // just remember current MediaChangeCount 410 // or fail if No Media .... 411 412 // experimental CHECK_VERIFY, for fucking BENQ DVD_DD_1620 413 414 // Now we can get device state via GET_EVENT (if supported) 415 // or still one TEST_UNIT_READY command 416 RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY, 417 TargetDeviceObject, 418 NULL,0, 419 &MediaChangeCount,sizeof(ULONG), 420 FALSE,&Iosb ); 421 422 // Send TEST_UNIT_READY comment 423 // This can spin-up or wake-up the device 424 if(UDFGetRegParameter(NULL, UDF_WAIT_CD_SPINUP, TRUE)) { 425 delay.QuadPart = -15000000LL; // 1.5 sec 426 for(i=0; i<UDF_READY_MAX_RETRY; i++) { 427 // Use device default ready timeout 428 Mode = 0; 429 RC = UDFPhSendIOCTL( IOCTL_CDRW_TEST_UNIT_READY, 430 TargetDeviceObject, 431 &Mode,sizeof(Mode), 432 &TestUnitReadyBuffer,sizeof(TEST_UNIT_READY_USER_OUT), 433 FALSE,NULL); 434 UDFPrint(("UDFMountVolume: TEST_UNIT_READY %x\n", RC)); 435 if(!NT_SUCCESS(RC)) 436 break; 437 if(TestUnitReadyBuffer.SenseKey == SCSI_SENSE_NOT_READY && 438 TestUnitReadyBuffer.AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY && 439 TestUnitReadyBuffer.AdditionalSenseCodeQualifier == SCSI_SENSEQ_BECOMING_READY) { 440 UDFPrint(("UDFMountVolume: retry\n")); 441 KeDelayExecutionThread(KernelMode, FALSE, &delay); 442 //delay.QuadPart -= 10000000LL; // 1.0 sec 443 } else { 444 break; 445 } 446 } 447 if(i) { 448 UDFPrint(("UDFMountVolume: additional delay 3 sec\n")); 449 delay.QuadPart = -30000000LL; // 3.0 sec 450 KeDelayExecutionThread(KernelMode, FALSE, &delay); 451 } 452 } 453 454 // Now we can get device state via GET_EVENT (if supported) 455 // or still one TEST_UNIT_READY command 456 RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY, 457 TargetDeviceObject, 458 NULL,0, 459 &MediaChangeCount,sizeof(ULONG), 460 FALSE,&Iosb ); 461 462 if(RC == STATUS_IO_DEVICE_ERROR) { 463 UDFPrint(("UDFMountVolume: retry check verify\n")); 464 RC = UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY, 465 TargetDeviceObject, 466 NULL,0, 467 &MediaChangeCount,sizeof(ULONG), 468 FALSE,&Iosb ); 469 } 470 471 if(!NT_SUCCESS(RC) && (RC != STATUS_VERIFY_REQUIRED)) 472 try_return(RC); 473 474 // Be safe about the count in case the driver didn't fill it in 475 if(Iosb.Information != sizeof(ULONG)) { 476 MediaChangeCount = 0; 477 } 478 479 if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) { 480 // Check if device is busy before locking tray and performing 481 // further geomentry discovery. This is needed to avoid streaming 482 // loss during CD-R recording. Note, that some recording tools 483 // work with device via SPTI bypassing FS/Device driver layers. 484 485 ioBuf = (int8*)MyAllocatePool__(NonPagedPool,4096); 486 if(!ioBuf) { 487 try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 488 } 489 RC = UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY,TargetDeviceObject, 490 ioBuf,sizeof(DISK_GEOMETRY), 491 ioBuf,sizeof(DISK_GEOMETRY), 492 FALSE, NULL ); 493 494 if(RC == STATUS_DEVICE_NOT_READY) { 495 // probably, the device is really busy, may be by CD/DVD recording 496 UserPrint((" busy (*)\n")); 497 try_return(RC); 498 } 499 } 500 501 // lock media for now 502 if(!WrongMedia) { 503 ((PPREVENT_MEDIA_REMOVAL_USER_IN)(&MediaChangeCount))->PreventMediaRemoval = TRUE; 504 RC = UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL, 505 TargetDeviceObject, 506 &MediaChangeCount,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN), 507 NULL,0, 508 FALSE,NULL); 509 Locked = TRUE; 510 } 511 512 } 513 // Now before we can initialize the Vcb we need to set up the 514 // Get our device object and alignment requirement. 515 // Device extension == VCB 516 UDFPrint(("UDFMountVolume: create device\n")); 517 RC = IoCreateDevice( UDFGlobalData.DriverObject, 518 sizeof(VCB), 519 NULL, 520 FsDeviceType, 521 0, 522 FALSE, 523 &VolDo ); 524 525 if(!NT_SUCCESS(RC)) try_return(RC); 526 527 // Our alignment requirement is the larger of the processor alignment requirement 528 // already in the volume device object and that in the DeviceObjectWeTalkTo 529 if(TargetDeviceObject->AlignmentRequirement > VolDo->AlignmentRequirement) { 530 VolDo->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; 531 } 532 533 VolDo->Flags &= ~DO_DEVICE_INITIALIZING; 534 535 // device object field in the VPB to point to our new volume device 536 // object. 537 Vpb->DeviceObject = (PDEVICE_OBJECT) VolDo; 538 539 // We must initialize the stack size in our device object before 540 // the following reads, because the I/O system has not done it yet. 541 ((PDEVICE_OBJECT)VolDo)->StackSize = (CCHAR) (TargetDeviceObject->StackSize + 1); 542 543 Vcb = (PVCB)VolDo->DeviceExtension; 544 545 // Initialize the Vcb. This routine will raise on an allocation 546 // failure. 547 RC = UDFInitializeVCB(VolDo,TargetDeviceObject,Vpb); 548 if(!NT_SUCCESS(RC)) { 549 Vcb = NULL; 550 try_return(RC); 551 } 552 553 VolDo = NULL; 554 Vpb = NULL; 555 556 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE ); 557 VcbAcquired = TRUE; 558 559 // Let's reference the Vpb to make sure we are the one to 560 // have the last dereference. 561 Vcb->Vpb->ReferenceCount ++; 562 563 Vcb->MediaChangeCount = MediaChangeCount; 564 Vcb->FsDeviceType = FsDeviceType; 565 566 // Clear the verify bit for the start of mount. 567 if(Vcb->Vpb->RealDevice->Flags & DO_VERIFY_VOLUME) { 568 Vcb->Vpb->RealDevice->Flags &= ~DO_VERIFY_VOLUME; 569 RestoreDoVerify = TRUE; 570 } 571 572 DeviceNotTouched = FALSE; 573 RC = UDFGetDiskInfo(TargetDeviceObject,Vcb); 574 if(!NT_SUCCESS(RC)) try_return(RC); 575 576 // **** Read registry settings **** 577 UDFReadRegKeys(Vcb, FALSE, FALSE); 578 579 Vcb->MountPhErrorCount = 0; 580 581 // Initialize internal cache 582 Mode = WCACHE_MODE_ROM; 583 RC = WCacheInit__(&(Vcb->FastCache), 584 Vcb->WCacheMaxFrames, 585 Vcb->WCacheMaxBlocks, 586 Vcb->WriteBlockSize, 587 5, Vcb->BlockSizeBits, 588 Vcb->WCacheBlocksPerFrameSh, 589 0/*Vcb->FirstLBA*/, Vcb->LastPossibleLBA, Mode, 590 0/*WCACHE_CACHE_WHOLE_PACKET*/ | 591 (Vcb->DoNotCompareBeforeWrite ? WCACHE_DO_NOT_COMPARE : 0) | 592 (Vcb->CacheChainedIo ? WCACHE_CHAINED_IO : 0) | 593 WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS, // this will be cleared after mount 594 Vcb->WCacheFramesToKeepFree, 595 // UDFTWrite, UDFTRead, 596 UDFTWriteVerify, UDFTReadVerify, 597 #ifdef UDF_ASYNC_IO 598 UDFTWriteAsync, UDFTReadAsync, 599 #else //UDF_ASYNC_IO 600 NULL, NULL, 601 #endif //UDF_ASYNC_IO 602 UDFIsBlockAllocated, 603 UDFUpdateVAT, 604 UDFWCacheErrorHandler); 605 if(!NT_SUCCESS(RC)) try_return(RC); 606 607 RC = UDFVInit(Vcb); 608 if(!NT_SUCCESS(RC)) try_return(RC); 609 610 UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE); 611 RC = UDFGetDiskInfoAndVerify(TargetDeviceObject,Vcb); 612 UDFReleaseResource(&(Vcb->BitMapResource1)); 613 614 ASSERT(!Vcb->Modified); 615 WCacheChFlags__(&(Vcb->FastCache), 616 WCACHE_CACHE_WHOLE_PACKET, // enable cache whole packet 617 WCACHE_MARK_BAD_BLOCKS | WCACHE_RO_BAD_BLOCKS); // let user retry request on Bad Blocks 618 619 #ifdef UDF_READ_ONLY_BUILD 620 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY; 621 Vcb->VCBFlags |= UDF_VCB_FLAGS_MEDIA_READ_ONLY; 622 #endif //UDF_READ_ONLY_BUILD 623 624 if(!NT_SUCCESS(RC)) { 625 UDFPrint(("UDFMountVolume: try raw mount\n")); 626 if(Vcb->NSRDesc & VRS_ISO9660_FOUND) { 627 UDFPrint(("UDFMountVolume: block raw mount due to ISO9660 presence\n")); 628 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK; 629 try_return(RC); 630 } 631 try_raw_mount: 632 UDFPrint(("UDFMountVolume: try raw mount (2)\n")); 633 if(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) { 634 635 UDFPrint(("UDFMountVolume: trying raw mount...\n")); 636 Vcb->VolIdent.Length = 637 (Vcb->VolIdent.MaximumLength = sizeof(UDF_BLANK_VOLUME_LABEL)) - 2; 638 if(Vcb->VolIdent.Buffer) 639 MyFreePool__(Vcb->VolIdent.Buffer); 640 Vcb->VolIdent.Buffer = (PWCHAR)MyAllocatePool__(NonPagedPool, sizeof(UDF_BLANK_VOLUME_LABEL)); 641 if(!Vcb->VolIdent.Buffer) 642 try_return(STATUS_INSUFFICIENT_RESOURCES); 643 RtlCopyMemory(Vcb->VolIdent.Buffer, UDF_BLANK_VOLUME_LABEL, sizeof(UDF_BLANK_VOLUME_LABEL)); 644 645 RC = UDFBlankMount(Vcb); 646 if(!NT_SUCCESS(RC)) try_return(RC); 647 648 } else { 649 // Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK; 650 try_return(RC); 651 } 652 } else { 653 Vcb->MountPhErrorCount = -1; 654 #ifndef UDF_READ_ONLY_BUILD 655 // set cache mode according to media type 656 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY)) { 657 UDFPrint(("UDFMountVolume: writable volume\n")); 658 if(!Vcb->CDR_Mode) { 659 if((FsDeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) || 660 CdrwMediaClassEx_IsRAM(Vcb->MediaClassEx)) { 661 UDFPrint(("UDFMountVolume: RAM mode\n")); 662 Mode = WCACHE_MODE_RAM; 663 } else { 664 UDFPrint(("UDFMountVolume: RW mode\n")); 665 Mode = WCACHE_MODE_RW; 666 } 667 /* if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) { 668 } else { 669 Vcb->WriteSecurity = TRUE; 670 }*/ 671 } else { 672 UDFPrint(("UDFMountVolume: R mode\n")); 673 Mode = WCACHE_MODE_R; 674 } 675 // we can't record ACL on old format disks 676 if(!UDFNtAclSupported(Vcb)) { 677 UDFPrint(("UDFMountVolume: NO ACL and ExtFE support\n")); 678 Vcb->WriteSecurity = FALSE; 679 Vcb->UseExtendedFE = FALSE; 680 } 681 } 682 WCacheSetMode__(&(Vcb->FastCache), Mode); 683 #endif //UDF_READ_ONLY_BUILD 684 // Complete mount operations: create root FCB 685 UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE); 686 RC = UDFCompleteMount(Vcb); 687 UDFReleaseResource(&(Vcb->BitMapResource1)); 688 if(!NT_SUCCESS(RC)) { 689 // We must have Vcb->VCBOpenCount = 1 for UDFBlankMount() 690 // Thus, we should not decrement it here 691 // Also, if we shall not perform BlankMount, 692 // but simply cleanup and return error, Vcb->VCBOpenCount 693 // will be decremented during cleanup. Thus anyway it must 694 // stay 1 unchanged here 695 //UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 696 UDFCloseResidual(Vcb); 697 Vcb->VCBOpenCount = 1; 698 if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) 699 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK; 700 goto try_raw_mount; 701 } 702 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK; 703 } 704 705 #ifndef UDF_READ_ONLY_BUILD 706 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY)) { 707 RC = UDFStartEjectWaiter(Vcb); 708 if(!NT_SUCCESS(RC)) try_return(RC); 709 } else { 710 UDFPrint(("UDFMountVolume: RO mount\n")); 711 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY; 712 } 713 #endif //UDF_READ_ONLY_BUILD 714 715 Vcb->Vpb->SerialNumber = Vcb->PhSerialNumber; 716 Vcb->Vpb->VolumeLabelLength = Vcb->VolIdent.Length; 717 RtlCopyMemory( Vcb->Vpb->VolumeLabel, 718 Vcb->VolIdent.Buffer, 719 Vcb->VolIdent.Length ); 720 721 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_MOUNTED; 722 723 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 724 Vcb->TotalAllocUnits = UDFGetTotalSpace(Vcb); 725 Vcb->FreeAllocUnits = UDFGetFreeSpace(Vcb); 726 // Register shutdown routine 727 if(!Vcb->ShutdownRegistered) { 728 UDFPrint(("UDFMountVolume: Register shutdown routine\n")); 729 IoRegisterShutdownNotification(Vcb->VCBDeviceObject); 730 Vcb->ShutdownRegistered = TRUE; 731 } 732 733 // unlock media 734 if(RemovableMedia) { 735 if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) { 736 UDFPrint(("UDFMountVolume: unlock media on RO volume\n")); 737 ((PPREVENT_MEDIA_REMOVAL_USER_IN)(&MediaChangeCount))->PreventMediaRemoval = FALSE; 738 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL, 739 TargetDeviceObject, 740 &MediaChangeCount,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN), 741 NULL,0, 742 FALSE,NULL); 743 if(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) 744 UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, TRUE); 745 } 746 } 747 748 if (UDFGlobalData.MountEvent) 749 { 750 Vcb->IsVolumeJustMounted = TRUE; 751 KeSetEvent(UDFGlobalData.MountEvent, 0, FALSE); 752 } 753 754 // The new mount is complete. 755 UDFReleaseResource( &(Vcb->VCBResource) ); 756 VcbAcquired = FALSE; 757 Vcb = NULL; 758 759 RC = STATUS_SUCCESS; 760 761 try_exit: NOTHING; 762 } _SEH2_FINALLY { 763 764 UDFPrint(("UDFMountVolume: RC = %x\n", RC)); 765 766 if(ioBuf) { 767 MyFreePool__(ioBuf); 768 } 769 770 if(!NT_SUCCESS(RC)) { 771 772 if(RemovableMedia && Locked) { 773 UDFPrint(("UDFMountVolume: unlock media\n")); 774 ((PPREVENT_MEDIA_REMOVAL_USER_IN)(&MediaChangeCount))->PreventMediaRemoval = FALSE; 775 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL, 776 TargetDeviceObject, 777 &MediaChangeCount,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN), 778 NULL,0, 779 FALSE,NULL); 780 } 781 /* if((RC != STATUS_DEVICE_NOT_READY) && 782 (RC != STATUS_NO_MEDIA_IN_DEVICE) ) {*/ 783 // reset driver 784 if(!DeviceNotTouched && 785 (!Vcb || (Vcb && (Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER)))) { 786 UDFPrint(("UDFMountVolume: reset driver\n")); 787 UDFResetDeviceDriver(Vcb, TargetDeviceObject, TRUE); 788 } 789 790 if(RC == STATUS_CRC_ERROR || RC == STATUS_FILE_CORRUPT_ERROR) { 791 UDFPrint(("UDFMountVolume: status -> STATUS_UNRECOGNIZED_VOLUME\n")); 792 RC = STATUS_UNRECOGNIZED_VOLUME; 793 } 794 795 // If we didn't complete the mount then cleanup any remaining structures. 796 if(Vpb) { 797 Vpb->DeviceObject = NULL; 798 } 799 800 if(Vcb) { 801 // Restore the verify bit. 802 if(RestoreDoVerify) { 803 Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME; 804 } 805 // Make sure there is no Vcb since it could go away 806 if(Vcb->VCBOpenCount) 807 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 808 // This procedure will also delete the volume device object 809 if(UDFDismountVcb( Vcb, VcbAcquired )) { 810 UDFReleaseResource( &(Vcb->VCBResource) ); 811 } 812 } else if(VolDo) { 813 IoDeleteDevice( VolDo ); 814 } 815 } 816 // Release the global resource. 817 UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) ); 818 819 if (CompleteIrp || NT_SUCCESS(RC)) { 820 if(!_SEH2_AbnormalTermination()) { 821 // Set mount event 822 823 UDFPrint(("UDFMountVolume: complete req RC %x\n", RC)); 824 UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_MOUNT); 825 // Complete the IRP. 826 Irp->IoStatus.Status = RC; 827 IoCompleteRequest(Irp, IO_NO_INCREMENT); 828 } 829 } else { 830 // Pass Irp to lower driver (CDFS) 831 832 // Get this driver out of the driver stack and get to the next driver as 833 // quickly as possible. 834 Irp->CurrentLocation++; 835 Irp->Tail.Overlay.CurrentStackLocation++; 836 837 // Now call the appropriate file system driver with the request. 838 RC = IoCallDriver( filterDevExt->lowerFSDeviceObject, Irp ); 839 840 } 841 842 } _SEH2_END; 843 844 UDFPrint(("UDFMountVolume: final RC = %x\n", RC)); 845 return RC; 846 847 } // end UDFMountVolume() 848 849 NTSTATUS 850 UDFStartEjectWaiter( 851 IN PVCB Vcb 852 ) 853 { 854 // NTSTATUS RC; 855 PREVENT_MEDIA_REMOVAL_USER_IN Buff; 856 UDFPrint(("UDFStartEjectWaiter:\n")); 857 858 if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) { 859 UDFPrint((" UDF_VCB_FLAGS_MEDIA_READ_ONLY\n")); 860 } 861 if(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_LOCKED) { 862 UDFPrint((" UDF_VCB_FLAGS_MEDIA_LOCKED\n")); 863 } 864 UDFPrint((" EjectWaiter=%x\n", Vcb->EjectWaiter)); 865 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_READ_ONLY) && 866 /*!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_LOCKED) &&*/ 867 !(Vcb->EjectWaiter)) { 868 869 UDFPrint(("UDFStartEjectWaiter: check driver\n")); 870 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) && 871 (Vcb->FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM)) { 872 // we don't know how to write without our device driver 873 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY; 874 UDFPrint((" not our driver, ignore\n")); 875 return STATUS_SUCCESS; 876 } 877 UDFPrint(("UDFStartEjectWaiter: check removable\n")); 878 if(Vcb->VCBFlags & UDF_VCB_FLAGS_REMOVABLE_MEDIA) { 879 // prevent media removal 880 UDFPrint(("UDFStartEjectWaiter: lock media\n")); 881 Buff.PreventMediaRemoval = TRUE; 882 UDFTSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL, 883 Vcb, 884 &Buff,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN), 885 NULL,0, 886 FALSE,NULL ); 887 Vcb->VCBFlags |= UDF_VCB_FLAGS_MEDIA_LOCKED; 888 } 889 UDFPrint(("UDFStartEjectWaiter: prepare to start\n")); 890 // initialize Eject Request waiter 891 Vcb->EjectWaiter = (PUDFEjectWaitContext)MyAllocatePool__(NonPagedPool, sizeof(UDFEjectWaitContext)); 892 if(!(Vcb->EjectWaiter)) return STATUS_INSUFFICIENT_RESOURCES; 893 KeInitializeEvent(&(Vcb->WaiterStopped), NotificationEvent, FALSE); 894 Vcb->EjectWaiter->Vcb = Vcb; 895 Vcb->EjectWaiter->SoftEjectReq = FALSE; 896 KeInitializeEvent(&(Vcb->EjectWaiter->StopReq), NotificationEvent, FALSE); 897 // Vcb->EjectWaiter->StopReq = FALSE; 898 Vcb->EjectWaiter->WaiterStopped = &(Vcb->WaiterStopped); 899 // This can occure after unexpected media loss, when EjectRequestWaiter 900 // terminates automatically 901 ASSERT(!(Vcb->VCBFlags & UDF_VCB_FLAGS_STOP_WAITER_EVENT)); 902 Vcb->VCBFlags |= UDF_VCB_FLAGS_STOP_WAITER_EVENT; 903 ExInitializeWorkItem(&(Vcb->EjectWaiter->EjectReqWorkQueueItem), UDFEjectReqWaiter, Vcb->EjectWaiter); 904 UDFPrint(("UDFStartEjectWaiter: create thread\n")); 905 ExQueueWorkItem(&(Vcb->EjectWaiter->EjectReqWorkQueueItem), DelayedWorkQueue); 906 } else { 907 UDFPrint((" ignore\n")); 908 } 909 return STATUS_SUCCESS; 910 } // end UDFStartEjectWaiter() 911 912 NTSTATUS 913 UDFCompleteMount( 914 IN PVCB Vcb 915 ) 916 { 917 NTSTATUS RC;// = STATUS_SUCCESS; 918 PtrUDFNTRequiredFCB NtReqFcb = NULL; 919 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader = NULL; 920 UNICODE_STRING LocalPath; 921 PtrUDFObjectName RootName; 922 PtrUDFFCB RootFcb; 923 924 UDFPrint(("UDFCompleteMount:\n")); 925 Vcb->ZBuffer = (PCHAR)DbgAllocatePoolWithTag(NonPagedPool, max(Vcb->LBlockSize, PAGE_SIZE), 'zNWD'); 926 if(!Vcb->ZBuffer) return STATUS_INSUFFICIENT_RESOURCES; 927 RtlZeroMemory(Vcb->ZBuffer, Vcb->LBlockSize); 928 929 UDFPrint(("UDFCompleteMount: alloc Root FCB\n")); 930 // Create the root index and reference it in the Vcb. 931 RootFcb = 932 Vcb->RootDirFCB = UDFAllocateFCB(); 933 if(!RootFcb) return STATUS_INSUFFICIENT_RESOURCES; 934 935 UDFPrint(("UDFCompleteMount: alloc Root ObjName\n")); 936 // Allocate and set root FCB unique name 937 RootName = UDFAllocateObjectName(); 938 if(!RootName) { 939 UDFCleanUpFCB(RootFcb); 940 Vcb->RootDirFCB = NULL; 941 return STATUS_INSUFFICIENT_RESOURCES; 942 } 943 RC = MyInitUnicodeString(&(RootName->ObjectName),UDF_ROOTDIR_NAME); 944 if(!NT_SUCCESS(RC)) 945 goto insuf_res_1; 946 947 RootFcb->FileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO)); 948 if(!RootFcb->FileInfo) { 949 RC = STATUS_INSUFFICIENT_RESOURCES; 950 insuf_res_1: 951 MyFreePool__(RootName->ObjectName.Buffer); 952 UDFReleaseObjectName(RootName); 953 UDFCleanUpFCB(RootFcb); 954 Vcb->RootDirFCB = NULL; 955 return RC; 956 } 957 UDFPrint(("UDFCompleteMount: open Root Dir\n")); 958 // Open Root Directory 959 RC = UDFOpenRootFile__( Vcb, &(Vcb->RootLbAddr), RootFcb->FileInfo ); 960 if(!NT_SUCCESS(RC)) { 961 insuf_res_2: 962 UDFCleanUpFile__(Vcb, RootFcb->FileInfo); 963 MyFreePool__(RootFcb->FileInfo); 964 goto insuf_res_1; 965 } 966 RootFcb->FileInfo->Fcb = RootFcb; 967 968 if(!(RootFcb->NTRequiredFCB = RootFcb->FileInfo->Dloc->CommonFcb)) { 969 UDFPrint(("UDFCompleteMount: alloc Root ObjName (2)\n")); 970 if(!(RootFcb->NTRequiredFCB = 971 (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB))) ) ) { 972 RC = STATUS_INSUFFICIENT_RESOURCES; 973 goto insuf_res_2; 974 } 975 RtlZeroMemory(RootFcb->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB))); 976 RootFcb->FileInfo->Dloc->CommonFcb = RootFcb->NTRequiredFCB; 977 } 978 UDFPrint(("UDFCompleteMount: init FCB\n")); 979 RC = UDFInitializeFCB(RootFcb,Vcb,RootName,UDF_FCB_ROOT_DIRECTORY | UDF_FCB_DIRECTORY,NULL); 980 if(!NT_SUCCESS(RC)) { 981 // if we get here, no resources are inited 982 RootFcb->OpenHandleCount = 983 RootFcb->ReferenceCount = 984 RootFcb->NTRequiredFCB->CommonRefCount = 0; 985 986 UDFCleanUpFile__(Vcb, RootFcb->FileInfo); 987 MyFreePool__(RootFcb->FileInfo); 988 MyFreePool__(RootFcb->NTRequiredFCB); 989 UDFCleanUpFCB(RootFcb); 990 Vcb->RootDirFCB = NULL; 991 return RC; 992 } 993 994 // this is a part of UDF_RESIDUAL_REFERENCE 995 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount)); 996 RootFcb->OpenHandleCount = 997 RootFcb->ReferenceCount = 998 RootFcb->NTRequiredFCB->CommonRefCount = 1; 999 1000 UDFGetFileXTime(RootFcb->FileInfo, 1001 &(RootFcb->NTRequiredFCB->CreationTime.QuadPart), 1002 &(RootFcb->NTRequiredFCB->LastAccessTime.QuadPart), 1003 &(RootFcb->NTRequiredFCB->ChangeTime.QuadPart), 1004 &(RootFcb->NTRequiredFCB->LastWriteTime.QuadPart) ); 1005 1006 if(Vcb->SysStreamLbAddr.logicalBlockNum) { 1007 Vcb->SysSDirFileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO)); 1008 if(!Vcb->SysSDirFileInfo) { 1009 RC = STATUS_INSUFFICIENT_RESOURCES; 1010 goto unwind_1; 1011 } 1012 // Open System SDir Directory 1013 RC = UDFOpenRootFile__( Vcb, &(Vcb->SysStreamLbAddr), Vcb->SysSDirFileInfo ); 1014 if(!NT_SUCCESS(RC)) { 1015 UDFCleanUpFile__(Vcb, Vcb->SysSDirFileInfo); 1016 MyFreePool__(Vcb->SysSDirFileInfo); 1017 Vcb->SysSDirFileInfo = NULL; 1018 goto unwind_1; 1019 } else { 1020 Vcb->SysSDirFileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_VERIFY; 1021 } 1022 } 1023 1024 // Open Unallocatable space stream 1025 // Generally, it should be placed in SystemStreamDirectory, but some 1026 // stupid apps think that RootDirectory is much better place.... :(( 1027 RC = MyInitUnicodeString(&LocalPath, UDF_FN_NON_ALLOCATABLE); 1028 if(NT_SUCCESS(RC)) { 1029 RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, RootFcb->FileInfo, &(Vcb->NonAllocFileInfo), NULL); 1030 MyFreePool__(LocalPath.Buffer); 1031 } 1032 if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) { 1033 1034 //unwind_2: 1035 UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo); 1036 Vcb->NonAllocFileInfo = NULL; 1037 // this was a part of UDF_RESIDUAL_REFERENCE 1038 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 1039 unwind_1: 1040 1041 // UDFCloseResidual() will clean up everything 1042 1043 return RC; 1044 } 1045 1046 /* process Non-allocatable */ 1047 if(NT_SUCCESS(RC)) { 1048 UDFMarkSpaceAsXXX(Vcb, Vcb->NonAllocFileInfo->Dloc, Vcb->NonAllocFileInfo->Dloc->DataLoc.Mapping, AS_USED); // used 1049 UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL; 1050 } else { 1051 /* try to read Non-allocatable from alternate locations */ 1052 RC = MyInitUnicodeString(&LocalPath, UDF_FN_NON_ALLOCATABLE_2); 1053 if(!NT_SUCCESS(RC)) { 1054 goto unwind_1; 1055 } 1056 RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, RootFcb->FileInfo, &(Vcb->NonAllocFileInfo), NULL); 1057 MyFreePool__(LocalPath.Buffer); 1058 if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) { 1059 goto unwind_1; 1060 } 1061 if(NT_SUCCESS(RC)) { 1062 UDFMarkSpaceAsXXX(Vcb, Vcb->NonAllocFileInfo->Dloc, Vcb->NonAllocFileInfo->Dloc->DataLoc.Mapping, AS_USED); // used 1063 UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL; 1064 } else 1065 if(Vcb->SysSDirFileInfo) { 1066 RC = MyInitUnicodeString(&LocalPath, UDF_SN_NON_ALLOCATABLE); 1067 if(!NT_SUCCESS(RC)) { 1068 goto unwind_1; 1069 } 1070 RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, Vcb->SysSDirFileInfo , &(Vcb->NonAllocFileInfo), NULL); 1071 MyFreePool__(LocalPath.Buffer); 1072 if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) { 1073 goto unwind_1; 1074 } 1075 if(NT_SUCCESS(RC)) { 1076 UDFMarkSpaceAsXXX(Vcb, Vcb->NonAllocFileInfo->Dloc, Vcb->NonAllocFileInfo->Dloc->DataLoc.Mapping, AS_USED); // used 1077 // UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL; 1078 } else { 1079 RC = STATUS_SUCCESS; 1080 } 1081 } else { 1082 RC = STATUS_SUCCESS; 1083 } 1084 } 1085 1086 /* Read SN UID mapping */ 1087 if(Vcb->SysSDirFileInfo) { 1088 RC = MyInitUnicodeString(&LocalPath, UDF_SN_UID_MAPPING); 1089 if(!NT_SUCCESS(RC)) 1090 goto unwind_3; 1091 RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, Vcb->SysSDirFileInfo , &(Vcb->UniqueIDMapFileInfo), NULL); 1092 MyFreePool__(LocalPath.Buffer); 1093 if(!NT_SUCCESS(RC) && (RC != STATUS_OBJECT_NAME_NOT_FOUND)) { 1094 unwind_3: 1095 // UDFCloseFile__(Vcb, Vcb->NonAllocFileInfo); 1096 // UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo); 1097 // if(Vcb->NonAllocFileInfo) 1098 // MyFreePool__(Vcb->NonAllocFileInfo); 1099 // Vcb->NonAllocFileInfo = NULL; 1100 goto unwind_1; 1101 } else { 1102 Vcb->UniqueIDMapFileInfo->Dloc->DataLoc.Flags |= EXTENT_FLAG_VERIFY; 1103 } 1104 RC = STATUS_SUCCESS; 1105 } 1106 1107 #define DWN_MAX_CFG_FILE_SIZE 0x10000 1108 1109 /* Read DWN config file from disk with disk-specific options */ 1110 RC = MyInitUnicodeString(&LocalPath, UDF_CONFIG_STREAM_NAME_W); 1111 if(NT_SUCCESS(RC)) { 1112 1113 int8* buff; 1114 SIZE_T len; 1115 PUDF_FILE_INFO CfgFileInfo = NULL; 1116 1117 RC = UDFOpenFile__(Vcb, FALSE, TRUE, &LocalPath, RootFcb->FileInfo, &CfgFileInfo, NULL); 1118 if(OS_SUCCESS(RC)) { 1119 1120 len = (ULONG)UDFGetFileSize(CfgFileInfo); 1121 if(len && len < DWN_MAX_CFG_FILE_SIZE) { 1122 buff = (int8*)MyAllocatePool__(NonPagedPool, len); 1123 if(buff) { 1124 RC = UDFReadFile__(Vcb, CfgFileInfo, 0, len, FALSE, buff, &len); 1125 if(OS_SUCCESS(RC)) { 1126 // parse config 1127 Vcb->Cfg = (PUCHAR)buff; 1128 Vcb->CfgLength = len; 1129 UDFReadRegKeys(Vcb, TRUE /*update*/, TRUE /*cfg*/); 1130 Vcb->Cfg = NULL; 1131 Vcb->CfgLength = 0; 1132 Vcb->CfgVersion = 0; 1133 } 1134 MyFreePool__(buff); 1135 } 1136 } 1137 1138 UDFCloseFile__(Vcb, CfgFileInfo); 1139 } 1140 if(CfgFileInfo) { 1141 UDFCleanUpFile__(Vcb, CfgFileInfo); 1142 } 1143 MyFreePool__(LocalPath.Buffer); 1144 } 1145 RC = STATUS_SUCCESS; 1146 1147 // clear Modified flags. It was not real modify, just 1148 // bitmap construction 1149 Vcb->BitmapModified = FALSE; 1150 //Vcb->Modified = FALSE; 1151 UDFPreClrModified(Vcb); 1152 UDFClrModified(Vcb); 1153 // this is a part of UDF_RESIDUAL_REFERENCE 1154 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount)); 1155 1156 NtReqFcb = RootFcb->NTRequiredFCB; 1157 1158 // Start initializing the fields contained in the CommonFCBHeader. 1159 PtrCommonFCBHeader = &(NtReqFcb->CommonFCBHeader); 1160 1161 // DisAllow fast-IO for now. 1162 // PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible; 1163 PtrCommonFCBHeader->IsFastIoPossible = FastIoIsPossible; 1164 1165 // Initialize the MainResource and PagingIoResource pointers in 1166 // the CommonFCBHeader structure to point to the ERESOURCE structures we 1167 // have allocated and already initialized above. 1168 // PtrCommonFCBHeader->Resource = &(NtReqFcb->MainResource); 1169 // PtrCommonFCBHeader->PagingIoResource = &(NtReqFcb->PagingIoResource); 1170 1171 // Initialize the file size values here. 1172 PtrCommonFCBHeader->AllocationSize.QuadPart = 0; 1173 PtrCommonFCBHeader->FileSize.QuadPart = 0; 1174 1175 // The following will disable ValidDataLength support. 1176 // PtrCommonFCBHeader->ValidDataLength.QuadPart = 0x7FFFFFFFFFFFFFFFI64; 1177 PtrCommonFCBHeader->ValidDataLength.QuadPart = 0; 1178 1179 if(!NT_SUCCESS(RC)) 1180 return RC; 1181 UDFAssignAcl(Vcb, NULL, RootFcb, NtReqFcb); 1182 /* 1183 Vcb->CDBurnerVolumeValid = true; 1184 1185 len = 1186 Vcb->CDBurnerVolume.Length = 256; 1187 Vcb->CDBurnerVolume.MaximumLength = 256; 1188 Vcb->CDBurnerVolume.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, 256); 1189 RC = RegTGetStringValue(NULL, REG_CD_BURNER_KEY_NAME, REG_CD_BURNER_VOLUME_NAME, Vcb->CDBurnerVolume.Buffer, 1190 len); 1191 Vcb->CDBurnerVolume.Length = (USHORT)(wcslen(Vcb->CDBurnerVolume.Buffer)*sizeof(WCHAR)); 1192 1193 if(RC != STATUS_OBJECT_NAME_NOT_FOUND && !NT_SUCCESS(RC) ) 1194 return RC; 1195 1196 if (NT_SUCCESS(RC)) { 1197 RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, 1198 REG_CD_BURNER_KEY_NAME, REG_CD_BURNER_VOLUME_NAME, 1199 REG_SZ,L"",sizeof(L"")+1); 1200 1201 } else { 1202 Vcb->CDBurnerVolumeValid = false; 1203 RC = STATUS_SUCCESS; 1204 } 1205 */ 1206 ASSERT(!Vcb->Modified); 1207 1208 return RC; 1209 } // end UDFCompleteMount() 1210 1211 NTSTATUS 1212 UDFBlankMount( 1213 IN PVCB Vcb 1214 ) 1215 { 1216 NTSTATUS RC;// = STATUS_SUCCESS; 1217 PtrUDFNTRequiredFCB NtReqFcb = NULL; 1218 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader = NULL; 1219 PtrUDFObjectName RootName; 1220 PtrUDFFCB RootFcb; 1221 PDIR_INDEX_HDR hDirNdx; 1222 PDIR_INDEX_ITEM DirNdx; 1223 1224 // Create the root index and reference it in the Vcb. 1225 RootFcb = 1226 Vcb->RootDirFCB = UDFAllocateFCB(); 1227 if(!RootFcb) return STATUS_INSUFFICIENT_RESOURCES; 1228 RtlZeroMemory(RootFcb,sizeof(UDFFCB)); 1229 1230 // Allocate and set root FCB unique name 1231 RootName = UDFAllocateObjectName(); 1232 if(!RootName) { 1233 //bl_unwind_2: 1234 UDFCleanUpFCB(RootFcb); 1235 Vcb->RootDirFCB = NULL; 1236 return STATUS_INSUFFICIENT_RESOURCES; 1237 } 1238 RC = MyInitUnicodeString(&(RootName->ObjectName),UDF_ROOTDIR_NAME); 1239 if(!NT_SUCCESS(RC)) 1240 goto bl_unwind_1; 1241 1242 RootFcb->NodeIdentifier.NodeType = UDF_NODE_TYPE_FCB; 1243 RootFcb->NodeIdentifier.NodeSize = sizeof(UDFFCB); 1244 1245 RootFcb->FileInfo = (PUDF_FILE_INFO)MyAllocatePool__(NonPagedPool,sizeof(UDF_FILE_INFO)); 1246 if(!RootFcb->FileInfo) { 1247 MyFreePool__(RootName->ObjectName.Buffer); 1248 RC = STATUS_INSUFFICIENT_RESOURCES; 1249 bl_unwind_1: 1250 UDFReleaseObjectName(RootName); 1251 UDFCleanUpFCB(RootFcb); 1252 Vcb->RootDirFCB = NULL; 1253 return RC; 1254 } 1255 RtlZeroMemory(RootFcb->FileInfo, sizeof(UDF_FILE_INFO)); 1256 if(!OS_SUCCESS(RC = UDFStoreDloc(Vcb, RootFcb->FileInfo, 1))) { 1257 MyFreePool__(RootFcb->FileInfo); 1258 RootFcb->FileInfo = NULL; 1259 MyFreePool__(RootName->ObjectName.Buffer); 1260 goto bl_unwind_1; 1261 } 1262 RootFcb->FileInfo->NextLinkedFile = 1263 RootFcb->FileInfo->PrevLinkedFile = RootFcb->FileInfo; 1264 1265 hDirNdx = UDFDirIndexAlloc(2); 1266 DirNdx = UDFDirIndex(hDirNdx,0); 1267 DirNdx->FileCharacteristics = FILE_DIRECTORY; 1268 DirNdx->FI_Flags = UDF_FI_FLAG_SYS_ATTR; 1269 DirNdx->SysAttr = FILE_ATTRIBUTE_READONLY; 1270 RtlInitUnicodeString(&DirNdx->FName, L"."); 1271 DirNdx->FileInfo = RootFcb->FileInfo; 1272 DirNdx->FI_Flags |= UDFBuildHashEntry(Vcb, &(DirNdx->FName), &(DirNdx->hashes), HASH_ALL | HASH_KEEP_NAME); 1273 1274 DirNdx = UDFDirIndex(hDirNdx,1); 1275 DirNdx->FI_Flags = UDF_FI_FLAG_SYS_ATTR; 1276 if(Vcb->ShowBlankCd == 2) { 1277 DirNdx->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL; 1278 } 1279 DirNdx->SysAttr = FILE_ATTRIBUTE_READONLY; 1280 RtlInitUnicodeString(&DirNdx->FName, L"Blank.CD"); 1281 DirNdx->FI_Flags |= UDFBuildHashEntry(Vcb, &(DirNdx->FName), &(DirNdx->hashes), HASH_ALL); 1282 1283 RootFcb->FileInfo->Dloc->DirIndex = hDirNdx; 1284 RootFcb->FileInfo->Fcb = RootFcb; 1285 1286 if(!(RootFcb->NTRequiredFCB = RootFcb->FileInfo->Dloc->CommonFcb)) { 1287 if(!(RootFcb->NTRequiredFCB = 1288 (PtrUDFNTRequiredFCB)MyAllocatePool__(NonPagedPool, UDFQuadAlign(sizeof(UDFNTRequiredFCB))) ) ) { 1289 MyFreePool__(RootName->ObjectName.Buffer); 1290 UDFReleaseObjectName(RootName); 1291 UDFCleanUpFCB(RootFcb); 1292 Vcb->RootDirFCB = NULL; 1293 return STATUS_INSUFFICIENT_RESOURCES; 1294 } 1295 RtlZeroMemory(RootFcb->NTRequiredFCB, UDFQuadAlign(sizeof(UDFNTRequiredFCB))); 1296 RootFcb->FileInfo->Dloc->CommonFcb = RootFcb->NTRequiredFCB; 1297 } 1298 RC = UDFInitializeFCB(RootFcb,Vcb,RootName,UDF_FCB_ROOT_DIRECTORY | UDF_FCB_DIRECTORY,NULL); 1299 if(!NT_SUCCESS(RC)) { 1300 // if we get here, no resources are inited 1301 RootFcb->OpenHandleCount = 1302 RootFcb->ReferenceCount = 1303 RootFcb->NTRequiredFCB->CommonRefCount = 0; 1304 1305 UDFCleanUpFile__(Vcb, RootFcb->FileInfo); 1306 MyFreePool__(RootFcb->FileInfo); 1307 MyFreePool__(RootFcb->NTRequiredFCB); 1308 UDFCleanUpFCB(RootFcb); 1309 Vcb->RootDirFCB = NULL; 1310 return RC; 1311 } 1312 1313 // this is a part of UDF_RESIDUAL_REFERENCE 1314 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount)); 1315 RootFcb->OpenHandleCount = 1316 RootFcb->ReferenceCount = 1317 RootFcb->NTRequiredFCB->CommonRefCount = 1318 RootFcb->FileInfo->RefCount = 1319 RootFcb->FileInfo->Dloc->LinkRefCount = 1; 1320 1321 // this is a part of UDF_RESIDUAL_REFERENCE 1322 UDFInterlockedIncrement((PLONG)&(Vcb->VCBOpenCount)); 1323 1324 NtReqFcb = RootFcb->NTRequiredFCB; 1325 1326 // Start initializing the fields contained in the CommonFCBHeader. 1327 PtrCommonFCBHeader = &(NtReqFcb->CommonFCBHeader); 1328 1329 // DisAllow fast-IO for now. 1330 PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible; 1331 1332 // Initialize the MainResource and PagingIoResource pointers in 1333 // the CommonFCBHeader structure to point to the ERESOURCE structures we 1334 // have allocated and already initialized above. 1335 PtrCommonFCBHeader->Resource = &(NtReqFcb->MainResource); 1336 PtrCommonFCBHeader->PagingIoResource = &(NtReqFcb->PagingIoResource); 1337 1338 // Initialize the file size values here. 1339 PtrCommonFCBHeader->AllocationSize.QuadPart = 0; 1340 PtrCommonFCBHeader->FileSize.QuadPart = 0; 1341 1342 // The following will disable ValidDataLength support. 1343 PtrCommonFCBHeader->ValidDataLength.QuadPart = 0x7FFFFFFFFFFFFFFFLL; 1344 1345 return RC; 1346 } // end UDFBlankMount() 1347 1348 VOID 1349 UDFCloseResidual( 1350 IN PVCB Vcb 1351 ) 1352 { 1353 // Deinitialize Non-alloc file 1354 if(Vcb->VCBOpenCount) 1355 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 1356 UDFPrint(("UDFCloseResidual: NonAllocFileInfo %x\n", Vcb->NonAllocFileInfo)); 1357 if(Vcb->NonAllocFileInfo) { 1358 UDFCloseFile__(Vcb,Vcb->NonAllocFileInfo); 1359 UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo); 1360 MyFreePool__(Vcb->NonAllocFileInfo); 1361 Vcb->NonAllocFileInfo = NULL; 1362 } 1363 // Deinitialize Unique ID Mapping 1364 UDFPrint(("UDFCloseResidual: NonAllocFileInfo %x\n", Vcb->NonAllocFileInfo)); 1365 if(Vcb->UniqueIDMapFileInfo) { 1366 UDFCloseFile__(Vcb,Vcb->UniqueIDMapFileInfo); 1367 UDFCleanUpFile__(Vcb, Vcb->UniqueIDMapFileInfo); 1368 MyFreePool__(Vcb->UniqueIDMapFileInfo); 1369 Vcb->UniqueIDMapFileInfo = NULL; 1370 } 1371 // Deinitialize VAT file 1372 UDFPrint(("UDFCloseResidual: VatFileInfo %x\n", Vcb->VatFileInfo)); 1373 if(Vcb->VatFileInfo) { 1374 UDFCloseFile__(Vcb,Vcb->VatFileInfo); 1375 UDFCleanUpFile__(Vcb, Vcb->VatFileInfo); 1376 MyFreePool__(Vcb->VatFileInfo); 1377 Vcb->VatFileInfo = NULL; 1378 } 1379 // System StreamDir 1380 UDFPrint(("UDFCloseResidual: SysSDirFileInfo %x\n", Vcb->SysSDirFileInfo)); 1381 if(Vcb->SysSDirFileInfo) { 1382 UDFCloseFile__(Vcb, Vcb->SysSDirFileInfo); 1383 UDFCleanUpFile__(Vcb, Vcb->SysSDirFileInfo); 1384 MyFreePool__(Vcb->SysSDirFileInfo); 1385 Vcb->SysSDirFileInfo = NULL; 1386 } 1387 /* // Deinitialize root dir fcb 1388 if(Vcb->RootDirFCB) { 1389 UDFCloseFile__(Vcb,Vcb->RootDirFCB->FileInfo); 1390 UDFCleanUpFile__(Vcb, Vcb->RootDirFCB->FileInfo); 1391 MyFreePool__(Vcb->RootDirFCB->FileInfo); 1392 UDFCleanUpFCB(Vcb->RootDirFCB); 1393 // Remove root FCB reference in vcb 1394 if(Vcb->VCBOpenCount) Vcb->VCBOpenCount--; 1395 } 1396 1397 // Deinitialize Non-alloc file 1398 if(Vcb->VCBOpenCount) Vcb->VCBOpenCount--; 1399 if(Vcb->NonAllocFileInfo) { 1400 UDFCloseFile__(Vcb,Vcb->NonAllocFileInfo); 1401 // We must release VCB here !!!! 1402 // UDFCleanUpFcbChain(Vcb, Vcb->NonAllocFileInfo, 1); 1403 Vcb->NonAllocFileInfo = NULL; 1404 } 1405 // Deinitialize VAT file 1406 if(Vcb->VatFileInfo) { 1407 UDFCloseFile__(Vcb,Vcb->VatFileInfo); 1408 // We must release VCB here !!!! 1409 // UDFCleanUpFcbChain(Vcb, Vcb->VatFileInfo, 1); 1410 Vcb->VatFileInfo = NULL; 1411 }*/ 1412 1413 // Deinitialize root dir fcb 1414 UDFPrint(("UDFCloseResidual: RootDirFCB %x\n", Vcb->RootDirFCB)); 1415 if(Vcb->RootDirFCB) { 1416 UDFCloseFile__(Vcb,Vcb->RootDirFCB->FileInfo); 1417 if(Vcb->RootDirFCB->OpenHandleCount) 1418 Vcb->RootDirFCB->OpenHandleCount--; 1419 UDFCleanUpFcbChain(Vcb, Vcb->RootDirFCB->FileInfo, 1, TRUE); 1420 // Remove root FCB reference in vcb 1421 if(Vcb->VCBOpenCount) 1422 UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount)); 1423 Vcb->RootDirFCB = NULL; 1424 } 1425 } // end UDFCloseResidual() 1426 1427 VOID 1428 UDFCleanupVCB( 1429 IN PVCB Vcb 1430 ) 1431 { 1432 _SEH2_TRY { 1433 UDFReleaseFileIdCache(Vcb); 1434 UDFReleaseDlocList(Vcb); 1435 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { 1436 BrutePoint(); 1437 } _SEH2_END; 1438 1439 if(Vcb->ShutdownRegistered && Vcb->VCBDeviceObject) { 1440 IoUnregisterShutdownNotification(Vcb->VCBDeviceObject); 1441 Vcb->ShutdownRegistered = FALSE; 1442 } 1443 1444 MyFreeMemoryAndPointer(Vcb->Partitions); 1445 MyFreeMemoryAndPointer(Vcb->LVid); 1446 MyFreeMemoryAndPointer(Vcb->Vat); 1447 MyFreeMemoryAndPointer(Vcb->SparingTable); 1448 1449 if(Vcb->FSBM_Bitmap) { 1450 DbgFreePool(Vcb->FSBM_Bitmap); 1451 Vcb->FSBM_Bitmap = NULL; 1452 } 1453 if(Vcb->ZSBM_Bitmap) { 1454 DbgFreePool(Vcb->ZSBM_Bitmap); 1455 Vcb->ZSBM_Bitmap = NULL; 1456 } 1457 if(Vcb->BSBM_Bitmap) { 1458 DbgFreePool(Vcb->BSBM_Bitmap); 1459 Vcb->BSBM_Bitmap = NULL; 1460 } 1461 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS 1462 if(Vcb->FSBM_Bitmap_owners) { 1463 DbgFreePool(Vcb->FSBM_Bitmap_owners); 1464 Vcb->FSBM_Bitmap_owners = NULL; 1465 } 1466 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS 1467 if(Vcb->FSBM_OldBitmap) { 1468 DbgFreePool(Vcb->FSBM_OldBitmap); 1469 Vcb->FSBM_OldBitmap = NULL; 1470 } 1471 1472 MyFreeMemoryAndPointer(Vcb->Statistics); 1473 MyFreeMemoryAndPointer(Vcb->NTRequiredFCB); 1474 MyFreeMemoryAndPointer(Vcb->VolIdent.Buffer); 1475 MyFreeMemoryAndPointer(Vcb->TargetDevName.Buffer); 1476 1477 if(Vcb->ZBuffer) { 1478 DbgFreePool(Vcb->ZBuffer); 1479 Vcb->ZBuffer = NULL; 1480 } 1481 1482 if(Vcb->fZBuffer) { 1483 DbgFreePool(Vcb->fZBuffer); 1484 Vcb->fZBuffer = NULL; 1485 } 1486 1487 MyFreeMemoryAndPointer(Vcb->OPCh); 1488 MyFreeMemoryAndPointer(Vcb->WParams); 1489 MyFreeMemoryAndPointer(Vcb->Error); 1490 MyFreeMemoryAndPointer(Vcb->TrackMap); 1491 1492 } // end UDFCleanupVCB() 1493 1494 /* 1495 1496 Routine Description: 1497 1498 This routine walks through the list of Vcb's looking for any which may 1499 now be deleted. They may have been left on the list because there were 1500 outstanding references. 1501 1502 Arguments: 1503 1504 Return Value: 1505 1506 None 1507 1508 */ 1509 VOID 1510 UDFScanForDismountedVcb( 1511 IN PtrUDFIrpContext IrpContext 1512 ) 1513 { 1514 PVCB Vcb; 1515 PLIST_ENTRY Link; 1516 1517 1518 // Walk through all of the Vcb's attached to the global data. 1519 Link = UDFGlobalData.VCBQueue.Flink; 1520 1521 while (Link != &(UDFGlobalData.VCBQueue)) { 1522 1523 Vcb = CONTAINING_RECORD( Link, VCB, NextVCB ); 1524 1525 // Move to the next link now since the current Vcb may be deleted. 1526 Link = Link->Flink; 1527 1528 // If dismount is already underway then check if this Vcb can 1529 // go away. 1530 if((Vcb->VCBFlags & UDF_VCB_FLAGS_BEING_DISMOUNTED) || 1531 ((!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) && (Vcb->VCBOpenCount <= UDF_RESIDUAL_REFERENCE))) { 1532 1533 UDFCheckForDismount( IrpContext, Vcb, FALSE ); 1534 } 1535 } 1536 1537 return; 1538 } // end UDFScanForDismountedVcb() 1539 1540 /* 1541 Routine Description: 1542 This routine determines if a volume is currently mounted. 1543 1544 Arguments: 1545 Irp - Supplies the Irp to process 1546 1547 Return Value: 1548 NTSTATUS - The return status for the operation 1549 1550 */ 1551 NTSTATUS 1552 UDFIsVolumeMounted( 1553 IN PtrUDFIrpContext IrpContext, 1554 IN PIRP Irp 1555 ) 1556 { 1557 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 1558 1559 PtrUDFFCB Fcb; 1560 PtrUDFCCB Ccb; 1561 1562 UDFPrint(("UDFIsVolumeMounted\n")); 1563 1564 Ccb = (PtrUDFCCB)IrpSp->FileObject->FsContext2; 1565 if(!Ccb) { 1566 UDFPrintErr((" !Ccb\n")); 1567 Irp->IoStatus.Information = 0; 1568 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1569 return STATUS_INVALID_PARAMETER; 1570 } 1571 Fcb = Ccb->Fcb; 1572 1573 if(Fcb && 1574 !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) && 1575 !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) ) { 1576 1577 // Disable PopUps, we want to return any error. 1578 IrpContext->IrpContextFlags |= UDF_IRP_CONTEXT_FLAG_DISABLE_POPUPS; 1579 1580 // Verify the Vcb. This will raise in the error condition. 1581 UDFVerifyVcb( IrpContext, Fcb->Vcb ); 1582 } 1583 1584 Irp->IoStatus.Information = 0; 1585 Irp->IoStatus.Status = STATUS_SUCCESS; 1586 1587 return STATUS_SUCCESS; 1588 } // end UDFIsVolumeMounted() 1589 1590 /* 1591 This routine returns the filesystem performance counters from the 1592 appropriate VCB. 1593 1594 Arguments: 1595 Irp - Supplies the Irp to process 1596 1597 Return Value: 1598 NTSTATUS - The return status for the operation 1599 */ 1600 NTSTATUS 1601 UDFGetStatistics( 1602 IN PtrUDFIrpContext IrpContext, 1603 IN PIRP Irp 1604 ) 1605 { 1606 PEXTENDED_IO_STACK_LOCATION IrpSp = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); 1607 NTSTATUS status; 1608 PVCB Vcb; 1609 1610 PFILE_SYSTEM_STATISTICS Buffer; 1611 ULONG BufferLength; 1612 ULONG StatsSize; 1613 ULONG BytesToCopy; 1614 1615 UDFPrint(("UDFGetStatistics\n")); 1616 1617 // Extract the buffer 1618 BufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; 1619 // Get a pointer to the output buffer. 1620 Buffer = (PFILE_SYSTEM_STATISTICS)(Irp->AssociatedIrp.SystemBuffer); 1621 1622 // Make sure the buffer is big enough for at least the common part. 1623 if (BufferLength < sizeof(FILESYSTEM_STATISTICS)) { 1624 status = STATUS_BUFFER_TOO_SMALL; 1625 Irp->IoStatus.Information = 0; 1626 goto EO_stat; 1627 } 1628 1629 // Now see how many bytes we can copy. 1630 StatsSize = sizeof(FILE_SYSTEM_STATISTICS) * KeNumberProcessors; 1631 if (BufferLength < StatsSize) { 1632 BytesToCopy = BufferLength; 1633 status = STATUS_BUFFER_OVERFLOW; 1634 } else { 1635 BytesToCopy = StatsSize; 1636 status = STATUS_SUCCESS; 1637 } 1638 1639 Vcb = (PVCB)(((PDEVICE_OBJECT)IrpSp->DeviceObject)->DeviceExtension); 1640 // Fill in the output buffer 1641 RtlCopyMemory( Buffer, Vcb->Statistics, BytesToCopy ); 1642 Irp->IoStatus.Information = BytesToCopy; 1643 EO_stat: 1644 Irp->IoStatus.Status = status; 1645 1646 return status; 1647 } // end UDFGetStatistics() 1648 1649 1650 /* 1651 This routine determines if pathname is valid path for UDF Filesystem 1652 1653 Arguments: 1654 Irp - Supplies the Irp to process 1655 1656 Return Value: 1657 NTSTATUS - The return status for the operation 1658 */ 1659 NTSTATUS 1660 UDFIsPathnameValid( 1661 IN PtrUDFIrpContext IrpContext, 1662 IN PIRP Irp 1663 ) 1664 { 1665 PEXTENDED_IO_STACK_LOCATION IrpSp = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); 1666 NTSTATUS RC; 1667 PPATHNAME_BUFFER PathnameBuffer; 1668 UNICODE_STRING PathName; 1669 UNICODE_STRING CurName; 1670 PWCHAR TmpBuffer; 1671 1672 UDFPrint(("UDFIsPathnameValid\n")); 1673 1674 // Extract the pathname 1675 PathnameBuffer = (PPATHNAME_BUFFER)Irp->AssociatedIrp.SystemBuffer; 1676 PathName.Buffer = PathnameBuffer->Name; 1677 PathName.Length = (USHORT)PathnameBuffer->PathNameLength; 1678 1679 _SEH2_TRY { 1680 // Check for an invalid buffer 1681 if (FIELD_OFFSET(PATHNAME_BUFFER, Name[0]) + PathnameBuffer->PathNameLength > 1682 IrpSp->Parameters.FileSystemControl.InputBufferLength) { 1683 try_return( RC = STATUS_INVALID_PARAMETER); 1684 } 1685 while (TRUE) { 1686 // get next path part... 1687 TmpBuffer = PathName.Buffer; 1688 PathName.Buffer = UDFDissectName(PathName.Buffer,&(CurName.Length) ); 1689 PathName.Length -= (USHORT)((ULONG_PTR)(PathName.Buffer) - (ULONG_PTR)TmpBuffer); 1690 CurName.Buffer = PathName.Buffer - CurName.Length; 1691 CurName.Length *= sizeof(WCHAR); 1692 CurName.MaximumLength -= CurName.Length; 1693 1694 if (CurName.Length) { 1695 // check path fragment size 1696 if (CurName.Length > UDF_NAME_LEN*sizeof(WCHAR)) { 1697 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1698 } 1699 if (!UDFIsNameValid(&CurName, NULL, NULL)) { 1700 try_return(RC = STATUS_OBJECT_NAME_INVALID); 1701 } 1702 } else { 1703 try_return(RC = STATUS_SUCCESS); 1704 } 1705 } 1706 try_exit: NOTHING; 1707 } _SEH2_FINALLY { 1708 Irp->IoStatus.Information = 0; 1709 Irp->IoStatus.Status = RC; 1710 } _SEH2_END; 1711 1712 return RC; 1713 } // end UDFIsPathnameValid() 1714 1715 /* 1716 This routine performs the lock volume operation. It is responsible for 1717 either completing of enqueuing the input Irp. 1718 Arguments: 1719 Irp - Supplies the Irp to process 1720 Return Value: 1721 NTSTATUS - The return status for the operation 1722 */ 1723 NTSTATUS 1724 UDFLockVolume( 1725 IN PtrUDFIrpContext IrpContext, 1726 IN PIRP Irp, 1727 IN ULONG PID 1728 ) 1729 { 1730 NTSTATUS RC; 1731 1732 KIRQL SavedIrql; 1733 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 1734 1735 PVCB Vcb; 1736 PtrUDFFCB Fcb; 1737 PtrUDFCCB Ccb; 1738 BOOLEAN VcbAcquired = FALSE; 1739 1740 UDFPrint(("UDFLockVolume: PID %x\n", PID)); 1741 1742 // Decode the file object, the only type of opens we accept are 1743 // user volume opens. 1744 Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2); 1745 if(!Ccb) { 1746 UDFPrintErr((" !Ccb\n")); 1747 Irp->IoStatus.Information = 0; 1748 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1749 return STATUS_INVALID_PARAMETER; 1750 } 1751 Fcb = Ccb->Fcb; 1752 Vcb = Fcb->Vcb; 1753 1754 // Check for volume open 1755 if (Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) { 1756 Irp->IoStatus.Information = 0; 1757 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1758 return STATUS_INVALID_PARAMETER; 1759 } 1760 1761 UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_LOCK); 1762 1763 _SEH2_TRY { 1764 1765 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) 1766 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo); 1767 #ifdef UDF_DELAYED_CLOSE 1768 UDFCloseAllDelayed(Vcb); 1769 #endif //UDF_DELAYED_CLOSE 1770 1771 // Acquire exclusive access to the Vcb. 1772 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE ); 1773 VcbAcquired = TRUE; 1774 1775 // Verify the Vcb. 1776 UDFVerifyVcb( IrpContext, Vcb ); 1777 1778 // If the volume is already locked then complete with success if this file 1779 // object has the volume locked, fail otherwise. 1780 /* if (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) { 1781 1782 if (Vcb->VolumeLockFileObject == IrpSp->FileObject) { 1783 RC = STATUS_SUCCESS; 1784 } else { 1785 RC = STATUS_ACCESS_DENIED; 1786 } 1787 // If the open count for the volume is greater than 1 then this request 1788 // will fail. 1789 } else if (Vcb->VCBOpenCount > UDF_RESIDUAL_REFERENCE+1) { 1790 RC = STATUS_ACCESS_DENIED; 1791 // We will try to get rid of all of the user references. If there is only one 1792 // remaining after the purge then we can allow the volume to be locked. 1793 } else { 1794 // flush system cache 1795 UDFReleaseResource( &(Vcb->VCBResource) ); 1796 VcbAcquired = FALSE; 1797 }*/ 1798 1799 } _SEH2_FINALLY { 1800 1801 // Release the Vcb. 1802 if(VcbAcquired) { 1803 UDFReleaseResource( &(Vcb->VCBResource) ); 1804 VcbAcquired = FALSE; 1805 } 1806 } _SEH2_END; 1807 1808 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE ); 1809 VcbAcquired = TRUE; 1810 UDFFlushLogicalVolume(NULL, NULL, Vcb/*, 0*/); 1811 UDFReleaseResource( &(Vcb->VCBResource) ); 1812 VcbAcquired = FALSE; 1813 // Check if the Vcb is already locked, or if the open file count 1814 // is greater than 1 (which implies that someone else also is 1815 // currently using the volume, or a file on the volume). 1816 IoAcquireVpbSpinLock( &SavedIrql ); 1817 1818 if (!(Vcb->Vpb->Flags & VPB_LOCKED) && 1819 (Vcb->VolumeLockPID == (ULONG)-1) && 1820 (Vcb->VCBOpenCount <= UDF_RESIDUAL_REFERENCE+1) && 1821 (Vcb->Vpb->ReferenceCount == 2)) { 1822 1823 // Mark volume as locked 1824 if(PID == (ULONG)-1) { 1825 Vcb->Vpb->Flags |= VPB_LOCKED; 1826 } 1827 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_LOCKED; 1828 Vcb->VolumeLockFileObject = IrpSp->FileObject; 1829 Vcb->VolumeLockPID = PID; 1830 1831 RC = STATUS_SUCCESS; 1832 1833 } else { 1834 1835 RC = STATUS_ACCESS_DENIED; 1836 } 1837 1838 IoReleaseVpbSpinLock( SavedIrql ); 1839 1840 if(!NT_SUCCESS(RC)) { 1841 UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_LOCK_FAILED); 1842 } 1843 1844 // Complete the request if there haven't been any exceptions. 1845 Irp->IoStatus.Information = 0; 1846 Irp->IoStatus.Status = RC; 1847 return RC; 1848 } // end UDFLockVolume() 1849 1850 /* 1851 This routine performs the unlock volume operation. It is responsible for 1852 either completing of enqueuing the input Irp. 1853 Arguments: 1854 Irp - Supplies the Irp to process 1855 Return Value: 1856 NTSTATUS - The return status for the operation 1857 */ 1858 NTSTATUS 1859 UDFUnlockVolume( 1860 IN PtrUDFIrpContext IrpContext, 1861 IN PIRP Irp, 1862 IN ULONG PID 1863 ) 1864 { 1865 NTSTATUS RC = STATUS_INVALID_PARAMETER; 1866 1867 KIRQL SavedIrql; 1868 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 1869 1870 PVCB Vcb; 1871 PtrUDFFCB Fcb; 1872 PtrUDFCCB Ccb; 1873 1874 UDFPrint(("UDFUnlockVolume: PID %x\n", PID)); 1875 1876 // Decode the file object, the only type of opens we accept are 1877 // user volume opens. 1878 Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2); 1879 if(!Ccb) { 1880 UDFPrintErr((" !Ccb\n")); 1881 Irp->IoStatus.Information = 0; 1882 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1883 return STATUS_INVALID_PARAMETER; 1884 } 1885 Fcb = Ccb->Fcb; 1886 Vcb = Fcb->Vcb; 1887 1888 // Check for volume open 1889 if(Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) { 1890 Irp->IoStatus.Information = 0; 1891 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1892 return STATUS_INVALID_PARAMETER; 1893 } 1894 1895 // Acquire exclusive access to the Vcb/Vpb. 1896 IoAcquireVpbSpinLock( &SavedIrql ); 1897 1898 _SEH2_TRY { 1899 1900 // We won't check for a valid Vcb for this request. An unlock will always 1901 // succeed on a locked volume. 1902 if(Vcb->Vpb->Flags & VPB_LOCKED || 1903 Vcb->VolumeLockPID == PID) { 1904 Vcb->Vpb->Flags &= ~VPB_LOCKED; 1905 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED; 1906 Vcb->VolumeLockFileObject = NULL; 1907 Vcb->VolumeLockPID = -1; 1908 UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_UNLOCK); 1909 RC = STATUS_SUCCESS; 1910 } else { 1911 RC = STATUS_NOT_LOCKED; 1912 RC = STATUS_SUCCESS; 1913 RC = STATUS_VOLUME_DISMOUNTED; 1914 } 1915 1916 } _SEH2_FINALLY { 1917 ; 1918 } _SEH2_END; 1919 1920 // Release all of our resources 1921 IoReleaseVpbSpinLock( SavedIrql ); 1922 1923 // Complete the request if there haven't been any exceptions. 1924 Irp->IoStatus.Information = 0; 1925 Irp->IoStatus.Status = RC; 1926 return RC; 1927 } // end UDFUnlockVolume() 1928 1929 1930 /* 1931 This routine performs the dismount volume operation. It is responsible for 1932 either completing of enqueuing the input Irp. We only dismount a volume which 1933 has been locked. The intent here is that someone has locked the volume (they are the 1934 only remaining handle). We set the verify bit here and the user will close his handle. 1935 We will dismount a volume with no user's handles in the verify path. 1936 Arguments: 1937 Irp - Supplies the Irp to process 1938 Return Value: 1939 NTSTATUS - The return status for the operation 1940 */ 1941 NTSTATUS 1942 UDFDismountVolume( 1943 IN PtrUDFIrpContext IrpContext, 1944 IN PIRP Irp 1945 ) 1946 { 1947 NTSTATUS RC; 1948 1949 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); 1950 1951 PVCB Vcb; 1952 PtrUDFFCB Fcb; 1953 PtrUDFCCB Ccb; 1954 PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL; 1955 BOOLEAN VcbAcquired = FALSE; 1956 1957 UDFPrint(("\n ### UDFDismountVolume ###\n\n")); 1958 1959 // Decode the file object, the only type of opens we accept are 1960 // user volume opens. 1961 Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2); 1962 if(!Ccb) { 1963 UDFPrintErr((" !Ccb\n")); 1964 Irp->IoStatus.Information = 0; 1965 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1966 return STATUS_INVALID_PARAMETER; 1967 } 1968 Fcb = Ccb->Fcb; 1969 Vcb = Fcb->Vcb; 1970 1971 // Check for volume open 1972 if(Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) { 1973 Irp->IoStatus.Information = 0; 1974 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 1975 return STATUS_INVALID_PARAMETER; 1976 } 1977 1978 UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_DISMOUNT); 1979 1980 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK)) 1981 UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo); 1982 #ifdef UDF_DELAYED_CLOSE 1983 UDFCloseAllDelayed(Vcb); 1984 #endif //UDF_DELAYED_CLOSE 1985 1986 // Acquire exclusive access to the Vcb. 1987 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE ); 1988 VcbAcquired = TRUE; 1989 1990 _SEH2_TRY { 1991 1992 // Mark the volume as needs to be verified, but only do it if 1993 // the vcb is locked by this handle and the volume is currently mounted. 1994 1995 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) { 1996 // disable Eject Request Waiter if any 1997 UDFReleaseResource( &(Vcb->VCBResource) ); 1998 VcbAcquired = FALSE; 1999 2000 UDFStopEjectWaiter(Vcb); 2001 RC = STATUS_SUCCESS; 2002 } else 2003 if(/*!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) ||*/ 2004 !(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) || 2005 (Vcb->VCBOpenCount > (UDF_RESIDUAL_REFERENCE+1))) { 2006 2007 RC = STATUS_NOT_LOCKED; 2008 } else 2009 if((Vcb->VolumeLockFileObject != IrpSp->FileObject)) { 2010 2011 RC = STATUS_INVALID_PARAMETER; 2012 2013 } else { 2014 2015 Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME; 2016 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN)); 2017 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES); 2018 UDFDoDismountSequence(Vcb, Buf, FALSE); 2019 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_MOUNTED; 2020 Vcb->WriteSecurity = FALSE; 2021 // disable Eject Request Waiter if any 2022 UDFReleaseResource( &(Vcb->VCBResource) ); 2023 VcbAcquired = FALSE; 2024 2025 UDFStopEjectWaiter(Vcb); 2026 RC = STATUS_SUCCESS; 2027 } 2028 try_exit: NOTHING; 2029 } _SEH2_FINALLY { 2030 // Free memory 2031 if(Buf) MyFreePool__(Buf); 2032 // Release all of our resources 2033 if(VcbAcquired) 2034 UDFReleaseResource( &(Vcb->VCBResource) ); 2035 } _SEH2_END; 2036 2037 if(!NT_SUCCESS(RC)) { 2038 UDFNotifyVolumeEvent(IrpSp->FileObject, FSRTL_VOLUME_DISMOUNT_FAILED); 2039 } 2040 2041 // Complete the request if there haven't been any exceptions. 2042 Irp->IoStatus.Information = 0; 2043 Irp->IoStatus.Status = RC; 2044 return RC; 2045 } // end UDFDismountVolume() 2046 2047 /* 2048 2049 This routine returns the volume allocation bitmap. 2050 2051 Input = the STARTING_LCN_INPUT_BUFFER data structure is passed in 2052 through the input buffer. 2053 Output = the VOLUME_BITMAP_BUFFER data structure is returned through 2054 the output buffer. 2055 2056 We return as much as the user buffer allows starting the specified input 2057 LCN (trucated to a byte). If there is no input buffer, we start at zero. 2058 2059 Arguments: 2060 2061 Irp - Supplies the Irp being processed. 2062 2063 Return Value: 2064 2065 NTSTATUS - The return status for the operation. 2066 2067 */ 2068 NTSTATUS 2069 UDFGetVolumeBitmap( 2070 IN PtrUDFIrpContext IrpContext, 2071 IN PIRP Irp 2072 ) 2073 { 2074 // NTSTATUS RC; 2075 2076 PEXTENDED_IO_STACK_LOCATION IrpSp = 2077 (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); 2078 2079 PVCB Vcb; 2080 PtrUDFFCB Fcb; 2081 PtrUDFCCB Ccb; 2082 2083 UDFPrint(("UDFGetVolumeBitmap\n")); 2084 2085 ULONG BytesToCopy; 2086 ULONG TotalClusters; 2087 ULONG DesiredClusters; 2088 ULONG StartingCluster; 2089 ULONG InputBufferLength; 2090 ULONG OutputBufferLength; 2091 LARGE_INTEGER StartingLcn; 2092 PVOLUME_BITMAP_BUFFER OutputBuffer; 2093 ULONG i, lim; 2094 PULONG FSBM; 2095 // PULONG Dest; 2096 ULONG LSh; 2097 2098 // Decode the file object, the only type of opens we accept are 2099 // user volume opens. 2100 Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2); 2101 if(!Ccb) { 2102 UDFPrintErr((" !Ccb\n")); 2103 Irp->IoStatus.Information = 0; 2104 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2105 return STATUS_INVALID_PARAMETER; 2106 } 2107 Fcb = Ccb->Fcb; 2108 Vcb = Fcb->Vcb; 2109 2110 InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; 2111 OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; 2112 2113 OutputBuffer = (PVOLUME_BITMAP_BUFFER)UDFGetCallersBuffer(IrpContext, Irp); 2114 if(!OutputBuffer) 2115 return STATUS_INVALID_USER_BUFFER; 2116 2117 // Check for a minimum length on the input and output buffers. 2118 if ((InputBufferLength < sizeof(STARTING_LCN_INPUT_BUFFER)) || 2119 (OutputBufferLength < sizeof(VOLUME_BITMAP_BUFFER))) { 2120 2121 UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); 2122 Irp->IoStatus.Information = 0; 2123 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; 2124 return STATUS_BUFFER_TOO_SMALL; 2125 } 2126 2127 // Check if a starting cluster was specified. 2128 TotalClusters = Vcb->FSBM_BitCount; 2129 StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn; 2130 2131 if (StartingLcn.HighPart || StartingLcn.LowPart >= TotalClusters) { 2132 2133 UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); 2134 Irp->IoStatus.Information = 0; 2135 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2136 return STATUS_INVALID_PARAMETER; 2137 2138 } else { 2139 2140 StartingCluster = StartingLcn.LowPart & ~7; 2141 } 2142 2143 OutputBufferLength -= FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer); 2144 DesiredClusters = TotalClusters - StartingCluster; 2145 2146 if (OutputBufferLength < (DesiredClusters + 7) / 8) { 2147 2148 BytesToCopy = OutputBufferLength; 2149 // RC = STATUS_BUFFER_OVERFLOW; 2150 2151 } else { 2152 2153 BytesToCopy = (DesiredClusters + 7) / 8; 2154 // RC = STATUS_SUCCESS; 2155 } 2156 2157 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE ); 2158 2159 _SEH2_TRY { 2160 2161 // Fill in the fixed part of the output buffer 2162 OutputBuffer->StartingLcn.QuadPart = StartingCluster; 2163 OutputBuffer->BitmapSize.QuadPart = DesiredClusters; 2164 2165 RtlZeroMemory( &OutputBuffer->Buffer[0], BytesToCopy ); 2166 lim = BytesToCopy * 8; 2167 FSBM = (PULONG)(Vcb->FSBM_Bitmap); 2168 LSh = Vcb->LB2B_Bits; 2169 // Dest = (PULONG)(&OutputBuffer->Buffer[0]); 2170 2171 for(i=StartingCluster & ~7; i<lim; i++) { 2172 if(UDFGetFreeBit(FSBM, i<<LSh)) 2173 UDFSetFreeBit(FSBM, i); 2174 } 2175 2176 } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) { 2177 2178 BrutePoint(); 2179 UDFPrintErr(("UDFGetVolumeBitmap: Exception\n")); 2180 // UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); 2181 BrutePoint(); 2182 // RC = UDFExceptionHandler(IrpContext, Irp); 2183 UDFReleaseResource(&(Vcb->VCBResource)); 2184 UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); 2185 2186 Irp->IoStatus.Information = 0; 2187 Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; 2188 return STATUS_INVALID_USER_BUFFER; 2189 } _SEH2_END; 2190 2191 UDFReleaseResource(&(Vcb->VCBResource)); 2192 2193 UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer); 2194 Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer) + 2195 BytesToCopy; 2196 Irp->IoStatus.Status = STATUS_SUCCESS; 2197 2198 return STATUS_SUCCESS; 2199 2200 2201 } // end UDFGetVolumeBitmap() 2202 2203 2204 NTSTATUS 2205 UDFGetRetrievalPointers( 2206 IN PtrUDFIrpContext IrpContext, 2207 IN PIRP Irp, 2208 IN ULONG Special 2209 ) 2210 { 2211 NTSTATUS RC; 2212 2213 PEXTENDED_IO_STACK_LOCATION IrpSp = 2214 (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); 2215 2216 PVCB Vcb; 2217 PtrUDFFCB Fcb; 2218 PtrUDFCCB Ccb; 2219 PUDF_FILE_INFO FileInfo; 2220 2221 ULONG InputBufferLength; 2222 ULONG OutputBufferLength; 2223 2224 PRETRIEVAL_POINTERS_BUFFER OutputBuffer; 2225 PSTARTING_VCN_INPUT_BUFFER InputBuffer; 2226 2227 LARGE_INTEGER StartingVcn; 2228 int64 AllocationSize; 2229 2230 PEXTENT_MAP SubMapping = NULL; 2231 ULONG SubExtInfoSz; 2232 ULONG i; 2233 ULONG LBS; 2234 ULONG LBSh; 2235 ULONG L2BSh; 2236 2237 UDFPrint(("UDFGetRetrievalPointers\n")); 2238 2239 // Decode the file object, the only type of opens we accept are 2240 // user volume opens. 2241 Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2); 2242 if(!Ccb) { 2243 UDFPrintErr((" !Ccb\n")); 2244 Irp->IoStatus.Information = 0; 2245 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2246 return STATUS_INVALID_PARAMETER; 2247 } 2248 Fcb = Ccb->Fcb; 2249 Vcb = Fcb->Vcb; 2250 2251 // Get the input and output buffer lengths and pointers. 2252 // Initialize some variables. 2253 InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength; 2254 OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength; 2255 2256 //OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFGetCallersBuffer( IrpContext, Irp ); 2257 if(Special) { 2258 OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->AssociatedIrp.SystemBuffer; 2259 } else { 2260 OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)Irp->UserBuffer; 2261 } 2262 InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer; 2263 if(!InputBuffer) { 2264 InputBuffer = (PSTARTING_VCN_INPUT_BUFFER)OutputBuffer; 2265 } 2266 2267 _SEH2_TRY { 2268 2269 Irp->IoStatus.Information = 0; 2270 // Check for a minimum length on the input and ouput buffers. 2271 if ((InputBufferLength < sizeof(STARTING_VCN_INPUT_BUFFER)) || 2272 (OutputBufferLength < sizeof(RETRIEVAL_POINTERS_BUFFER))) { 2273 2274 try_return( RC = STATUS_BUFFER_TOO_SMALL ); 2275 } 2276 2277 _SEH2_TRY { 2278 2279 if (Irp->RequestorMode != KernelMode) { 2280 ProbeForRead( IrpSp->Parameters.FileSystemControl.Type3InputBuffer, 2281 InputBufferLength, 2282 sizeof(UCHAR) ); 2283 ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(UCHAR) ); 2284 } 2285 StartingVcn = InputBuffer->StartingVcn; 2286 2287 } _SEH2_EXCEPT(Irp->RequestorMode != KernelMode ? EXCEPTION_EXECUTE_HANDLER: EXCEPTION_CONTINUE_SEARCH) { 2288 2289 RC = _SEH2_GetExceptionCode(); 2290 RC = FsRtlIsNtstatusExpected(RC) ? 2291 RC : STATUS_INVALID_USER_BUFFER; 2292 try_return(RC); 2293 } _SEH2_END; 2294 2295 switch(Special) { 2296 case 0: 2297 FileInfo = Fcb->FileInfo; 2298 break; 2299 case 1: 2300 FileInfo = Vcb->NonAllocFileInfo; 2301 break; 2302 default: 2303 try_return( RC = STATUS_INVALID_PARAMETER ); 2304 } 2305 2306 if(!FileInfo) { 2307 try_return( RC = STATUS_OBJECT_NAME_NOT_FOUND ); 2308 } 2309 2310 AllocationSize = UDFGetFileAllocationSize(Vcb, FileInfo); 2311 2312 LBS = Vcb->LBlockSize; 2313 LBSh = Vcb->LBlockSizeBits; 2314 L2BSh = Vcb->LB2B_Bits; 2315 2316 if (StartingVcn.HighPart || 2317 StartingVcn.LowPart >= (ULONG)(AllocationSize >> LBSh)) { 2318 2319 try_return( RC = STATUS_END_OF_FILE ); 2320 } 2321 2322 SubExtInfoSz = (OutputBufferLength - FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER, Extents[0])) / (sizeof(LARGE_INTEGER)*2); 2323 // re-use AllocationSize as NextVcn 2324 RC = UDFReadFileLocation__(Vcb, FileInfo, StartingVcn.QuadPart << LBSh, 2325 &SubMapping, &SubExtInfoSz, &AllocationSize); 2326 if(!NT_SUCCESS(RC)) 2327 try_return(RC); 2328 2329 OutputBuffer->ExtentCount = SubExtInfoSz; 2330 OutputBuffer->StartingVcn = StartingVcn; 2331 for(i=0; i<SubExtInfoSz; i++) { 2332 // assume, that 2333 // for not-allocated extents we have start Lba = -1 2334 // for not-recorded extents start Lba.LowPart contains real Lba, Lba.HighPart = 0x80000000 2335 // for recorded extents Lba.LowPart contains real Lba, Lba.HighPart = 0 2336 if(SubMapping[i].extLocation == LBA_NOT_ALLOCATED) { 2337 OutputBuffer->Extents[i].Lcn.QuadPart = (int64)(-1); 2338 } else 2339 if(SubMapping[i].extLocation & 0x80000000) { 2340 OutputBuffer->Extents[i].Lcn.LowPart = (SubMapping[i].extLocation & 0x7fffffff) >> L2BSh; 2341 OutputBuffer->Extents[i].Lcn.HighPart = 0x80000000; 2342 } else { 2343 OutputBuffer->Extents[i].Lcn.LowPart = SubMapping[i].extLocation >> L2BSh; 2344 OutputBuffer->Extents[i].Lcn.HighPart = 0; 2345 } 2346 // alignment for last sector 2347 SubMapping[i].extLength += LBS-1; 2348 StartingVcn.QuadPart += SubMapping[i].extLength >> LBSh; 2349 OutputBuffer->Extents[i].NextVcn = StartingVcn; 2350 } 2351 2352 Irp->IoStatus.Information = FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER, Extents[0]) + i * sizeof(LARGE_INTEGER) * 2; 2353 2354 try_exit: NOTHING; 2355 } _SEH2_FINALLY { 2356 2357 if(SubMapping) 2358 MyFreePool__(SubMapping); 2359 Irp->IoStatus.Status = RC; 2360 } _SEH2_END; 2361 2362 return RC; 2363 } // end UDFGetRetrievalPointers() 2364 2365 2366 NTSTATUS 2367 UDFIsVolumeDirty( 2368 IN PtrUDFIrpContext IrpContext, 2369 IN PIRP Irp 2370 ) 2371 { 2372 PULONG VolumeState; 2373 PEXTENDED_IO_STACK_LOCATION IrpSp = 2374 (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); 2375 2376 PVCB Vcb; 2377 PtrUDFFCB Fcb; 2378 PtrUDFCCB Ccb; 2379 2380 UDFPrint(("UDFIsVolumeDirty\n")); 2381 2382 Irp->IoStatus.Information = 0; 2383 2384 if (Irp->AssociatedIrp.SystemBuffer != NULL) { 2385 VolumeState = (PULONG)(Irp->AssociatedIrp.SystemBuffer); 2386 } else if (Irp->MdlAddress != NULL) { 2387 VolumeState = (PULONG)MmGetSystemAddressForMdl(Irp->MdlAddress); 2388 } else { 2389 UDFPrintErr((" STATUS_INVALID_USER_BUFFER\n")); 2390 Irp->IoStatus.Status = STATUS_INVALID_USER_BUFFER; 2391 return STATUS_INVALID_USER_BUFFER; 2392 } 2393 2394 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) { 2395 UDFPrintErr((" STATUS_BUFFER_TOO_SMALL\n")); 2396 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; 2397 return STATUS_BUFFER_TOO_SMALL; 2398 } 2399 2400 (*VolumeState) = 0; 2401 2402 // Decode the file object, the only type of opens we accept are 2403 // user volume opens. 2404 Ccb = (PtrUDFCCB)(IrpSp->FileObject->FsContext2); 2405 if(!Ccb) { 2406 UDFPrintErr((" !Ccb\n")); 2407 Irp->IoStatus.Information = 0; 2408 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2409 return STATUS_INVALID_PARAMETER; 2410 } 2411 Fcb = Ccb->Fcb; 2412 Vcb = Fcb->Vcb; 2413 2414 if(Vcb != (PVCB)Fcb || !(Ccb->CCBFlags & UDF_CCB_VOLUME_OPEN)) { 2415 UDFPrintErr((" !Volume\n")); 2416 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2417 return STATUS_INVALID_PARAMETER; 2418 } 2419 2420 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED)) { 2421 UDFPrintErr((" !Mounted\n")); 2422 Irp->IoStatus.Status = STATUS_VOLUME_DISMOUNTED; 2423 return STATUS_VOLUME_DISMOUNTED; 2424 } 2425 2426 if(Vcb->origIntegrityType == INTEGRITY_TYPE_OPEN) { 2427 UDFPrint((" Dirty\n")); 2428 (*VolumeState) |= VOLUME_IS_DIRTY; 2429 Irp->IoStatus.Information = sizeof(ULONG); 2430 } else { 2431 UDFPrint((" Clean\n")); 2432 } 2433 Irp->IoStatus.Status = STATUS_SUCCESS; 2434 2435 return STATUS_SUCCESS; 2436 2437 } // end UDFIsVolumeDirty() 2438 2439 2440 NTSTATUS 2441 UDFInvalidateVolumes( 2442 IN PtrUDFIrpContext IrpContext, 2443 IN PIRP Irp 2444 ) 2445 { 2446 NTSTATUS RC; 2447 PEXTENDED_IO_STACK_LOCATION IrpSp = 2448 (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp ); 2449 PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL; 2450 2451 UDFPrint(("UDFInvalidateVolumes\n")); 2452 2453 KIRQL SavedIrql; 2454 2455 LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0}; 2456 2457 HANDLE Handle; 2458 2459 PVPB NewVpb; 2460 PVCB Vcb; 2461 2462 PLIST_ENTRY Link; 2463 2464 PFILE_OBJECT FileToMarkBad; 2465 PDEVICE_OBJECT DeviceToMarkBad; 2466 2467 Irp->IoStatus.Information = 0; 2468 2469 // Check for the correct security access. 2470 // The caller must have the SeTcbPrivilege. 2471 if (IrpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL && 2472 IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST && 2473 IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_INVALIDATE_VOLUMES && 2474 !SeSinglePrivilegeCheck( TcbPrivilege, UserMode )) { 2475 UDFPrintErr(("UDFInvalidateVolumes: STATUS_PRIVILEGE_NOT_HELD\n")); 2476 Irp->IoStatus.Status = STATUS_PRIVILEGE_NOT_HELD; 2477 return STATUS_PRIVILEGE_NOT_HELD; 2478 } 2479 // Try to get a pointer to the device object from the handle passed in. 2480 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( HANDLE )) { 2481 UDFPrintErr(("UDFInvalidateVolumes: STATUS_INVALID_PARAMETER\n")); 2482 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; 2483 return STATUS_INVALID_PARAMETER; 2484 } 2485 2486 Handle = *((PHANDLE) Irp->AssociatedIrp.SystemBuffer); 2487 2488 RC = ObReferenceObjectByHandle( Handle, 2489 0, 2490 *IoFileObjectType, 2491 KernelMode, 2492 (PVOID*)&FileToMarkBad, 2493 NULL ); 2494 2495 if (!NT_SUCCESS(RC)) { 2496 UDFPrintErr(("UDFInvalidateVolumes: can't get handle, RC=%x\n", RC)); 2497 Irp->IoStatus.Status = RC; 2498 return RC; 2499 } 2500 2501 // We only needed the pointer, not a reference. 2502 ObDereferenceObject( FileToMarkBad ); 2503 2504 // Grab the DeviceObject from the FileObject. 2505 DeviceToMarkBad = FileToMarkBad->DeviceObject; 2506 2507 // Create a new Vpb for this device so that any new opens will mount 2508 // a new volume. 2509 NewVpb = (PVPB)DbgAllocatePoolWithTag( NonPagedPool, sizeof( VPB ), 'bpvU' ); 2510 if(!NewVpb) { 2511 UDFPrintErr(("UDFInvalidateVolumes: STATUS_INSUFFICIENT_RESOURCES\n")); 2512 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2513 return STATUS_INSUFFICIENT_RESOURCES; 2514 } 2515 RtlZeroMemory( NewVpb, sizeof( VPB ) ); 2516 2517 NewVpb->Type = IO_TYPE_VPB; 2518 NewVpb->Size = sizeof( VPB ); 2519 NewVpb->RealDevice = DeviceToMarkBad; 2520 NewVpb->Flags = DeviceToMarkBad->Vpb->Flags & VPB_REMOVE_PENDING; 2521 2522 // Acquire GlobalDataResource 2523 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE); 2524 2525 // Nothing can go wrong now. 2526 IoAcquireVpbSpinLock( &SavedIrql ); 2527 if (DeviceToMarkBad->Vpb->Flags & VPB_MOUNTED) { 2528 DeviceToMarkBad->Vpb = NewVpb; 2529 NewVpb = NULL; 2530 } 2531 ASSERT( DeviceToMarkBad->Vpb->DeviceObject == NULL ); 2532 IoReleaseVpbSpinLock( SavedIrql ); 2533 2534 if (NewVpb) { 2535 DbgFreePool( NewVpb ); 2536 } 2537 2538 // Walk through all of the Vcb's attached to the global data. 2539 Link = UDFGlobalData.VCBQueue.Flink; 2540 2541 //ASSERT(FALSE); 2542 2543 while (Link != &(UDFGlobalData.VCBQueue)) { 2544 // Get 'next' Vcb 2545 Vcb = CONTAINING_RECORD( Link, VCB, NextVCB ); 2546 // Move to the next link now since the current Vcb may be deleted. 2547 Link = Link->Flink; 2548 2549 // Acquire Vcb resource 2550 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE); 2551 2552 if (Vcb->Vpb->RealDevice == DeviceToMarkBad) { 2553 2554 if(!Buf) { 2555 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN)*2); 2556 if(!Buf) { 2557 UDFPrintErr(("UDFInvalidateVolumes: STATUS_INSUFFICIENT_RESOURCES (2)\n")); 2558 UDFReleaseResource(&(Vcb->VCBResource)); 2559 MyFreePool__(NewVpb); 2560 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; 2561 return STATUS_INSUFFICIENT_RESOURCES; 2562 } 2563 } 2564 2565 #ifdef UDF_DELAYED_CLOSE 2566 UDFPrint((" UDFInvalidateVolumes: set UDF_VCB_FLAGS_NO_DELAYED_CLOSE\n")); 2567 Vcb->VCBFlags |= UDF_VCB_FLAGS_NO_DELAYED_CLOSE; 2568 UDFReleaseResource(&(Vcb->VCBResource)); 2569 #endif //UDF_DELAYED_CLOSE 2570 2571 if(Vcb->RootDirFCB && Vcb->RootDirFCB->FileInfo) { 2572 UDFPrint((" UDFInvalidateVolumes: UDFCloseAllSystemDelayedInDir\n")); 2573 RC = UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo); 2574 ASSERT(OS_SUCCESS(RC)); 2575 } 2576 #ifdef UDF_DELAYED_CLOSE 2577 UDFPrint((" UDFInvalidateVolumes: UDFCloseAllDelayed\n")); 2578 UDFCloseAllDelayed(Vcb); 2579 //ASSERT(OS_SUCCESS(RC)); 2580 #endif //UDF_DELAYED_CLOSE 2581 2582 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE); 2583 2584 UDFDoDismountSequence(Vcb, Buf, FALSE); 2585 UDFReleaseResource(&(Vcb->VCBResource)); 2586 2587 UDFStopEjectWaiter(Vcb); 2588 UDFPrint(("UDFInvalidateVolumes: Vcb %x dismounted\n", Vcb)); 2589 break; 2590 } else { 2591 UDFPrint(("UDFInvalidateVolumes: skip Vcb %x\n", Vcb)); 2592 UDFReleaseResource(&(Vcb->VCBResource)); 2593 } 2594 2595 } 2596 // Once we have processed all the mounted logical volumes, we can release 2597 // all acquired global resources and leave (in peace :-) 2598 UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) ); 2599 2600 Irp->IoStatus.Status = STATUS_SUCCESS; 2601 2602 if(Buf) { 2603 UDFPrint(("UDFInvalidateVolumes: free buffer\n")); 2604 MyFreePool__(Buf); 2605 } 2606 2607 // drop volume completly 2608 UDFPrint(("UDFInvalidateVolumes: drop volume completly\n")); 2609 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE); 2610 UDFScanForDismountedVcb(IrpContext); 2611 UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) ); 2612 2613 UDFPrint(("UDFInvalidateVolumes: done\n")); 2614 return STATUS_SUCCESS; 2615 2616 } // end UDFInvalidateVolumes() 2617