1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
8 Module Name: FsCntrl.cpp
12 Contains code to handle the "File System IOCTL" dispatch entry point.
22 // define the file specific bug-check id
23 #define UDF_BUG_CHECK_ID UDF_FILE_FS_CONTROL
25 NTSTATUS
UDFBlankMount(IN PVCB Vcb
);
27 PDIR_INDEX_HDR
UDFDirIndexAlloc(IN uint_di i
);
30 Function: UDFFSControl()
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)
40 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
41 PIRP Irp
// I/O Request Packet
44 NTSTATUS RC
= STATUS_SUCCESS
;
45 PtrUDFIrpContext PtrIrpContext
;
46 BOOLEAN AreWeTopLevel
= FALSE
;
48 UDFPrint(("\nUDFFSControl: \n\n"));
50 FsRtlEnterFileSystem();
54 // set the top level context
55 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
59 // get an IRP context structure and issue the request
60 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
62 RC
= UDFCommonFSControl(PtrIrpContext
, Irp
);
64 RC
= STATUS_INSUFFICIENT_RESOURCES
;
65 Irp
->IoStatus
.Status
= RC
;
66 Irp
->IoStatus
.Information
= 0;
68 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
71 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
73 UDFPrintErr(("UDFFSControl: exception ***"));
74 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
76 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
80 IoSetTopLevelIrp(NULL
);
83 FsRtlExitFileSystem();
86 } // end UDFFSControl()
89 Function: UDFCommonFSControl()
92 The actual work is performed here.
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)
98 Return Value: STATUS_SUCCESS/Error
104 PtrUDFIrpContext PtrIrpContext
,
105 PIRP Irp
// I/O Request Packet
108 NTSTATUS RC
= STATUS_UNRECOGNIZED_VOLUME
;
109 PIO_STACK_LOCATION IrpSp
= NULL
;
110 // PDEVICE_OBJECT PtrTargetDeviceObject = NULL;
112 UDFPrint(("\nUDFCommonFSControl\n\n"));
117 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
120 switch ((IrpSp
)->MinorFunction
)
122 case IRP_MN_USER_FS_REQUEST
:
123 UDFPrint((" UDFFSControl: UserFsReq request ....\n"));
125 RC
= UDFUserFsCtrlRequest(PtrIrpContext
,Irp
);
127 case IRP_MN_MOUNT_VOLUME
:
129 UDFPrint((" UDFFSControl: MOUNT_VOLUME request ....\n"));
131 RC
= UDFMountVolume(PtrIrpContext
,Irp
);
133 case IRP_MN_VERIFY_VOLUME
:
135 UDFPrint((" UDFFSControl: VERIFY_VOLUME request ....\n"));
137 RC
= UDFVerifyVolume(Irp
);
140 UDFPrintErr((" UDFFSControl: STATUS_INVALID_DEVICE_REQUEST MinorFunction %x\n", (IrpSp
)->MinorFunction
));
141 RC
= STATUS_INVALID_DEVICE_REQUEST
;
143 Irp
->IoStatus
.Status
= RC
;
144 Irp
->IoStatus
.Information
= 0;
146 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
152 if (!_SEH2_AbnormalTermination()) {
153 // Free up the Irp Context
154 UDFPrint((" UDFCommonFSControl: finally\n"));
155 UDFReleaseIrpContext(PtrIrpContext
);
157 UDFPrint((" UDFCommonFSControl: finally after exception ***\n"));
162 } // end UDFCommonFSControl()
166 This is the common routine for implementing the user's requests made
167 through NtFsControlFile.
170 Irp - Supplies the Irp being processed
173 NTSTATUS - The return status for the operation
178 UDFUserFsCtrlRequest(
179 PtrUDFIrpContext IrpContext
,
184 PEXTENDED_IO_STACK_LOCATION IrpSp
= (PEXTENDED_IO_STACK_LOCATION
) IoGetCurrentIrpStackLocation( Irp
);
186 // Case on the control code.
187 switch ( IrpSp
->Parameters
.FileSystemControl
.FsControlCode
) {
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
:
198 UDFPrint(("UDFUserFsCtrlRequest: OPLOCKS\n"));
199 RC
= STATUS_INVALID_DEVICE_REQUEST
;
201 Irp
->IoStatus
.Information
= 0;
202 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
205 RC = UDFOplockRequest( IrpContext, Irp );
208 case FSCTL_INVALIDATE_VOLUMES
:
210 RC
= UDFInvalidateVolumes( IrpContext
, Irp
);
213 case FSCTL_MOVE_FILE:
215 case FSCTL_QUERY_ALLOCATED_RANGES:
216 case FSCTL_SET_ZERO_DATA:
217 case FSCTL_SET_SPARSE:
219 case FSCTL_MARK_VOLUME_DIRTY:
221 RC = UDFDirtyVolume( IrpContext, Irp );
225 case FSCTL_IS_VOLUME_DIRTY
:
227 RC
= UDFIsVolumeDirty(IrpContext
, Irp
);
230 case FSCTL_ALLOW_EXTENDED_DASD_IO
:
232 UDFPrint(("UDFUserFsCtrlRequest: FSCTL_ALLOW_EXTENDED_DASD_IO\n"));
233 // DASD i/o is always permitted
234 // So, no-op this call
237 Irp
->IoStatus
.Information
= 0;
238 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
241 case FSCTL_DISMOUNT_VOLUME
:
243 RC
= UDFDismountVolume( IrpContext
, Irp
);
246 case FSCTL_IS_VOLUME_MOUNTED
:
248 RC
= UDFIsVolumeMounted( IrpContext
, Irp
);
251 case FSCTL_FILESYSTEM_GET_STATISTICS
:
253 RC
= UDFGetStatistics( IrpContext
, Irp
);
256 case FSCTL_LOCK_VOLUME
:
258 RC
= UDFLockVolume( IrpContext
, Irp
);
261 case FSCTL_UNLOCK_VOLUME
:
263 RC
= UDFUnlockVolume( IrpContext
, Irp
);
266 case FSCTL_IS_PATHNAME_VALID
:
268 RC
= UDFIsPathnameValid( IrpContext
, Irp
);
271 case FSCTL_GET_VOLUME_BITMAP
:
273 UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_VOLUME_BITMAP\n"));
274 RC
= UDFGetVolumeBitmap( IrpContext
, Irp
);
277 case FSCTL_GET_RETRIEVAL_POINTERS
:
279 UDFPrint(("UDFUserFsCtrlRequest: FSCTL_GET_RETRIEVAL_POINTERS\n"));
280 RC
= UDFGetRetrievalPointers( IrpContext
, Irp
, 0 );
284 // We don't support any of the known or unknown requests.
287 UDFPrintErr(("UDFUserFsCtrlRequest: STATUS_INVALID_DEVICE_REQUEST for %x\n",
288 IrpSp
->Parameters
.FileSystemControl
.FsControlCode
));
289 RC
= STATUS_INVALID_DEVICE_REQUEST
;
291 Irp
->IoStatus
.Information
= 0;
292 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
296 IoCompleteRequest(Irp
,IO_DISK_INCREMENT
);
299 } // end UDFUserFsCtrlRequest()
304 This is the common routine for implementing the mount requests
307 Irp - Supplies the Irp being processed
310 NTSTATUS - The return status for the operation
316 IN PtrUDFIrpContext PtrIrpContext
,
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
;
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
;
338 TEST_UNIT_READY_USER_OUT TestUnitReadyBuffer
;
341 BOOLEAN VcbAcquired
= FALSE
;
342 BOOLEAN DeviceNotTouched
= TRUE
;
343 BOOLEAN Locked
= FALSE
;
347 UDFPrint(("\n !!! UDFMountVolume\n"));
348 // UDFPrint(("Build " VER_STR_PRODUCT "\n\n"));
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
)) {
357 if (filterDevExt
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_UDFFS_DEVOBJ
&&
358 filterDevExt
->NodeIdentifier
.NodeSize
== sizeof(UDFFS_DEV_EXTENSION
)) {
361 UDFPrintErr(("Invalid node type in FS or FILTER DeviceObject\n"));
364 // Get a pointer to the target physical/virtual device object.
365 TargetDeviceObject
= IrpSp
->Parameters
.MountVolume
.DeviceObject
;
367 if(((Characteristics
= TargetDeviceObject
->Characteristics
) & FILE_FLOPPY_DISKETTE
) ||
368 (UDFGlobalData
.UDFFlags
& UDF_DATA_FLAGS_BEING_UNLOADED
) ) {
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
)) {
377 if(TargetDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
) {
378 FsDeviceType
= FILE_DEVICE_CD_ROM_FILE_SYSTEM
;
379 #ifdef UDF_HDD_SUPPORT
381 if (TargetDeviceObject
->DeviceType
== FILE_DEVICE_DISK
) {
383 if(!UDFGetRegParameter(NULL
, REG_MOUNT_ON_ZIP_NAME
, FALSE
)) {
387 if(!UDFGetRegParameter(NULL
, REG_MOUNT_ON_HDD_NAME
, FALSE
)) {
391 FsDeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
392 #endif //UDF_HDD_SUPPORT
398 // Acquire GlobalDataResource
399 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
403 UDFScanForDismountedVcb(PtrIrpContext
);
405 if(WrongMedia
) try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
408 UDFPrint(("UDFMountVolume: removable media\n"));
409 // just remember current MediaChangeCount
410 // or fail if No Media ....
412 // experimental CHECK_VERIFY, for fucking BENQ DVD_DD_1620
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
,
419 &MediaChangeCount
,sizeof(ULONG
),
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
429 RC
= UDFPhSendIOCTL( IOCTL_CDRW_TEST_UNIT_READY
,
432 &TestUnitReadyBuffer
,sizeof(TEST_UNIT_READY_USER_OUT
),
434 UDFPrint(("UDFMountVolume: TEST_UNIT_READY %x\n", RC
));
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
448 UDFPrint(("UDFMountVolume: additional delay 3 sec\n"));
449 delay
.QuadPart
= -30000000LL; // 3.0 sec
450 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
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
,
459 &MediaChangeCount
,sizeof(ULONG
),
462 if(RC
== STATUS_IO_DEVICE_ERROR
) {
463 UDFPrint(("UDFMountVolume: retry check verify\n"));
464 RC
= UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY
,
467 &MediaChangeCount
,sizeof(ULONG
),
471 if(!NT_SUCCESS(RC
) && (RC
!= STATUS_VERIFY_REQUIRED
))
474 // Be safe about the count in case the driver didn't fill it in
475 if(Iosb
.Information
!= sizeof(ULONG
)) {
476 MediaChangeCount
= 0;
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.
485 ioBuf
= (int8
*)MyAllocatePool__(NonPagedPool
,4096);
487 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
489 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY
,TargetDeviceObject
,
490 ioBuf
,sizeof(DISK_GEOMETRY
),
491 ioBuf
,sizeof(DISK_GEOMETRY
),
494 if(RC
== STATUS_DEVICE_NOT_READY
) {
495 // probably, the device is really busy, may be by CD/DVD recording
496 UserPrint((" busy (*)\n"));
501 // lock media for now
503 ((PPREVENT_MEDIA_REMOVAL_USER_IN
)(&MediaChangeCount
))->PreventMediaRemoval
= TRUE
;
504 RC
= UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL
,
506 &MediaChangeCount
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
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
,
525 if(!NT_SUCCESS(RC
)) try_return(RC
);
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
;
533 VolDo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
535 // device object field in the VPB to point to our new volume device
537 Vpb
->DeviceObject
= (PDEVICE_OBJECT
) VolDo
;
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);
543 Vcb
= (PVCB
)VolDo
->DeviceExtension
;
545 // Initialize the Vcb. This routine will raise on an allocation
547 RC
= UDFInitializeVCB(VolDo
,TargetDeviceObject
,Vpb
);
548 if(!NT_SUCCESS(RC
)) {
556 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
559 // Let's reference the Vpb to make sure we are the one to
560 // have the last dereference.
561 Vcb
->Vpb
->ReferenceCount
++;
563 Vcb
->MediaChangeCount
= MediaChangeCount
;
564 Vcb
->FsDeviceType
= FsDeviceType
;
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
;
572 DeviceNotTouched
= FALSE
;
573 RC
= UDFGetDiskInfo(TargetDeviceObject
,Vcb
);
574 if(!NT_SUCCESS(RC
)) try_return(RC
);
576 // **** Read registry settings ****
577 UDFReadRegKeys(Vcb
, FALSE
, FALSE
);
579 Vcb
->MountPhErrorCount
= 0;
581 // Initialize internal cache
582 Mode
= WCACHE_MODE_ROM
;
583 RC
= WCacheInit__(&(Vcb
->FastCache
),
584 Vcb
->WCacheMaxFrames
,
585 Vcb
->WCacheMaxBlocks
,
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
,
598 UDFTWriteAsync
, UDFTReadAsync
,
601 #endif //UDF_ASYNC_IO
604 UDFWCacheErrorHandler
);
605 if(!NT_SUCCESS(RC
)) try_return(RC
);
608 if(!NT_SUCCESS(RC
)) try_return(RC
);
610 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
611 RC
= UDFGetDiskInfoAndVerify(TargetDeviceObject
,Vcb
);
612 UDFReleaseResource(&(Vcb
->BitMapResource1
));
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
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
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
;
632 UDFPrint(("UDFMountVolume: try raw mount (2)\n"));
633 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
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
));
645 RC
= UDFBlankMount(Vcb
);
646 if(!NT_SUCCESS(RC
)) try_return(RC
);
649 // Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
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"));
659 if((FsDeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
660 CdrwMediaClassEx_IsRAM(Vcb
->MediaClassEx
)) {
661 UDFPrint(("UDFMountVolume: RAM mode\n"));
662 Mode
= WCACHE_MODE_RAM
;
664 UDFPrint(("UDFMountVolume: RW mode\n"));
665 Mode
= WCACHE_MODE_RW
;
667 /* if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
669 Vcb->WriteSecurity = TRUE;
672 UDFPrint(("UDFMountVolume: R mode\n"));
673 Mode
= WCACHE_MODE_R
;
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
;
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
;
702 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_RAW_DISK
;
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
);
710 UDFPrint(("UDFMountVolume: RO mount\n"));
711 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
713 #endif //UDF_READ_ONLY_BUILD
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
);
721 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_MOUNTED
;
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
;
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
,
740 &MediaChangeCount
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
743 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
)
744 UDFResetDeviceDriver(Vcb
, Vcb
->TargetDeviceObject
, TRUE
);
748 if (UDFGlobalData
.MountEvent
)
750 Vcb
->IsVolumeJustMounted
= TRUE
;
751 KeSetEvent(UDFGlobalData
.MountEvent
, 0, FALSE
);
754 // The new mount is complete.
755 UDFReleaseResource( &(Vcb
->VCBResource
) );
764 UDFPrint(("UDFMountVolume: RC = %x\n", RC
));
770 if(!NT_SUCCESS(RC
)) {
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
,
777 &MediaChangeCount
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
781 /* if((RC != STATUS_DEVICE_NOT_READY) &&
782 (RC != STATUS_NO_MEDIA_IN_DEVICE) ) {*/
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
);
790 if(RC
== STATUS_CRC_ERROR
|| RC
== STATUS_FILE_CORRUPT_ERROR
) {
791 UDFPrint(("UDFMountVolume: status -> STATUS_UNRECOGNIZED_VOLUME\n"));
792 RC
= STATUS_UNRECOGNIZED_VOLUME
;
795 // If we didn't complete the mount then cleanup any remaining structures.
797 Vpb
->DeviceObject
= NULL
;
801 // Restore the verify bit.
802 if(RestoreDoVerify
) {
803 Vcb
->Vpb
->RealDevice
->Flags
|= DO_VERIFY_VOLUME
;
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
) );
813 IoDeleteDevice( VolDo
);
816 // Release the global resource.
817 UDFReleaseResource( &(UDFGlobalData
.GlobalDataResource
) );
819 if (CompleteIrp
|| NT_SUCCESS(RC
)) {
820 if(!_SEH2_AbnormalTermination()) {
823 UDFPrint(("UDFMountVolume: complete req RC %x\n", RC
));
824 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_MOUNT
);
826 Irp
->IoStatus
.Status
= RC
;
827 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
830 // Pass Irp to lower driver (CDFS)
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
++;
837 // Now call the appropriate file system driver with the request.
838 RC
= IoCallDriver( filterDevExt
->lowerFSDeviceObject
, Irp
);
844 UDFPrint(("UDFMountVolume: final RC = %x\n", RC
));
847 } // end UDFMountVolume()
855 PREVENT_MEDIA_REMOVAL_USER_IN Buff
;
856 UDFPrint(("UDFStartEjectWaiter:\n"));
858 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_READ_ONLY
) {
859 UDFPrint((" UDF_VCB_FLAGS_MEDIA_READ_ONLY\n"));
861 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_LOCKED
) {
862 UDFPrint((" UDF_VCB_FLAGS_MEDIA_LOCKED\n"));
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
)) {
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
;
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
,
884 &Buff
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
887 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_MEDIA_LOCKED
;
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
);
907 UDFPrint((" ignore\n"));
909 return STATUS_SUCCESS
;
910 } // end UDFStartEjectWaiter()
917 NTSTATUS RC
;// = STATUS_SUCCESS;
918 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
919 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader
= NULL
;
920 UNICODE_STRING LocalPath
;
921 PtrUDFObjectName RootName
;
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
);
929 UDFPrint(("UDFCompleteMount: alloc Root FCB\n"));
930 // Create the root index and reference it in the Vcb.
932 Vcb
->RootDirFCB
= UDFAllocateFCB();
933 if(!RootFcb
) return STATUS_INSUFFICIENT_RESOURCES
;
935 UDFPrint(("UDFCompleteMount: alloc Root ObjName\n"));
936 // Allocate and set root FCB unique name
937 RootName
= UDFAllocateObjectName();
939 UDFCleanUpFCB(RootFcb
);
940 Vcb
->RootDirFCB
= NULL
;
941 return STATUS_INSUFFICIENT_RESOURCES
;
943 RC
= MyInitUnicodeString(&(RootName
->ObjectName
),UDF_ROOTDIR_NAME
);
947 RootFcb
->FileInfo
= (PUDF_FILE_INFO
)MyAllocatePool__(NonPagedPool
,sizeof(UDF_FILE_INFO
));
948 if(!RootFcb
->FileInfo
) {
949 RC
= STATUS_INSUFFICIENT_RESOURCES
;
951 MyFreePool__(RootName
->ObjectName
.Buffer
);
952 UDFReleaseObjectName(RootName
);
953 UDFCleanUpFCB(RootFcb
);
954 Vcb
->RootDirFCB
= NULL
;
957 UDFPrint(("UDFCompleteMount: open Root Dir\n"));
958 // Open Root Directory
959 RC
= UDFOpenRootFile__( Vcb
, &(Vcb
->RootLbAddr
), RootFcb
->FileInfo
);
960 if(!NT_SUCCESS(RC
)) {
962 UDFCleanUpFile__(Vcb
, RootFcb
->FileInfo
);
963 MyFreePool__(RootFcb
->FileInfo
);
966 RootFcb
->FileInfo
->Fcb
= RootFcb
;
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
;
975 RtlZeroMemory(RootFcb
->NTRequiredFCB
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
)));
976 RootFcb
->FileInfo
->Dloc
->CommonFcb
= RootFcb
->NTRequiredFCB
;
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;
986 UDFCleanUpFile__(Vcb
, RootFcb
->FileInfo
);
987 MyFreePool__(RootFcb
->FileInfo
);
988 MyFreePool__(RootFcb
->NTRequiredFCB
);
989 UDFCleanUpFCB(RootFcb
);
990 Vcb
->RootDirFCB
= NULL
;
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;
1000 UDFGetFileXTime(RootFcb
->FileInfo
,
1001 &(RootFcb
->NTRequiredFCB
->CreationTime
.QuadPart
),
1002 &(RootFcb
->NTRequiredFCB
->LastAccessTime
.QuadPart
),
1003 &(RootFcb
->NTRequiredFCB
->ChangeTime
.QuadPart
),
1004 &(RootFcb
->NTRequiredFCB
->LastWriteTime
.QuadPart
) );
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
;
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
;
1020 Vcb
->SysSDirFileInfo
->Dloc
->DataLoc
.Flags
|= EXTENT_FLAG_VERIFY
;
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
);
1032 if(!NT_SUCCESS(RC
) && (RC
!= STATUS_OBJECT_NAME_NOT_FOUND
)) {
1035 UDFCleanUpFile__(Vcb
, Vcb
->NonAllocFileInfo
);
1036 Vcb
->NonAllocFileInfo
= NULL
;
1037 // this was a part of UDF_RESIDUAL_REFERENCE
1038 UDFInterlockedDecrement((PLONG
)&(Vcb
->VCBOpenCount
));
1041 // UDFCloseResidual() will clean up everything
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
;
1051 /* try to read Non-allocatable from alternate locations */
1052 RC
= MyInitUnicodeString(&LocalPath
, UDF_FN_NON_ALLOCATABLE_2
);
1053 if(!NT_SUCCESS(RC
)) {
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
)) {
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
;
1065 if(Vcb
->SysSDirFileInfo
) {
1066 RC
= MyInitUnicodeString(&LocalPath
, UDF_SN_NON_ALLOCATABLE
);
1067 if(!NT_SUCCESS(RC
)) {
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
)) {
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;
1079 RC
= STATUS_SUCCESS
;
1082 RC
= STATUS_SUCCESS
;
1086 /* Read SN UID mapping */
1087 if(Vcb
->SysSDirFileInfo
) {
1088 RC
= MyInitUnicodeString(&LocalPath
, UDF_SN_UID_MAPPING
);
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
)) {
1095 // UDFCloseFile__(Vcb, Vcb->NonAllocFileInfo);
1096 // UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo);
1097 // if(Vcb->NonAllocFileInfo)
1098 // MyFreePool__(Vcb->NonAllocFileInfo);
1099 // Vcb->NonAllocFileInfo = NULL;
1102 Vcb
->UniqueIDMapFileInfo
->Dloc
->DataLoc
.Flags
|= EXTENT_FLAG_VERIFY
;
1104 RC
= STATUS_SUCCESS
;
1107 #define DWN_MAX_CFG_FILE_SIZE 0x10000
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
)) {
1115 PUDF_FILE_INFO CfgFileInfo
= NULL
;
1117 RC
= UDFOpenFile__(Vcb
, FALSE
, TRUE
, &LocalPath
, RootFcb
->FileInfo
, &CfgFileInfo
, NULL
);
1118 if(OS_SUCCESS(RC
)) {
1120 len
= (ULONG
)UDFGetFileSize(CfgFileInfo
);
1121 if(len
&& len
< DWN_MAX_CFG_FILE_SIZE
) {
1122 buff
= (int8
*)MyAllocatePool__(NonPagedPool
, len
);
1124 RC
= UDFReadFile__(Vcb
, CfgFileInfo
, 0, len
, FALSE
, buff
, &len
);
1125 if(OS_SUCCESS(RC
)) {
1127 Vcb
->Cfg
= (PUCHAR
)buff
;
1128 Vcb
->CfgLength
= len
;
1129 UDFReadRegKeys(Vcb
, TRUE
/*update*/, TRUE
/*cfg*/);
1132 Vcb
->CfgVersion
= 0;
1138 UDFCloseFile__(Vcb
, CfgFileInfo
);
1141 UDFCleanUpFile__(Vcb
, CfgFileInfo
);
1143 MyFreePool__(LocalPath
.Buffer
);
1145 RC
= STATUS_SUCCESS
;
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
));
1156 NtReqFcb
= RootFcb
->NTRequiredFCB
;
1158 // Start initializing the fields contained in the CommonFCBHeader.
1159 PtrCommonFCBHeader
= &(NtReqFcb
->CommonFCBHeader
);
1161 // DisAllow fast-IO for now.
1162 // PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible;
1163 PtrCommonFCBHeader
->IsFastIoPossible
= FastIoIsPossible
;
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);
1171 // Initialize the file size values here.
1172 PtrCommonFCBHeader
->AllocationSize
.QuadPart
= 0;
1173 PtrCommonFCBHeader
->FileSize
.QuadPart
= 0;
1175 // The following will disable ValidDataLength support.
1176 // PtrCommonFCBHeader->ValidDataLength.QuadPart = 0x7FFFFFFFFFFFFFFFI64;
1177 PtrCommonFCBHeader
->ValidDataLength
.QuadPart
= 0;
1181 UDFAssignAcl(Vcb
, NULL
, RootFcb
, NtReqFcb
);
1183 Vcb->CDBurnerVolumeValid = true;
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,
1191 Vcb->CDBurnerVolume.Length = (USHORT)(wcslen(Vcb->CDBurnerVolume.Buffer)*sizeof(WCHAR));
1193 if(RC != STATUS_OBJECT_NAME_NOT_FOUND && !NT_SUCCESS(RC) )
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);
1202 Vcb->CDBurnerVolumeValid = false;
1203 RC = STATUS_SUCCESS;
1206 ASSERT(!Vcb
->Modified
);
1209 } // end UDFCompleteMount()
1216 NTSTATUS RC
;// = STATUS_SUCCESS;
1217 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
1218 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader
= NULL
;
1219 PtrUDFObjectName RootName
;
1221 PDIR_INDEX_HDR hDirNdx
;
1222 PDIR_INDEX_ITEM DirNdx
;
1224 // Create the root index and reference it in the Vcb.
1226 Vcb
->RootDirFCB
= UDFAllocateFCB();
1227 if(!RootFcb
) return STATUS_INSUFFICIENT_RESOURCES
;
1228 RtlZeroMemory(RootFcb
,sizeof(UDFFCB
));
1230 // Allocate and set root FCB unique name
1231 RootName
= UDFAllocateObjectName();
1234 UDFCleanUpFCB(RootFcb
);
1235 Vcb
->RootDirFCB
= NULL
;
1236 return STATUS_INSUFFICIENT_RESOURCES
;
1238 RC
= MyInitUnicodeString(&(RootName
->ObjectName
),UDF_ROOTDIR_NAME
);
1242 RootFcb
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_FCB
;
1243 RootFcb
->NodeIdentifier
.NodeSize
= sizeof(UDFFCB
);
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
;
1250 UDFReleaseObjectName(RootName
);
1251 UDFCleanUpFCB(RootFcb
);
1252 Vcb
->RootDirFCB
= NULL
;
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
);
1262 RootFcb
->FileInfo
->NextLinkedFile
=
1263 RootFcb
->FileInfo
->PrevLinkedFile
= RootFcb
->FileInfo
;
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
);
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
;
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
);
1283 RootFcb
->FileInfo
->Dloc
->DirIndex
= hDirNdx
;
1284 RootFcb
->FileInfo
->Fcb
= RootFcb
;
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
;
1295 RtlZeroMemory(RootFcb
->NTRequiredFCB
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
)));
1296 RootFcb
->FileInfo
->Dloc
->CommonFcb
= RootFcb
->NTRequiredFCB
;
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;
1305 UDFCleanUpFile__(Vcb
, RootFcb
->FileInfo
);
1306 MyFreePool__(RootFcb
->FileInfo
);
1307 MyFreePool__(RootFcb
->NTRequiredFCB
);
1308 UDFCleanUpFCB(RootFcb
);
1309 Vcb
->RootDirFCB
= NULL
;
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;
1321 // this is a part of UDF_RESIDUAL_REFERENCE
1322 UDFInterlockedIncrement((PLONG
)&(Vcb
->VCBOpenCount
));
1324 NtReqFcb
= RootFcb
->NTRequiredFCB
;
1326 // Start initializing the fields contained in the CommonFCBHeader.
1327 PtrCommonFCBHeader
= &(NtReqFcb
->CommonFCBHeader
);
1329 // DisAllow fast-IO for now.
1330 PtrCommonFCBHeader
->IsFastIoPossible
= FastIoIsNotPossible
;
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
);
1338 // Initialize the file size values here.
1339 PtrCommonFCBHeader
->AllocationSize
.QuadPart
= 0;
1340 PtrCommonFCBHeader
->FileSize
.QuadPart
= 0;
1342 // The following will disable ValidDataLength support.
1343 PtrCommonFCBHeader
->ValidDataLength
.QuadPart
= 0x7FFFFFFFFFFFFFFFLL
;
1346 } // end UDFBlankMount()
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
;
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
;
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
;
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
;
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--;
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;
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;
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
;
1425 } // end UDFCloseResidual()
1433 UDFReleaseFileIdCache(Vcb
);
1434 UDFReleaseDlocList(Vcb
);
1435 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1439 if(Vcb
->ShutdownRegistered
&& Vcb
->VCBDeviceObject
) {
1440 IoUnregisterShutdownNotification(Vcb
->VCBDeviceObject
);
1441 Vcb
->ShutdownRegistered
= FALSE
;
1444 MyFreeMemoryAndPointer(Vcb
->Partitions
);
1445 MyFreeMemoryAndPointer(Vcb
->LVid
);
1446 MyFreeMemoryAndPointer(Vcb
->Vat
);
1447 MyFreeMemoryAndPointer(Vcb
->SparingTable
);
1449 if(Vcb
->FSBM_Bitmap
) {
1450 DbgFreePool(Vcb
->FSBM_Bitmap
);
1451 Vcb
->FSBM_Bitmap
= NULL
;
1453 if(Vcb
->ZSBM_Bitmap
) {
1454 DbgFreePool(Vcb
->ZSBM_Bitmap
);
1455 Vcb
->ZSBM_Bitmap
= NULL
;
1457 if(Vcb
->BSBM_Bitmap
) {
1458 DbgFreePool(Vcb
->BSBM_Bitmap
);
1459 Vcb
->BSBM_Bitmap
= NULL
;
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
;
1466 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1467 if(Vcb
->FSBM_OldBitmap
) {
1468 DbgFreePool(Vcb
->FSBM_OldBitmap
);
1469 Vcb
->FSBM_OldBitmap
= NULL
;
1472 MyFreeMemoryAndPointer(Vcb
->Statistics
);
1473 MyFreeMemoryAndPointer(Vcb
->NTRequiredFCB
);
1474 MyFreeMemoryAndPointer(Vcb
->VolIdent
.Buffer
);
1475 MyFreeMemoryAndPointer(Vcb
->TargetDevName
.Buffer
);
1478 DbgFreePool(Vcb
->ZBuffer
);
1479 Vcb
->ZBuffer
= NULL
;
1483 DbgFreePool(Vcb
->fZBuffer
);
1484 Vcb
->fZBuffer
= NULL
;
1487 MyFreeMemoryAndPointer(Vcb
->OPCh
);
1488 MyFreeMemoryAndPointer(Vcb
->WParams
);
1489 MyFreeMemoryAndPointer(Vcb
->Error
);
1490 MyFreeMemoryAndPointer(Vcb
->TrackMap
);
1492 } // end UDFCleanupVCB()
1496 Routine Description:
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.
1510 UDFScanForDismountedVcb(
1511 IN PtrUDFIrpContext IrpContext
1518 // Walk through all of the Vcb's attached to the global data.
1519 Link
= UDFGlobalData
.VCBQueue
.Flink
;
1521 while (Link
!= &(UDFGlobalData
.VCBQueue
)) {
1523 Vcb
= CONTAINING_RECORD( Link
, VCB
, NextVCB
);
1525 // Move to the next link now since the current Vcb may be deleted.
1528 // If dismount is already underway then check if this Vcb can
1530 if((Vcb
->VCBFlags
& UDF_VCB_FLAGS_BEING_DISMOUNTED
) ||
1531 ((!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
)) && (Vcb
->VCBOpenCount
<= UDF_RESIDUAL_REFERENCE
))) {
1533 UDFCheckForDismount( IrpContext
, Vcb
, FALSE
);
1538 } // end UDFScanForDismountedVcb()
1541 Routine Description:
1542 This routine determines if a volume is currently mounted.
1545 Irp - Supplies the Irp to process
1548 NTSTATUS - The return status for the operation
1553 IN PtrUDFIrpContext IrpContext
,
1557 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1562 UDFPrint(("UDFIsVolumeMounted\n"));
1564 Ccb
= (PtrUDFCCB
)IrpSp
->FileObject
->FsContext2
;
1566 UDFPrintErr((" !Ccb\n"));
1567 Irp
->IoStatus
.Information
= 0;
1568 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1569 return STATUS_INVALID_PARAMETER
;
1574 !(Fcb
->Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) &&
1575 !(Fcb
->Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_LOCKED
) ) {
1577 // Disable PopUps, we want to return any error.
1578 IrpContext
->IrpContextFlags
|= UDF_IRP_CONTEXT_FLAG_DISABLE_POPUPS
;
1580 // Verify the Vcb. This will raise in the error condition.
1581 UDFVerifyVcb( IrpContext
, Fcb
->Vcb
);
1584 Irp
->IoStatus
.Information
= 0;
1585 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1587 return STATUS_SUCCESS
;
1588 } // end UDFIsVolumeMounted()
1591 This routine returns the filesystem performance counters from the
1595 Irp - Supplies the Irp to process
1598 NTSTATUS - The return status for the operation
1602 IN PtrUDFIrpContext IrpContext
,
1606 PEXTENDED_IO_STACK_LOCATION IrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
1610 PFILE_SYSTEM_STATISTICS Buffer
;
1615 UDFPrint(("UDFGetStatistics\n"));
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
);
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;
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
;
1635 BytesToCopy
= StatsSize
;
1636 status
= STATUS_SUCCESS
;
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
;
1644 Irp
->IoStatus
.Status
= status
;
1647 } // end UDFGetStatistics()
1651 This routine determines if pathname is valid path for UDF Filesystem
1654 Irp - Supplies the Irp to process
1657 NTSTATUS - The return status for the operation
1661 IN PtrUDFIrpContext IrpContext
,
1665 PEXTENDED_IO_STACK_LOCATION IrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
1667 PPATHNAME_BUFFER PathnameBuffer
;
1668 UNICODE_STRING PathName
;
1669 UNICODE_STRING CurName
;
1672 UDFPrint(("UDFIsPathnameValid\n"));
1674 // Extract the pathname
1675 PathnameBuffer
= (PPATHNAME_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
1676 PathName
.Buffer
= PathnameBuffer
->Name
;
1677 PathName
.Length
= (USHORT
)PathnameBuffer
->PathNameLength
;
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
);
1686 // get next path part...
1687 TmpBuffer
= PathName
.Buffer
;
1688 PathName
.Buffer
= UDFDissectName(PathName
.Buffer
,&(CurName
.Length
) );
1689 PathName
.Length
-= (USHORT
)((ULONG
)(PathName
.Buffer
) - (ULONG
)TmpBuffer
);
1690 CurName
.Buffer
= PathName
.Buffer
- CurName
.Length
;
1691 CurName
.Length
*= sizeof(WCHAR
);
1692 CurName
.MaximumLength
-= CurName
.Length
;
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
);
1699 if (!UDFIsNameValid(&CurName
, NULL
, NULL
)) {
1700 try_return(RC
= STATUS_OBJECT_NAME_INVALID
);
1703 try_return(RC
= STATUS_SUCCESS
);
1708 Irp
->IoStatus
.Information
= 0;
1709 Irp
->IoStatus
.Status
= RC
;
1713 } // end UDFIsPathnameValid()
1716 This routine performs the lock volume operation. It is responsible for
1717 either completing of enqueuing the input Irp.
1719 Irp - Supplies the Irp to process
1721 NTSTATUS - The return status for the operation
1725 IN PtrUDFIrpContext IrpContext
,
1733 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1738 BOOLEAN VcbAcquired
= FALSE
;
1740 UDFPrint(("UDFLockVolume: PID %x\n", PID
));
1742 // Decode the file object, the only type of opens we accept are
1743 // user volume opens.
1744 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
1746 UDFPrintErr((" !Ccb\n"));
1747 Irp
->IoStatus
.Information
= 0;
1748 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1749 return STATUS_INVALID_PARAMETER
;
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
;
1761 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_LOCK
);
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
1771 // Acquire exclusive access to the Vcb.
1772 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
1776 UDFVerifyVcb( IrpContext
, Vcb
);
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) {
1782 if (Vcb->VolumeLockFileObject == IrpSp->FileObject) {
1783 RC = STATUS_SUCCESS;
1785 RC = STATUS_ACCESS_DENIED;
1787 // If the open count for the volume is greater than 1 then this request
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.
1794 // flush system cache
1795 UDFReleaseResource( &(Vcb->VCBResource) );
1796 VcbAcquired = FALSE;
1803 UDFReleaseResource( &(Vcb
->VCBResource
) );
1804 VcbAcquired
= FALSE
;
1808 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), 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
);
1818 if (!(Vcb
->Vpb
->Flags
& VPB_LOCKED
) &&
1819 (Vcb
->VolumeLockPID
== (ULONG
)-1) &&
1820 (Vcb
->VCBOpenCount
<= UDF_RESIDUAL_REFERENCE
+1) &&
1821 (Vcb
->Vpb
->ReferenceCount
== 2)) {
1823 // Mark volume as locked
1824 if(PID
== (ULONG
)-1) {
1825 Vcb
->Vpb
->Flags
|= VPB_LOCKED
;
1827 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_LOCKED
;
1828 Vcb
->VolumeLockFileObject
= IrpSp
->FileObject
;
1829 Vcb
->VolumeLockPID
= PID
;
1831 RC
= STATUS_SUCCESS
;
1835 RC
= STATUS_ACCESS_DENIED
;
1838 IoReleaseVpbSpinLock( SavedIrql
);
1840 if(!NT_SUCCESS(RC
)) {
1841 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_LOCK_FAILED
);
1844 // Complete the request if there haven't been any exceptions.
1845 Irp
->IoStatus
.Information
= 0;
1846 Irp
->IoStatus
.Status
= RC
;
1848 } // end UDFLockVolume()
1851 This routine performs the unlock volume operation. It is responsible for
1852 either completing of enqueuing the input Irp.
1854 Irp - Supplies the Irp to process
1856 NTSTATUS - The return status for the operation
1860 IN PtrUDFIrpContext IrpContext
,
1865 NTSTATUS RC
= STATUS_INVALID_PARAMETER
;
1868 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1874 UDFPrint(("UDFUnlockVolume: PID %x\n", PID
));
1876 // Decode the file object, the only type of opens we accept are
1877 // user volume opens.
1878 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
1880 UDFPrintErr((" !Ccb\n"));
1881 Irp
->IoStatus
.Information
= 0;
1882 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1883 return STATUS_INVALID_PARAMETER
;
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
;
1895 // Acquire exclusive access to the Vcb/Vpb.
1896 IoAcquireVpbSpinLock( &SavedIrql
);
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
;
1911 RC
= STATUS_NOT_LOCKED
;
1912 RC
= STATUS_SUCCESS
;
1913 RC
= STATUS_VOLUME_DISMOUNTED
;
1920 // Release all of our resources
1921 IoReleaseVpbSpinLock( SavedIrql
);
1923 // Complete the request if there haven't been any exceptions.
1924 Irp
->IoStatus
.Information
= 0;
1925 Irp
->IoStatus
.Status
= RC
;
1927 } // end UDFUnlockVolume()
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.
1937 Irp - Supplies the Irp to process
1939 NTSTATUS - The return status for the operation
1943 IN PtrUDFIrpContext IrpContext
,
1949 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1954 PPREVENT_MEDIA_REMOVAL_USER_IN Buf
= NULL
;
1955 BOOLEAN VcbAcquired
= FALSE
;
1957 UDFPrint(("\n ### UDFDismountVolume ###\n\n"));
1959 // Decode the file object, the only type of opens we accept are
1960 // user volume opens.
1961 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
1963 UDFPrintErr((" !Ccb\n"));
1964 Irp
->IoStatus
.Information
= 0;
1965 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1966 return STATUS_INVALID_PARAMETER
;
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
;
1978 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_DISMOUNT
);
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
1986 // Acquire exclusive access to the Vcb.
1987 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
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.
1995 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
)) {
1996 // disable Eject Request Waiter if any
1997 UDFReleaseResource( &(Vcb
->VCBResource
) );
1998 VcbAcquired
= FALSE
;
2000 UDFStopEjectWaiter(Vcb
);
2001 RC
= STATUS_SUCCESS
;
2003 if(/*!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) ||*/
2004 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_LOCKED
) ||
2005 (Vcb
->VCBOpenCount
> (UDF_RESIDUAL_REFERENCE
+1))) {
2007 RC
= STATUS_NOT_LOCKED
;
2009 if((Vcb
->VolumeLockFileObject
!= IrpSp
->FileObject
)) {
2011 RC
= STATUS_INVALID_PARAMETER
;
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
;
2025 UDFStopEjectWaiter(Vcb
);
2026 RC
= STATUS_SUCCESS
;
2031 if(Buf
) MyFreePool__(Buf
);
2032 // Release all of our resources
2034 UDFReleaseResource( &(Vcb
->VCBResource
) );
2037 if(!NT_SUCCESS(RC
)) {
2038 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_DISMOUNT_FAILED
);
2041 // Complete the request if there haven't been any exceptions.
2042 Irp
->IoStatus
.Information
= 0;
2043 Irp
->IoStatus
.Status
= RC
;
2045 } // end UDFDismountVolume()
2049 This routine returns the volume allocation bitmap.
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
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.
2061 Irp - Supplies the Irp being processed.
2065 NTSTATUS - The return status for the operation.
2070 IN PtrUDFIrpContext IrpContext
,
2076 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2077 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2083 UDFPrint(("UDFGetVolumeBitmap\n"));
2086 ULONG TotalClusters
;
2087 ULONG DesiredClusters
;
2088 ULONG StartingCluster
;
2089 ULONG InputBufferLength
;
2090 ULONG OutputBufferLength
;
2091 LARGE_INTEGER StartingLcn
;
2092 PVOLUME_BITMAP_BUFFER OutputBuffer
;
2098 // Decode the file object, the only type of opens we accept are
2099 // user volume opens.
2100 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
2102 UDFPrintErr((" !Ccb\n"));
2103 Irp
->IoStatus
.Information
= 0;
2104 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2105 return STATUS_INVALID_PARAMETER
;
2110 InputBufferLength
= IrpSp
->Parameters
.FileSystemControl
.InputBufferLength
;
2111 OutputBufferLength
= IrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
2113 OutputBuffer
= (PVOLUME_BITMAP_BUFFER
)UDFGetCallersBuffer(IrpContext
, Irp
);
2115 return STATUS_INVALID_USER_BUFFER
;
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
))) {
2121 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2122 Irp
->IoStatus
.Information
= 0;
2123 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
2124 return STATUS_BUFFER_TOO_SMALL
;
2127 // Check if a starting cluster was specified.
2128 TotalClusters
= Vcb
->FSBM_BitCount
;
2129 StartingLcn
= ((PSTARTING_LCN_INPUT_BUFFER
)IrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
)->StartingLcn
;
2131 if (StartingLcn
.HighPart
|| StartingLcn
.LowPart
>= TotalClusters
) {
2133 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2134 Irp
->IoStatus
.Information
= 0;
2135 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2136 return STATUS_INVALID_PARAMETER
;
2140 StartingCluster
= StartingLcn
.LowPart
& ~7;
2143 OutputBufferLength
-= FIELD_OFFSET(VOLUME_BITMAP_BUFFER
, Buffer
);
2144 DesiredClusters
= TotalClusters
- StartingCluster
;
2146 if (OutputBufferLength
< (DesiredClusters
+ 7) / 8) {
2148 BytesToCopy
= OutputBufferLength
;
2149 // RC = STATUS_BUFFER_OVERFLOW;
2153 BytesToCopy
= (DesiredClusters
+ 7) / 8;
2154 // RC = STATUS_SUCCESS;
2157 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
2161 // Fill in the fixed part of the output buffer
2162 OutputBuffer
->StartingLcn
.QuadPart
= StartingCluster
;
2163 OutputBuffer
->BitmapSize
.QuadPart
= DesiredClusters
;
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]);
2171 for(i
=StartingCluster
& ~7; i
<lim
; i
++) {
2172 if(UDFGetFreeBit(FSBM
, i
<<LSh
))
2173 UDFSetFreeBit(FSBM
, i
);
2176 } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext
, _SEH2_GetExceptionInformation())) {
2179 UDFPrintErr(("UDFGetVolumeBitmap: Exception\n"));
2180 // UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer);
2182 // RC = UDFExceptionHandler(IrpContext, Irp);
2183 UDFReleaseResource(&(Vcb
->VCBResource
));
2184 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2186 Irp
->IoStatus
.Information
= 0;
2187 Irp
->IoStatus
.Status
= STATUS_INVALID_USER_BUFFER
;
2188 return STATUS_INVALID_USER_BUFFER
;
2191 UDFReleaseResource(&(Vcb
->VCBResource
));
2193 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2194 Irp
->IoStatus
.Information
= FIELD_OFFSET(VOLUME_BITMAP_BUFFER
, Buffer
) +
2196 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2198 return STATUS_SUCCESS
;
2201 } // end UDFGetVolumeBitmap()
2205 UDFGetRetrievalPointers(
2206 IN PtrUDFIrpContext IrpContext
,
2213 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2214 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2219 PUDF_FILE_INFO FileInfo
;
2221 ULONG InputBufferLength
;
2222 ULONG OutputBufferLength
;
2224 PRETRIEVAL_POINTERS_BUFFER OutputBuffer
;
2225 PSTARTING_VCN_INPUT_BUFFER InputBuffer
;
2227 LARGE_INTEGER StartingVcn
;
2228 int64 AllocationSize
;
2230 PEXTENT_MAP SubMapping
= NULL
;
2237 UDFPrint(("UDFGetRetrievalPointers\n"));
2239 // Decode the file object, the only type of opens we accept are
2240 // user volume opens.
2241 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
2243 UDFPrintErr((" !Ccb\n"));
2244 Irp
->IoStatus
.Information
= 0;
2245 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2246 return STATUS_INVALID_PARAMETER
;
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
;
2256 //OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFGetCallersBuffer( IrpContext, Irp );
2258 OutputBuffer
= (PRETRIEVAL_POINTERS_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
2260 OutputBuffer
= (PRETRIEVAL_POINTERS_BUFFER
)Irp
->UserBuffer
;
2262 InputBuffer
= (PSTARTING_VCN_INPUT_BUFFER
)IrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
;
2264 InputBuffer
= (PSTARTING_VCN_INPUT_BUFFER
)OutputBuffer
;
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
))) {
2274 try_return( RC
= STATUS_BUFFER_TOO_SMALL
);
2279 if (Irp
->RequestorMode
!= KernelMode
) {
2280 ProbeForRead( IrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
,
2283 ProbeForWrite( OutputBuffer
, OutputBufferLength
, sizeof(UCHAR
) );
2285 StartingVcn
= InputBuffer
->StartingVcn
;
2287 } _SEH2_EXCEPT(Irp
->RequestorMode
!= KernelMode
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
) {
2289 RC
= _SEH2_GetExceptionCode();
2290 RC
= FsRtlIsNtstatusExpected(RC
) ?
2291 RC
: STATUS_INVALID_USER_BUFFER
;
2297 FileInfo
= Fcb
->FileInfo
;
2300 FileInfo
= Vcb
->NonAllocFileInfo
;
2303 try_return( RC
= STATUS_INVALID_PARAMETER
);
2307 try_return( RC
= STATUS_OBJECT_NAME_NOT_FOUND
);
2310 AllocationSize
= UDFGetFileAllocationSize(Vcb
, FileInfo
);
2312 LBS
= Vcb
->LBlockSize
;
2313 LBSh
= Vcb
->LBlockSizeBits
;
2314 L2BSh
= Vcb
->LB2B_Bits
;
2316 if (StartingVcn
.HighPart
||
2317 StartingVcn
.LowPart
>= (ULONG
)(AllocationSize
>> LBSh
)) {
2319 try_return( RC
= STATUS_END_OF_FILE
);
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
);
2329 OutputBuffer
->ExtentCount
= SubExtInfoSz
;
2330 OutputBuffer
->StartingVcn
= StartingVcn
;
2331 for(i
=0; i
<SubExtInfoSz
; i
++) {
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);
2339 if(SubMapping
[i
].extLocation
& 0x80000000) {
2340 OutputBuffer
->Extents
[i
].Lcn
.LowPart
= (SubMapping
[i
].extLocation
& 0x7fffffff) >> L2BSh
;
2341 OutputBuffer
->Extents
[i
].Lcn
.HighPart
= 0x80000000;
2343 OutputBuffer
->Extents
[i
].Lcn
.LowPart
= SubMapping
[i
].extLocation
>> L2BSh
;
2344 OutputBuffer
->Extents
[i
].Lcn
.HighPart
= 0;
2346 // alignment for last sector
2347 SubMapping
[i
].extLength
+= LBS
-1;
2348 StartingVcn
.QuadPart
+= SubMapping
[i
].extLength
>> LBSh
;
2349 OutputBuffer
->Extents
[i
].NextVcn
= StartingVcn
;
2352 Irp
->IoStatus
.Information
= FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER
, Extents
[0]) + i
* sizeof(LARGE_INTEGER
) * 2;
2358 MyFreePool__(SubMapping
);
2359 Irp
->IoStatus
.Status
= RC
;
2363 } // end UDFGetRetrievalPointers()
2368 IN PtrUDFIrpContext IrpContext
,
2373 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2374 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2380 UDFPrint(("UDFIsVolumeDirty\n"));
2382 Irp
->IoStatus
.Information
= 0;
2384 if (Irp
->AssociatedIrp
.SystemBuffer
!= NULL
) {
2385 VolumeState
= (PULONG
)(Irp
->AssociatedIrp
.SystemBuffer
);
2386 } else if (Irp
->MdlAddress
!= NULL
) {
2387 VolumeState
= (PULONG
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
2389 UDFPrintErr((" STATUS_INVALID_USER_BUFFER\n"));
2390 Irp
->IoStatus
.Status
= STATUS_INVALID_USER_BUFFER
;
2391 return STATUS_INVALID_USER_BUFFER
;
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
;
2402 // Decode the file object, the only type of opens we accept are
2403 // user volume opens.
2404 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
2406 UDFPrintErr((" !Ccb\n"));
2407 Irp
->IoStatus
.Information
= 0;
2408 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2409 return STATUS_INVALID_PARAMETER
;
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
;
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
;
2426 if(Vcb
->origIntegrityType
== INTEGRITY_TYPE_OPEN
) {
2427 UDFPrint((" Dirty\n"));
2428 (*VolumeState
) |= VOLUME_IS_DIRTY
;
2429 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2431 UDFPrint((" Clean\n"));
2433 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2435 return STATUS_SUCCESS
;
2437 } // end UDFIsVolumeDirty()
2441 UDFInvalidateVolumes(
2442 IN PtrUDFIrpContext IrpContext
,
2447 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2448 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2449 PPREVENT_MEDIA_REMOVAL_USER_IN Buf
= NULL
;
2451 UDFPrint(("UDFInvalidateVolumes\n"));
2455 LUID TcbPrivilege
= {SE_TCB_PRIVILEGE
, 0};
2464 PFILE_OBJECT FileToMarkBad
;
2465 PDEVICE_OBJECT DeviceToMarkBad
;
2467 Irp
->IoStatus
.Information
= 0;
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
;
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
;
2486 Handle
= *((PHANDLE
) Irp
->AssociatedIrp
.SystemBuffer
);
2488 RC
= ObReferenceObjectByHandle( Handle
,
2492 (PVOID
*)&FileToMarkBad
,
2495 if (!NT_SUCCESS(RC
)) {
2496 UDFPrintErr(("UDFInvalidateVolumes: can't get handle, RC=%x\n", RC
));
2497 Irp
->IoStatus
.Status
= RC
;
2501 // We only needed the pointer, not a reference.
2502 ObDereferenceObject( FileToMarkBad
);
2504 // Grab the DeviceObject from the FileObject.
2505 DeviceToMarkBad
= FileToMarkBad
->DeviceObject
;
2507 // Create a new Vpb for this device so that any new opens will mount
2509 NewVpb
= (PVPB
)DbgAllocatePoolWithTag( NonPagedPool
, sizeof( VPB
), 'bpvU' );
2511 UDFPrintErr(("UDFInvalidateVolumes: STATUS_INSUFFICIENT_RESOURCES\n"));
2512 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
2513 return STATUS_INSUFFICIENT_RESOURCES
;
2515 RtlZeroMemory( NewVpb
, sizeof( VPB
) );
2517 NewVpb
->Type
= IO_TYPE_VPB
;
2518 NewVpb
->Size
= sizeof( VPB
);
2519 NewVpb
->RealDevice
= DeviceToMarkBad
;
2520 NewVpb
->Flags
= DeviceToMarkBad
->Vpb
->Flags
& VPB_REMOVE_PENDING
;
2522 // Acquire GlobalDataResource
2523 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
2525 // Nothing can go wrong now.
2526 IoAcquireVpbSpinLock( &SavedIrql
);
2527 if (DeviceToMarkBad
->Vpb
->Flags
& VPB_MOUNTED
) {
2528 DeviceToMarkBad
->Vpb
= NewVpb
;
2531 ASSERT( DeviceToMarkBad
->Vpb
->DeviceObject
== NULL
);
2532 IoReleaseVpbSpinLock( SavedIrql
);
2535 DbgFreePool( NewVpb
);
2538 // Walk through all of the Vcb's attached to the global data.
2539 Link
= UDFGlobalData
.VCBQueue
.Flink
;
2543 while (Link
!= &(UDFGlobalData
.VCBQueue
)) {
2545 Vcb
= CONTAINING_RECORD( Link
, VCB
, NextVCB
);
2546 // Move to the next link now since the current Vcb may be deleted.
2549 // Acquire Vcb resource
2550 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
2552 if (Vcb
->Vpb
->RealDevice
== DeviceToMarkBad
) {
2555 Buf
= (PPREVENT_MEDIA_REMOVAL_USER_IN
)MyAllocatePool__(NonPagedPool
, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
)*2);
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
;
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
2571 if(Vcb
->RootDirFCB
&& Vcb
->RootDirFCB
->FileInfo
) {
2572 UDFPrint((" UDFInvalidateVolumes: UDFCloseAllSystemDelayedInDir\n"));
2573 RC
= UDFCloseAllSystemDelayedInDir(Vcb
, Vcb
->RootDirFCB
->FileInfo
);
2574 ASSERT(OS_SUCCESS(RC
));
2576 #ifdef UDF_DELAYED_CLOSE
2577 UDFPrint((" UDFInvalidateVolumes: UDFCloseAllDelayed\n"));
2578 UDFCloseAllDelayed(Vcb
);
2579 //ASSERT(OS_SUCCESS(RC));
2580 #endif //UDF_DELAYED_CLOSE
2582 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
2584 UDFDoDismountSequence(Vcb
, Buf
, FALSE
);
2585 UDFReleaseResource(&(Vcb
->VCBResource
));
2587 UDFStopEjectWaiter(Vcb
);
2588 UDFPrint(("UDFInvalidateVolumes: Vcb %x dismounted\n", Vcb
));
2591 UDFPrint(("UDFInvalidateVolumes: skip Vcb %x\n", Vcb
));
2592 UDFReleaseResource(&(Vcb
->VCBResource
));
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
) );
2600 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2603 UDFPrint(("UDFInvalidateVolumes: free buffer\n"));
2607 // drop volume completly
2608 UDFPrint(("UDFInvalidateVolumes: drop volume completly\n"));
2609 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
2610 UDFScanForDismountedVcb(IrpContext
);
2611 UDFReleaseResource( &(UDFGlobalData
.GlobalDataResource
) );
2613 UDFPrint(("UDFInvalidateVolumes: done\n"));
2614 return STATUS_SUCCESS
;
2616 } // end UDFInvalidateVolumes()