1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 ////////////////////////////////////////////////////////////////////
7 Module Name: FsCntrl.cpp
11 Contains code to handle the "File System IOCTL" dispatch entry point.
21 // define the file specific bug-check id
22 #define UDF_BUG_CHECK_ID UDF_FILE_FS_CONTROL
24 NTSTATUS
UDFBlankMount(IN PVCB Vcb
);
26 PDIR_INDEX_HDR
UDFDirIndexAlloc(IN uint_di i
);
29 Function: UDFFSControl()
32 The I/O Manager will invoke this routine to handle a File System
33 Control request (this is IRP_MJ_FILE_SYSTEM_CONTROL dispatch point)
39 PDEVICE_OBJECT DeviceObject
, // the logical volume device object
40 PIRP Irp
// I/O Request Packet
43 NTSTATUS RC
= STATUS_SUCCESS
;
44 PtrUDFIrpContext PtrIrpContext
;
45 BOOLEAN AreWeTopLevel
= FALSE
;
47 KdPrint(("\nUDFFSControl: \n\n"));
49 FsRtlEnterFileSystem();
53 // set the top level context
54 AreWeTopLevel
= UDFIsIrpTopLevel(Irp
);
58 // get an IRP context structure and issue the request
59 PtrIrpContext
= UDFAllocateIrpContext(Irp
, DeviceObject
);
61 RC
= UDFCommonFSControl(PtrIrpContext
, Irp
);
63 RC
= STATUS_INSUFFICIENT_RESOURCES
;
64 Irp
->IoStatus
.Status
= RC
;
65 Irp
->IoStatus
.Information
= 0;
67 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
70 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext
, _SEH2_GetExceptionInformation())) {
72 KdPrint(("UDFFSControl: exception ***"));
73 RC
= UDFExceptionHandler(PtrIrpContext
, Irp
);
75 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR
, RC
);
79 IoSetTopLevelIrp(NULL
);
82 FsRtlExitFileSystem();
85 } // end UDFFSControl()
88 Function: UDFCommonFSControl()
91 The actual work is performed here.
93 Expected Interrupt Level (for execution) :
94 IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
95 to be deferred to a worker thread context)
97 Return Value: STATUS_SUCCESS/Error
103 PtrUDFIrpContext PtrIrpContext
,
104 PIRP Irp
// I/O Request Packet
107 NTSTATUS RC
= STATUS_UNRECOGNIZED_VOLUME
;
108 PIO_STACK_LOCATION IrpSp
= NULL
;
109 // PDEVICE_OBJECT PtrTargetDeviceObject = NULL;
111 KdPrint(("\nUDFCommonFSControl\n\n"));
116 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
119 switch ((IrpSp
)->MinorFunction
)
121 case IRP_MN_USER_FS_REQUEST
:
122 KdPrint((" UDFFSControl: UserFsReq request ....\n"));
124 RC
= UDFUserFsCtrlRequest(PtrIrpContext
,Irp
);
126 case IRP_MN_MOUNT_VOLUME
:
128 KdPrint((" UDFFSControl: MOUNT_VOLUME request ....\n"));
130 RC
= UDFMountVolume(PtrIrpContext
,Irp
);
132 case IRP_MN_VERIFY_VOLUME
:
134 KdPrint((" UDFFSControl: VERIFY_VOLUME request ....\n"));
136 RC
= UDFVerifyVolume(Irp
);
139 KdPrint((" UDFFSControl: STATUS_INVALID_DEVICE_REQUEST MinorFunction %x\n", (IrpSp
)->MinorFunction
));
140 RC
= STATUS_INVALID_DEVICE_REQUEST
;
142 Irp
->IoStatus
.Status
= RC
;
143 Irp
->IoStatus
.Information
= 0;
145 IoCompleteRequest(Irp
, IO_DISK_INCREMENT
);
151 if (!_SEH2_AbnormalTermination()) {
152 // Free up the Irp Context
153 KdPrint((" UDFCommonFSControl: finally\n"));
154 UDFReleaseIrpContext(PtrIrpContext
);
156 KdPrint((" UDFCommonFSControl: finally after exception ***\n"));
161 } // end UDFCommonFSControl()
165 This is the common routine for implementing the user's requests made
166 through NtFsControlFile.
169 Irp - Supplies the Irp being processed
172 NTSTATUS - The return status for the operation
177 UDFUserFsCtrlRequest(
178 PtrUDFIrpContext IrpContext
,
183 PEXTENDED_IO_STACK_LOCATION IrpSp
= (PEXTENDED_IO_STACK_LOCATION
) IoGetCurrentIrpStackLocation( Irp
);
185 // Case on the control code.
186 switch ( IrpSp
->Parameters
.FileSystemControl
.FsControlCode
) {
188 case FSCTL_REQUEST_OPLOCK_LEVEL_1
:
189 case FSCTL_REQUEST_OPLOCK_LEVEL_2
:
190 case FSCTL_REQUEST_BATCH_OPLOCK
:
191 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
:
192 case FSCTL_OPBATCH_ACK_CLOSE_PENDING
:
193 case FSCTL_OPLOCK_BREAK_NOTIFY
:
194 case FSCTL_OPLOCK_BREAK_ACK_NO_2
:
195 case FSCTL_REQUEST_FILTER_OPLOCK
:
197 KdPrint(("UDFUserFsCtrlRequest: OPLOCKS\n"));
198 RC
= STATUS_INVALID_DEVICE_REQUEST
;
200 Irp
->IoStatus
.Information
= 0;
201 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
204 RC = UDFOplockRequest( IrpContext, Irp );
207 case FSCTL_INVALIDATE_VOLUMES
:
209 RC
= UDFInvalidateVolumes( IrpContext
, Irp
);
212 case FSCTL_MOVE_FILE:
214 case FSCTL_QUERY_ALLOCATED_RANGES:
215 case FSCTL_SET_ZERO_DATA:
216 case FSCTL_SET_SPARSE:
218 case FSCTL_MARK_VOLUME_DIRTY:
220 RC = UDFDirtyVolume( IrpContext, Irp );
224 case FSCTL_IS_VOLUME_DIRTY
:
226 RC
= UDFIsVolumeDirty(IrpContext
, Irp
);
229 case FSCTL_ALLOW_EXTENDED_DASD_IO
:
231 KdPrint(("UDFUserFsCtrlRequest: FSCTL_ALLOW_EXTENDED_DASD_IO\n"));
232 // DASD i/o is always permitted
233 // So, no-op this call
236 Irp
->IoStatus
.Information
= 0;
237 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
240 case FSCTL_DISMOUNT_VOLUME
:
242 RC
= UDFDismountVolume( IrpContext
, Irp
);
245 case FSCTL_IS_VOLUME_MOUNTED
:
247 RC
= UDFIsVolumeMounted( IrpContext
, Irp
);
250 case FSCTL_FILESYSTEM_GET_STATISTICS
:
252 RC
= UDFGetStatistics( IrpContext
, Irp
);
255 case FSCTL_LOCK_VOLUME
:
257 RC
= UDFLockVolume( IrpContext
, Irp
);
260 case FSCTL_UNLOCK_VOLUME
:
262 RC
= UDFUnlockVolume( IrpContext
, Irp
);
265 case FSCTL_IS_PATHNAME_VALID
:
267 RC
= UDFIsPathnameValid( IrpContext
, Irp
);
270 case FSCTL_GET_VOLUME_BITMAP
:
272 KdPrint(("UDFUserFsCtrlRequest: FSCTL_GET_VOLUME_BITMAP\n"));
273 RC
= UDFGetVolumeBitmap( IrpContext
, Irp
);
276 case FSCTL_GET_RETRIEVAL_POINTERS
:
278 KdPrint(("UDFUserFsCtrlRequest: FSCTL_GET_RETRIEVAL_POINTERS\n"));
279 RC
= UDFGetRetrievalPointers( IrpContext
, Irp
, 0 );
283 // We don't support any of the known or unknown requests.
286 KdPrint(("UDFUserFsCtrlRequest: STATUS_INVALID_DEVICE_REQUEST for %x\n",
287 IrpSp
->Parameters
.FileSystemControl
.FsControlCode
));
288 RC
= STATUS_INVALID_DEVICE_REQUEST
;
290 Irp
->IoStatus
.Information
= 0;
291 Irp
->IoStatus
.Status
= STATUS_INVALID_DEVICE_REQUEST
;
295 IoCompleteRequest(Irp
,IO_DISK_INCREMENT
);
298 } // end UDFUserFsCtrlRequest()
303 This is the common routine for implementing the mount requests
306 Irp - Supplies the Irp being processed
309 NTSTATUS - The return status for the operation
315 IN PtrUDFIrpContext PtrIrpContext
,
320 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
321 PDEVICE_OBJECT TargetDeviceObject
= NULL
;
322 PFILTER_DEV_EXTENSION filterDevExt
;
323 PDEVICE_OBJECT fsDeviceObject
;
324 PVPB Vpb
= IrpSp
->Parameters
.MountVolume
.Vpb
;
326 // PVCB OldVcb = NULL;
327 PDEVICE_OBJECT VolDo
= NULL
;
328 IO_STATUS_BLOCK Iosb
;
329 ULONG MediaChangeCount
= 0;
330 ULONG Characteristics
;
331 DEVICE_TYPE FsDeviceType
;
332 BOOLEAN RestoreDoVerify
= FALSE
;
333 BOOLEAN WrongMedia
= FALSE
;
334 BOOLEAN RemovableMedia
= TRUE
;
335 BOOLEAN CompleteIrp
= FALSE
;
337 TEST_UNIT_READY_USER_OUT TestUnitReadyBuffer
;
340 BOOLEAN VcbAcquired
= FALSE
;
341 BOOLEAN DeviceNotTouched
= TRUE
;
342 BOOLEAN Locked
= FALSE
;
346 KdPrint(("\n !!! UDFMountVolume\n"));
347 // KdPrint(("Build " VER_STR_PRODUCT "\n\n"));
349 fsDeviceObject
= PtrIrpContext
->TargetDeviceObject
;
350 KdPrint(("Mount on device object %x\n"));
351 filterDevExt
= (PFILTER_DEV_EXTENSION
)fsDeviceObject
->DeviceExtension
;
352 if (filterDevExt
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_FILTER_DEVOBJ
&&
353 filterDevExt
->NodeIdentifier
.NodeSize
== sizeof(FILTER_DEV_EXTENSION
)) {
356 if (filterDevExt
->NodeIdentifier
.NodeType
== UDF_NODE_TYPE_UDFFS_DEVOBJ
&&
357 filterDevExt
->NodeIdentifier
.NodeSize
== sizeof(UDFFS_DEV_EXTENSION
)) {
360 KdPrint(("Invalid node type in FS or FILTER DeviceObject\n"));
363 // Get a pointer to the target physical/virtual device object.
364 TargetDeviceObject
= IrpSp
->Parameters
.MountVolume
.DeviceObject
;
366 if(((Characteristics
= TargetDeviceObject
->Characteristics
) & FILE_FLOPPY_DISKETTE
) ||
367 (UDFGlobalData
.UDFFlags
& UDF_DATA_FLAGS_BEING_UNLOADED
) ) {
370 RemovableMedia
= (Characteristics
& FILE_REMOVABLE_MEDIA
) ? TRUE
: FALSE
;
371 if(TargetDeviceObject
->DeviceType
!= FILE_DEVICE_CD_ROM
) {
372 if(UDFGetRegParameter(NULL
, REG_MOUNT_ON_CDONLY_NAME
, TRUE
)) {
376 if(TargetDeviceObject
->DeviceType
== FILE_DEVICE_CD_ROM
) {
377 FsDeviceType
= FILE_DEVICE_CD_ROM_FILE_SYSTEM
;
378 #ifdef UDF_HDD_SUPPORT
380 if (TargetDeviceObject
->DeviceType
== FILE_DEVICE_DISK
) {
382 if(!UDFGetRegParameter(NULL
, REG_MOUNT_ON_ZIP_NAME
, FALSE
)) {
386 if(!UDFGetRegParameter(NULL
, REG_MOUNT_ON_HDD_NAME
, FALSE
)) {
390 FsDeviceType
= FILE_DEVICE_DISK_FILE_SYSTEM
;
391 #endif //UDF_HDD_SUPPORT
397 // Acquire GlobalDataResource
398 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
402 UDFScanForDismountedVcb(PtrIrpContext
);
404 if(WrongMedia
) try_return(RC
= STATUS_UNRECOGNIZED_VOLUME
);
407 KdPrint(("UDFMountVolume: removable media\n"));
408 // just remember current MediaChangeCount
409 // or fail if No Media ....
411 // experimental CHECK_VERIFY, for fucking BENQ DVD_DD_1620
413 // Now we can get device state via GET_EVENT (if supported)
414 // or still one TEST_UNIT_READY command
415 RC
= UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY
,
418 &MediaChangeCount
,sizeof(ULONG
),
421 // Send TEST_UNIT_READY comment
422 // This can spin-up or wake-up the device
423 if(UDFGetRegParameter(NULL
, UDF_WAIT_CD_SPINUP
, TRUE
)) {
424 delay
.QuadPart
= -15000000LL; // 1.5 sec
425 for(i
=0; i
<UDF_READY_MAX_RETRY
; i
++) {
426 // Use device default ready timeout
428 RC
= UDFPhSendIOCTL( IOCTL_CDRW_TEST_UNIT_READY
,
431 &TestUnitReadyBuffer
,sizeof(TEST_UNIT_READY_USER_OUT
),
433 KdPrint(("UDFMountVolume: TEST_UNIT_READY %x\n", RC
));
436 if(TestUnitReadyBuffer
.SenseKey
== SCSI_SENSE_NOT_READY
&&
437 TestUnitReadyBuffer
.AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
&&
438 TestUnitReadyBuffer
.AdditionalSenseCodeQualifier
== SCSI_SENSEQ_BECOMING_READY
) {
439 KdPrint(("UDFMountVolume: retry\n"));
440 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
441 //delay.QuadPart -= 10000000LL; // 1.0 sec
447 KdPrint(("UDFMountVolume: additional delay 3 sec\n"));
448 delay
.QuadPart
= -30000000LL; // 3.0 sec
449 KeDelayExecutionThread(KernelMode
, FALSE
, &delay
);
453 // Now we can get device state via GET_EVENT (if supported)
454 // or still one TEST_UNIT_READY command
455 RC
= UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY
,
458 &MediaChangeCount
,sizeof(ULONG
),
461 if(RC
== STATUS_IO_DEVICE_ERROR
) {
462 KdPrint(("UDFMountVolume: retry check verify\n"));
463 RC
= UDFPhSendIOCTL( IOCTL_STORAGE_CHECK_VERIFY
,
466 &MediaChangeCount
,sizeof(ULONG
),
470 if(!NT_SUCCESS(RC
) && (RC
!= STATUS_VERIFY_REQUIRED
))
473 // Be safe about the count in case the driver didn't fill it in
474 if(Iosb
.Information
!= sizeof(ULONG
)) {
475 MediaChangeCount
= 0;
478 if(FsDeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
) {
479 // Check if device is busy before locking tray and performing
480 // further geomentry discovery. This is needed to avoid streaming
481 // loss during CD-R recording. Note, that some recording tools
482 // work with device via SPTI bypassing FS/Device driver layers.
484 ioBuf
= (int8
*)MyAllocatePool__(NonPagedPool
,4096);
486 try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
488 RC
= UDFPhSendIOCTL(IOCTL_CDROM_GET_DRIVE_GEOMETRY
,TargetDeviceObject
,
489 ioBuf
,sizeof(DISK_GEOMETRY
),
490 ioBuf
,sizeof(DISK_GEOMETRY
),
493 if(RC
== STATUS_DEVICE_NOT_READY
) {
494 // probably, the device is really busy, may be by CD/DVD recording
495 UserPrint((" busy (*)\n"));
500 // lock media for now
502 ((PPREVENT_MEDIA_REMOVAL_USER_IN
)(&MediaChangeCount
))->PreventMediaRemoval
= TRUE
;
503 RC
= UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL
,
505 &MediaChangeCount
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
512 // Now before we can initialize the Vcb we need to set up the
513 // Get our device object and alignment requirement.
514 // Device extension == VCB
515 KdPrint(("UDFMountVolume: create device\n"));
516 RC
= IoCreateDevice( UDFGlobalData
.DriverObject
,
524 if(!NT_SUCCESS(RC
)) try_return(RC
);
526 // Our alignment requirement is the larger of the processor alignment requirement
527 // already in the volume device object and that in the DeviceObjectWeTalkTo
528 if(TargetDeviceObject
->AlignmentRequirement
> VolDo
->AlignmentRequirement
) {
529 VolDo
->AlignmentRequirement
= TargetDeviceObject
->AlignmentRequirement
;
532 VolDo
->Flags
&= ~DO_DEVICE_INITIALIZING
;
534 // device object field in the VPB to point to our new volume device
536 Vpb
->DeviceObject
= (PDEVICE_OBJECT
) VolDo
;
538 // We must initialize the stack size in our device object before
539 // the following reads, because the I/O system has not done it yet.
540 ((PDEVICE_OBJECT
)VolDo
)->StackSize
= (CCHAR
) (TargetDeviceObject
->StackSize
+ 1);
542 Vcb
= (PVCB
)VolDo
->DeviceExtension
;
544 // Initialize the Vcb. This routine will raise on an allocation
546 RC
= UDFInitializeVCB(VolDo
,TargetDeviceObject
,Vpb
);
547 if(!NT_SUCCESS(RC
)) {
552 #ifdef EVALUATION_TIME_LIMIT
553 if(UDFGlobalData
.Saved_j
!= 4) {
554 UDFGlobalData
.UDFFlags
|= UDF_DATA_FLAGS_UNREGISTERED
;
556 #endif //EVALUATION_TIME_LIMIT
561 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
564 // Let's reference the Vpb to make sure we are the one to
565 // have the last dereference.
566 Vcb
->Vpb
->ReferenceCount
++;
568 Vcb
->MediaChangeCount
= MediaChangeCount
;
569 Vcb
->FsDeviceType
= FsDeviceType
;
571 // Clear the verify bit for the start of mount.
572 if(Vcb
->Vpb
->RealDevice
->Flags
& DO_VERIFY_VOLUME
) {
573 Vcb
->Vpb
->RealDevice
->Flags
&= ~DO_VERIFY_VOLUME
;
574 RestoreDoVerify
= TRUE
;
577 DeviceNotTouched
= FALSE
;
578 RC
= UDFGetDiskInfo(TargetDeviceObject
,Vcb
);
579 if(!NT_SUCCESS(RC
)) try_return(RC
);
581 // **** Read registry settings ****
582 UDFReadRegKeys(Vcb
, FALSE
, FALSE
);
584 Vcb
->MountPhErrorCount
= 0;
586 // Initialize internal cache
587 Mode
= WCACHE_MODE_ROM
;
588 RC
= WCacheInit__(&(Vcb
->FastCache
),
589 Vcb
->WCacheMaxFrames
,
590 Vcb
->WCacheMaxBlocks
,
592 5, Vcb
->BlockSizeBits
,
593 Vcb
->WCacheBlocksPerFrameSh
,
594 0/*Vcb->FirstLBA*/, Vcb
->LastPossibleLBA
, Mode
,
595 0/*WCACHE_CACHE_WHOLE_PACKET*/ |
596 (Vcb
->DoNotCompareBeforeWrite
? WCACHE_DO_NOT_COMPARE
: 0) |
597 (Vcb
->CacheChainedIo
? WCACHE_CHAINED_IO
: 0) |
598 WCACHE_MARK_BAD_BLOCKS
| WCACHE_RO_BAD_BLOCKS
, // this will be cleared after mount
599 Vcb
->WCacheFramesToKeepFree
,
600 // UDFTWrite, UDFTRead,
601 UDFTWriteVerify
, UDFTReadVerify
,
603 UDFTWriteAsync
, UDFTReadAsync
,
606 #endif //UDF_ASYNC_IO
609 UDFWCacheErrorHandler
);
610 if(!NT_SUCCESS(RC
)) try_return(RC
);
613 if(!NT_SUCCESS(RC
)) try_return(RC
);
615 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
616 RC
= UDFGetDiskInfoAndVerify(TargetDeviceObject
,Vcb
);
617 UDFReleaseResource(&(Vcb
->BitMapResource1
));
619 ASSERT(!Vcb
->Modified
);
620 WCacheChFlags__(&(Vcb
->FastCache
),
621 WCACHE_CACHE_WHOLE_PACKET
, // enable cache whole packet
622 WCACHE_MARK_BAD_BLOCKS
| WCACHE_RO_BAD_BLOCKS
); // let user retry request on Bad Blocks
624 #ifdef UDF_READ_ONLY_BUILD
625 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
626 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_MEDIA_READ_ONLY
;
627 #endif //UDF_READ_ONLY_BUILD
628 #ifdef EVALUATION_TIME_LIMIT
629 if(UDFGlobalData
.UDFFlags
& UDF_DATA_FLAGS_UNREGISTERED
) {
630 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
632 #endif //EVALUATION_TIME_LIMIT
634 if(!NT_SUCCESS(RC
)) {
635 KdPrint(("UDFMountVolume: try raw mount\n"));
636 if(Vcb
->NSRDesc
& VRS_ISO9660_FOUND
) {
637 KdPrint(("UDFMountVolume: block raw mount due to ISO9660 presence\n"));
638 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_RAW_DISK
;
642 KdPrint(("UDFMountVolume: try raw mount (2)\n"));
643 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) {
645 KdPrint(("UDFMountVolume: trying raw mount...\n"));
646 Vcb
->VolIdent
.Length
=
647 (Vcb
->VolIdent
.MaximumLength
= sizeof(UDF_BLANK_VOLUME_LABEL
)) - 2;
648 if(Vcb
->VolIdent
.Buffer
)
649 MyFreePool__(Vcb
->VolIdent
.Buffer
);
650 Vcb
->VolIdent
.Buffer
= (PWCHAR
)MyAllocatePool__(NonPagedPool
, sizeof(UDF_BLANK_VOLUME_LABEL
));
651 if(!Vcb
->VolIdent
.Buffer
)
652 try_return(STATUS_INSUFFICIENT_RESOURCES
);
653 RtlCopyMemory(Vcb
->VolIdent
.Buffer
, UDF_BLANK_VOLUME_LABEL
, sizeof(UDF_BLANK_VOLUME_LABEL
));
655 RC
= UDFBlankMount(Vcb
);
656 if(!NT_SUCCESS(RC
)) try_return(RC
);
659 // Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
663 Vcb
->MountPhErrorCount
= -1;
664 #ifndef UDF_READ_ONLY_BUILD
665 // set cache mode according to media type
666 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_READ_ONLY
)) {
667 KdPrint(("UDFMountVolume: writable volume\n"));
669 if((FsDeviceType
== FILE_DEVICE_DISK_FILE_SYSTEM
) ||
670 CdrwMediaClassEx_IsRAM(Vcb
->MediaClassEx
)) {
671 KdPrint(("UDFMountVolume: RAM mode\n"));
672 Mode
= WCACHE_MODE_RAM
;
674 KdPrint(("UDFMountVolume: RW mode\n"));
675 Mode
= WCACHE_MODE_RW
;
677 /* if(FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
679 Vcb->WriteSecurity = TRUE;
682 KdPrint(("UDFMountVolume: R mode\n"));
683 Mode
= WCACHE_MODE_R
;
685 // we can't record ACL on old format disks
686 if(!UDFNtAclSupported(Vcb
)) {
687 KdPrint(("UDFMountVolume: NO ACL and ExtFE support\n"));
688 Vcb
->WriteSecurity
= FALSE
;
689 Vcb
->UseExtendedFE
= FALSE
;
692 WCacheSetMode__(&(Vcb
->FastCache
), Mode
);
693 #endif //UDF_READ_ONLY_BUILD
694 // Complete mount operations: create root FCB
695 UDFAcquireResourceExclusive(&(Vcb
->BitMapResource1
),TRUE
);
696 RC
= UDFCompleteMount(Vcb
);
697 UDFReleaseResource(&(Vcb
->BitMapResource1
));
698 if(!NT_SUCCESS(RC
)) {
699 // We must have Vcb->VCBOpenCount = 1 for UDFBlankMount()
700 // Thus, we should not decrement it here
701 // Also, if we shall not perform BlankMount,
702 // but simply cleanup and return error, Vcb->VCBOpenCount
703 // will be decremented during cleanup. Thus anyway it must
704 // stay 1 unchanged here
705 //UDFInterlockedDecrement((PLONG)&(Vcb->VCBOpenCount));
706 UDFCloseResidual(Vcb
);
707 Vcb
->VCBOpenCount
= 1;
708 if(FsDeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
)
709 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_RAW_DISK
;
712 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_RAW_DISK
;
715 #ifndef UDF_READ_ONLY_BUILD
716 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_READ_ONLY
)) {
717 RC
= UDFStartEjectWaiter(Vcb
);
718 if(!NT_SUCCESS(RC
)) try_return(RC
);
720 KdPrint(("UDFMountVolume: RO mount\n"));
721 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
723 #endif //UDF_READ_ONLY_BUILD
725 Vcb
->Vpb
->SerialNumber
= Vcb
->PhSerialNumber
;
726 Vcb
->Vpb
->VolumeLabelLength
= Vcb
->VolIdent
.Length
;
727 RtlCopyMemory( Vcb
->Vpb
->VolumeLabel
,
728 Vcb
->VolIdent
.Buffer
,
729 Vcb
->VolIdent
.Length
);
731 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_MOUNTED
;
733 UDFInterlockedDecrement((PLONG
)&(Vcb
->VCBOpenCount
));
734 Vcb
->TotalAllocUnits
= UDFGetTotalSpace(Vcb
);
735 Vcb
->FreeAllocUnits
= UDFGetFreeSpace(Vcb
);
736 // Register shutdown routine
737 if(!Vcb
->ShutdownRegistered
) {
738 KdPrint(("UDFMountVolume: Register shutdown routine\n"));
739 IoRegisterShutdownNotification(Vcb
->VCBDeviceObject
);
740 Vcb
->ShutdownRegistered
= TRUE
;
745 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_READ_ONLY
) {
746 KdPrint(("UDFMountVolume: unlock media on RO volume\n"));
747 ((PPREVENT_MEDIA_REMOVAL_USER_IN
)(&MediaChangeCount
))->PreventMediaRemoval
= FALSE
;
748 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL
,
750 &MediaChangeCount
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
753 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
)
754 UDFResetDeviceDriver(Vcb
, Vcb
->TargetDeviceObject
, TRUE
);
758 if (UDFGlobalData
.MountEvent
)
760 Vcb
->IsVolumeJustMounted
= TRUE
;
761 KeSetEvent(UDFGlobalData
.MountEvent
, 0, FALSE
);
764 // The new mount is complete.
765 UDFReleaseResource( &(Vcb
->VCBResource
) );
774 KdPrint(("UDFMountVolume: RC = %x\n", RC
));
780 if(!NT_SUCCESS(RC
)) {
782 if(RemovableMedia
&& Locked
) {
783 KdPrint(("UDFMountVolume: unlock media\n"));
784 ((PPREVENT_MEDIA_REMOVAL_USER_IN
)(&MediaChangeCount
))->PreventMediaRemoval
= FALSE
;
785 UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL
,
787 &MediaChangeCount
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
791 /* if((RC != STATUS_DEVICE_NOT_READY) &&
792 (RC != STATUS_NO_MEDIA_IN_DEVICE) ) {*/
794 if(!DeviceNotTouched
&&
795 (!Vcb
|| (Vcb
&& (Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
)))) {
796 KdPrint(("UDFMountVolume: reset driver\n"));
797 UDFResetDeviceDriver(Vcb
, TargetDeviceObject
, TRUE
);
800 if(RC
== STATUS_CRC_ERROR
|| RC
== STATUS_FILE_CORRUPT_ERROR
) {
801 KdPrint(("UDFMountVolume: status -> STATUS_UNRECOGNIZED_VOLUME\n"));
802 RC
= STATUS_UNRECOGNIZED_VOLUME
;
805 // If we didn't complete the mount then cleanup any remaining structures.
807 Vpb
->DeviceObject
= NULL
;
811 // Restore the verify bit.
812 if(RestoreDoVerify
) {
813 Vcb
->Vpb
->RealDevice
->Flags
|= DO_VERIFY_VOLUME
;
815 // Make sure there is no Vcb since it could go away
816 if(Vcb
->VCBOpenCount
)
817 UDFInterlockedDecrement((PLONG
)&(Vcb
->VCBOpenCount
));
818 // This procedure will also delete the volume device object
819 if(UDFDismountVcb( Vcb
, VcbAcquired
)) {
820 UDFReleaseResource( &(Vcb
->VCBResource
) );
823 IoDeleteDevice( VolDo
);
826 // Release the global resource.
827 UDFReleaseResource( &(UDFGlobalData
.GlobalDataResource
) );
829 if (CompleteIrp
|| NT_SUCCESS(RC
)) {
830 if(!_SEH2_AbnormalTermination()) {
833 KdPrint(("UDFMountVolume: complete req RC %x\n", RC
));
834 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_MOUNT
);
836 Irp
->IoStatus
.Status
= RC
;
837 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
840 // Pass Irp to lower driver (CDFS)
842 // Get this driver out of the driver stack and get to the next driver as
843 // quickly as possible.
844 Irp
->CurrentLocation
++;
845 Irp
->Tail
.Overlay
.CurrentStackLocation
++;
847 // Now call the appropriate file system driver with the request.
848 return IoCallDriver( filterDevExt
->lowerFSDeviceObject
, Irp
);
854 KdPrint(("UDFMountVolume: final RC = %x\n", RC
));
857 } // end UDFMountVolume()
865 PREVENT_MEDIA_REMOVAL_USER_IN Buff
;
866 KdPrint(("UDFStartEjectWaiter:\n"));
868 #ifdef EVALUATION_TIME_LIMIT
869 if(UDFGlobalData
.Saved_j
!= 4) {
870 UDFGlobalData
.UDFFlags
|= UDF_DATA_FLAGS_UNREGISTERED
;
872 #endif //EVALUATION_TIME_LIMIT
874 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_READ_ONLY
) {
875 KdPrint((" UDF_VCB_FLAGS_MEDIA_READ_ONLY\n"));
877 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_LOCKED
) {
878 KdPrint((" UDF_VCB_FLAGS_MEDIA_LOCKED\n"));
880 KdPrint((" EjectWaiter=%x\n", Vcb
->EjectWaiter
));
881 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_MEDIA_READ_ONLY
) &&
882 /*!(Vcb->VCBFlags & UDF_VCB_FLAGS_MEDIA_LOCKED) &&*/
883 !(Vcb
->EjectWaiter
)) {
885 KdPrint(("UDFStartEjectWaiter: check driver\n"));
886 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
) &&
887 (Vcb
->FsDeviceType
== FILE_DEVICE_CD_ROM_FILE_SYSTEM
)) {
888 // we don't know how to write without our device driver
889 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
890 KdPrint((" not our driver, ignore\n"));
891 return STATUS_SUCCESS
;
893 KdPrint(("UDFStartEjectWaiter: check removable\n"));
894 if(Vcb
->VCBFlags
& UDF_VCB_FLAGS_REMOVABLE_MEDIA
) {
895 // prevent media removal
896 KdPrint(("UDFStartEjectWaiter: lock media\n"));
897 Buff
.PreventMediaRemoval
= TRUE
;
898 RC
= UDFTSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL
,
900 &Buff
,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
),
903 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_MEDIA_LOCKED
;
905 KdPrint(("UDFStartEjectWaiter: prepare to start\n"));
906 // initialize Eject Request waiter
907 Vcb
->EjectWaiter
= (PUDFEjectWaitContext
)MyAllocatePool__(NonPagedPool
, sizeof(UDFEjectWaitContext
));
908 if(!(Vcb
->EjectWaiter
)) return STATUS_INSUFFICIENT_RESOURCES
;
909 KeInitializeEvent(&(Vcb
->WaiterStopped
), NotificationEvent
, FALSE
);
910 Vcb
->EjectWaiter
->Vcb
= Vcb
;
911 Vcb
->EjectWaiter
->SoftEjectReq
= FALSE
;
912 KeInitializeEvent(&(Vcb
->EjectWaiter
->StopReq
), NotificationEvent
, FALSE
);
913 // Vcb->EjectWaiter->StopReq = FALSE;
914 Vcb
->EjectWaiter
->WaiterStopped
= &(Vcb
->WaiterStopped
);
915 // This can occure after unexpected media loss, when EjectRequestWaiter
916 // terminates automatically
917 ASSERT(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_STOP_WAITER_EVENT
));
918 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_STOP_WAITER_EVENT
;
919 ExInitializeWorkItem(&(Vcb
->EjectWaiter
->EjectReqWorkQueueItem
), (PWORKER_THREAD_ROUTINE
)UDFEjectReqWaiter
, Vcb
->EjectWaiter
);
920 KdPrint(("UDFStartEjectWaiter: create thread\n"));
921 ExQueueWorkItem(&(Vcb
->EjectWaiter
->EjectReqWorkQueueItem
), DelayedWorkQueue
);
923 #ifdef EVALUATION_TIME_LIMIT
924 if(UDFGlobalData
.UDFFlags
& UDF_DATA_FLAGS_UNREGISTERED
) {
925 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_READ_ONLY
;
927 #endif //EVALUATION_TIME_LIMIT
930 KdPrint((" ignore\n"));
932 return STATUS_SUCCESS
;
933 } // end UDFStartEjectWaiter()
940 NTSTATUS RC
;// = STATUS_SUCCESS;
941 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
942 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader
= NULL
;
943 UNICODE_STRING LocalPath
;
944 PtrUDFObjectName RootName
;
947 KdPrint(("UDFCompleteMount:\n"));
948 Vcb
->ZBuffer
= (PCHAR
)DbgAllocatePoolWithTag(NonPagedPool
, max(Vcb
->LBlockSize
, PAGE_SIZE
), 'zNWD');
949 if(!Vcb
->ZBuffer
) return STATUS_INSUFFICIENT_RESOURCES
;
950 RtlZeroMemory(Vcb
->ZBuffer
, Vcb
->LBlockSize
);
952 KdPrint(("UDFCompleteMount: alloc Root FCB\n"));
953 // Create the root index and reference it in the Vcb.
955 Vcb
->RootDirFCB
= UDFAllocateFCB();
956 if(!RootFcb
) return STATUS_INSUFFICIENT_RESOURCES
;
958 KdPrint(("UDFCompleteMount: alloc Root ObjName\n"));
959 // Allocate and set root FCB unique name
960 RootName
= UDFAllocateObjectName();
962 UDFCleanUpFCB(RootFcb
);
963 Vcb
->RootDirFCB
= NULL
;
964 return STATUS_INSUFFICIENT_RESOURCES
;
966 RC
= MyInitUnicodeString(&(RootName
->ObjectName
),UDF_ROOTDIR_NAME
);
970 RootFcb
->FileInfo
= (PUDF_FILE_INFO
)MyAllocatePool__(NonPagedPool
,sizeof(UDF_FILE_INFO
));
971 if(!RootFcb
->FileInfo
) {
972 RC
= STATUS_INSUFFICIENT_RESOURCES
;
974 MyFreePool__(RootName
->ObjectName
.Buffer
);
975 UDFReleaseObjectName(RootName
);
976 UDFCleanUpFCB(RootFcb
);
977 Vcb
->RootDirFCB
= NULL
;
980 KdPrint(("UDFCompleteMount: open Root Dir\n"));
981 // Open Root Directory
982 RC
= UDFOpenRootFile__( Vcb
, &(Vcb
->RootLbAddr
), RootFcb
->FileInfo
);
983 if(!NT_SUCCESS(RC
)) {
985 UDFCleanUpFile__(Vcb
, RootFcb
->FileInfo
);
986 MyFreePool__(RootFcb
->FileInfo
);
989 RootFcb
->FileInfo
->Fcb
= RootFcb
;
991 if(!(RootFcb
->NTRequiredFCB
= RootFcb
->FileInfo
->Dloc
->CommonFcb
)) {
992 KdPrint(("UDFCompleteMount: alloc Root ObjName (2)\n"));
993 if(!(RootFcb
->NTRequiredFCB
=
994 (PtrUDFNTRequiredFCB
)MyAllocatePool__(NonPagedPool
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
))) ) ) {
995 RC
= STATUS_INSUFFICIENT_RESOURCES
;
998 RtlZeroMemory(RootFcb
->NTRequiredFCB
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
)));
999 RootFcb
->FileInfo
->Dloc
->CommonFcb
= RootFcb
->NTRequiredFCB
;
1001 KdPrint(("UDFCompleteMount: init FCB\n"));
1002 RC
= UDFInitializeFCB(RootFcb
,Vcb
,RootName
,UDF_FCB_ROOT_DIRECTORY
| UDF_FCB_DIRECTORY
,NULL
);
1003 if(!NT_SUCCESS(RC
)) {
1004 // if we get here, no resources are inited
1005 RootFcb
->OpenHandleCount
=
1006 RootFcb
->ReferenceCount
=
1007 RootFcb
->NTRequiredFCB
->CommonRefCount
= 0;
1009 UDFCleanUpFile__(Vcb
, RootFcb
->FileInfo
);
1010 MyFreePool__(RootFcb
->FileInfo
);
1011 MyFreePool__(RootFcb
->NTRequiredFCB
);
1012 UDFCleanUpFCB(RootFcb
);
1013 Vcb
->RootDirFCB
= NULL
;
1017 // this is a part of UDF_RESIDUAL_REFERENCE
1018 UDFInterlockedIncrement((PLONG
)&(Vcb
->VCBOpenCount
));
1019 RootFcb
->OpenHandleCount
=
1020 RootFcb
->ReferenceCount
=
1021 RootFcb
->NTRequiredFCB
->CommonRefCount
= 1;
1023 UDFGetFileXTime(RootFcb
->FileInfo
,
1024 &(RootFcb
->NTRequiredFCB
->CreationTime
.QuadPart
),
1025 &(RootFcb
->NTRequiredFCB
->LastAccessTime
.QuadPart
),
1026 &(RootFcb
->NTRequiredFCB
->ChangeTime
.QuadPart
),
1027 &(RootFcb
->NTRequiredFCB
->LastWriteTime
.QuadPart
) );
1029 if(Vcb
->SysStreamLbAddr
.logicalBlockNum
) {
1030 Vcb
->SysSDirFileInfo
= (PUDF_FILE_INFO
)MyAllocatePool__(NonPagedPool
,sizeof(UDF_FILE_INFO
));
1031 if(!Vcb
->SysSDirFileInfo
) {
1032 RC
= STATUS_INSUFFICIENT_RESOURCES
;
1035 // Open System SDir Directory
1036 RC
= UDFOpenRootFile__( Vcb
, &(Vcb
->SysStreamLbAddr
), Vcb
->SysSDirFileInfo
);
1037 if(!NT_SUCCESS(RC
)) {
1038 UDFCleanUpFile__(Vcb
, Vcb
->SysSDirFileInfo
);
1039 MyFreePool__(Vcb
->SysSDirFileInfo
);
1040 Vcb
->SysSDirFileInfo
= NULL
;
1043 Vcb
->SysSDirFileInfo
->Dloc
->DataLoc
.Flags
|= EXTENT_FLAG_VERIFY
;
1047 // Open Unallocatable space stream
1048 // Generally, it should be placed in SystemStreamDirectory, but some
1049 // stupid apps think that RootDirectory is much better place.... :((
1050 RC
= MyInitUnicodeString(&LocalPath
, UDF_FN_NON_ALLOCATABLE
);
1051 if(NT_SUCCESS(RC
)) {
1052 RC
= UDFOpenFile__(Vcb
, FALSE
, TRUE
, &LocalPath
, RootFcb
->FileInfo
, &(Vcb
->NonAllocFileInfo
), NULL
);
1053 MyFreePool__(LocalPath
.Buffer
);
1055 if(!NT_SUCCESS(RC
) && (RC
!= STATUS_OBJECT_NAME_NOT_FOUND
)) {
1058 UDFCleanUpFile__(Vcb
, Vcb
->NonAllocFileInfo
);
1059 Vcb
->NonAllocFileInfo
= NULL
;
1060 // this was a part of UDF_RESIDUAL_REFERENCE
1061 UDFInterlockedDecrement((PLONG
)&(Vcb
->VCBOpenCount
));
1064 // UDFCloseResidual() will clean up everything
1069 /* process Non-allocatable */
1070 if(NT_SUCCESS(RC
)) {
1071 UDFMarkSpaceAsXXX(Vcb
, Vcb
->NonAllocFileInfo
->Dloc
, Vcb
->NonAllocFileInfo
->Dloc
->DataLoc
.Mapping
, AS_USED
); // used
1072 UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb
->NonAllocFileInfo
), Vcb
->NonAllocFileInfo
->Index
)->FI_Flags
|= UDF_FI_FLAG_FI_INTERNAL
;
1074 /* try to read Non-allocatable from alternate locations */
1075 RC
= MyInitUnicodeString(&LocalPath
, UDF_FN_NON_ALLOCATABLE_2
);
1076 if(!NT_SUCCESS(RC
)) {
1079 RC
= UDFOpenFile__(Vcb
, FALSE
, TRUE
, &LocalPath
, RootFcb
->FileInfo
, &(Vcb
->NonAllocFileInfo
), NULL
);
1080 MyFreePool__(LocalPath
.Buffer
);
1081 if(!NT_SUCCESS(RC
) && (RC
!= STATUS_OBJECT_NAME_NOT_FOUND
)) {
1084 if(NT_SUCCESS(RC
)) {
1085 UDFMarkSpaceAsXXX(Vcb
, Vcb
->NonAllocFileInfo
->Dloc
, Vcb
->NonAllocFileInfo
->Dloc
->DataLoc
.Mapping
, AS_USED
); // used
1086 UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb
->NonAllocFileInfo
), Vcb
->NonAllocFileInfo
->Index
)->FI_Flags
|= UDF_FI_FLAG_FI_INTERNAL
;
1088 if(Vcb
->SysSDirFileInfo
) {
1089 RC
= MyInitUnicodeString(&LocalPath
, UDF_SN_NON_ALLOCATABLE
);
1090 if(!NT_SUCCESS(RC
)) {
1093 RC
= UDFOpenFile__(Vcb
, FALSE
, TRUE
, &LocalPath
, Vcb
->SysSDirFileInfo
, &(Vcb
->NonAllocFileInfo
), NULL
);
1094 MyFreePool__(LocalPath
.Buffer
);
1095 if(!NT_SUCCESS(RC
) && (RC
!= STATUS_OBJECT_NAME_NOT_FOUND
)) {
1098 if(NT_SUCCESS(RC
)) {
1099 UDFMarkSpaceAsXXX(Vcb
, Vcb
->NonAllocFileInfo
->Dloc
, Vcb
->NonAllocFileInfo
->Dloc
->DataLoc
.Mapping
, AS_USED
); // used
1100 // UDFDirIndex(UDFGetDirIndexByFileInfo(Vcb->NonAllocFileInfo), Vcb->NonAllocFileInfo->Index)->FI_Flags |= UDF_FI_FLAG_FI_INTERNAL;
1102 RC
= STATUS_SUCCESS
;
1105 RC
= STATUS_SUCCESS
;
1109 /* Read SN UID mapping */
1110 if(Vcb
->SysSDirFileInfo
) {
1111 RC
= MyInitUnicodeString(&LocalPath
, UDF_SN_UID_MAPPING
);
1114 RC
= UDFOpenFile__(Vcb
, FALSE
, TRUE
, &LocalPath
, Vcb
->SysSDirFileInfo
, &(Vcb
->UniqueIDMapFileInfo
), NULL
);
1115 MyFreePool__(LocalPath
.Buffer
);
1116 if(!NT_SUCCESS(RC
) && (RC
!= STATUS_OBJECT_NAME_NOT_FOUND
)) {
1118 // UDFCloseFile__(Vcb, Vcb->NonAllocFileInfo);
1119 // UDFCleanUpFile__(Vcb, Vcb->NonAllocFileInfo);
1120 // if(Vcb->NonAllocFileInfo)
1121 // MyFreePool__(Vcb->NonAllocFileInfo);
1122 // Vcb->NonAllocFileInfo = NULL;
1125 Vcb
->UniqueIDMapFileInfo
->Dloc
->DataLoc
.Flags
|= EXTENT_FLAG_VERIFY
;
1127 RC
= STATUS_SUCCESS
;
1130 #define DWN_MAX_CFG_FILE_SIZE 0x10000
1132 /* Read DWN config file from disk with disk-specific options */
1133 RC
= MyInitUnicodeString(&LocalPath
, UDF_CONFIG_STREAM_NAME_W
);
1134 if(NT_SUCCESS(RC
)) {
1138 PUDF_FILE_INFO CfgFileInfo
= NULL
;
1140 RC
= UDFOpenFile__(Vcb
, FALSE
, TRUE
, &LocalPath
, RootFcb
->FileInfo
, &CfgFileInfo
, NULL
);
1141 if(OS_SUCCESS(RC
)) {
1143 len
= (ULONG
)UDFGetFileSize(CfgFileInfo
);
1144 if(len
&& len
< DWN_MAX_CFG_FILE_SIZE
) {
1145 buff
= (int8
*)MyAllocatePool__(NonPagedPool
, len
);
1147 RC
= UDFReadFile__(Vcb
, CfgFileInfo
, 0, len
, FALSE
, buff
, &len
);
1148 if(OS_SUCCESS(RC
)) {
1150 Vcb
->Cfg
= (PUCHAR
)buff
;
1151 Vcb
->CfgLength
= len
;
1152 UDFReadRegKeys(Vcb
, TRUE
/*update*/, TRUE
/*cfg*/);
1155 Vcb
->CfgVersion
= 0;
1161 UDFCloseFile__(Vcb
, CfgFileInfo
);
1164 UDFCleanUpFile__(Vcb
, CfgFileInfo
);
1166 MyFreePool__(LocalPath
.Buffer
);
1168 RC
= STATUS_SUCCESS
;
1170 // clear Modified flags. It was not real modify, just
1171 // bitmap construction
1172 Vcb
->BitmapModified
= FALSE
;
1173 //Vcb->Modified = FALSE;
1174 UDFPreClrModified(Vcb
);
1175 UDFClrModified(Vcb
);
1176 // this is a part of UDF_RESIDUAL_REFERENCE
1177 UDFInterlockedIncrement((PLONG
)&(Vcb
->VCBOpenCount
));
1179 NtReqFcb
= RootFcb
->NTRequiredFCB
;
1181 // Start initializing the fields contained in the CommonFCBHeader.
1182 PtrCommonFCBHeader
= &(NtReqFcb
->CommonFCBHeader
);
1184 // DisAllow fast-IO for now.
1185 // PtrCommonFCBHeader->IsFastIoPossible = FastIoIsNotPossible;
1186 PtrCommonFCBHeader
->IsFastIoPossible
= FastIoIsPossible
;
1188 // Initialize the MainResource and PagingIoResource pointers in
1189 // the CommonFCBHeader structure to point to the ERESOURCE structures we
1190 // have allocated and already initialized above.
1191 // PtrCommonFCBHeader->Resource = &(NtReqFcb->MainResource);
1192 // PtrCommonFCBHeader->PagingIoResource = &(NtReqFcb->PagingIoResource);
1194 // Initialize the file size values here.
1195 PtrCommonFCBHeader
->AllocationSize
.QuadPart
= 0;
1196 PtrCommonFCBHeader
->FileSize
.QuadPart
= 0;
1198 // The following will disable ValidDataLength support.
1199 // PtrCommonFCBHeader->ValidDataLength.QuadPart = 0x7FFFFFFFFFFFFFFFI64;
1200 PtrCommonFCBHeader
->ValidDataLength
.QuadPart
= 0;
1204 UDFAssignAcl(Vcb
, NULL
, RootFcb
, NtReqFcb
);
1206 Vcb->CDBurnerVolumeValid = true;
1209 Vcb->CDBurnerVolume.Length = 256;
1210 Vcb->CDBurnerVolume.MaximumLength = 256;
1211 Vcb->CDBurnerVolume.Buffer = (PWCHAR)ExAllocatePool(NonPagedPool, 256);
1212 RC = RegTGetStringValue(NULL, REG_CD_BURNER_KEY_NAME, REG_CD_BURNER_VOLUME_NAME, Vcb->CDBurnerVolume.Buffer,
1214 Vcb->CDBurnerVolume.Length = (USHORT)(wcslen(Vcb->CDBurnerVolume.Buffer)*sizeof(WCHAR));
1216 if(RC != STATUS_OBJECT_NAME_NOT_FOUND && !NT_SUCCESS(RC) )
1219 if (NT_SUCCESS(RC)) {
1220 RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
1221 REG_CD_BURNER_KEY_NAME, REG_CD_BURNER_VOLUME_NAME,
1222 REG_SZ,L"",sizeof(L"")+1);
1225 Vcb->CDBurnerVolumeValid = false;
1226 RC = STATUS_SUCCESS;
1229 ASSERT(!Vcb
->Modified
);
1232 } // end UDFCompleteMount()
1239 NTSTATUS RC
;// = STATUS_SUCCESS;
1240 PtrUDFNTRequiredFCB NtReqFcb
= NULL
;
1241 PFSRTL_COMMON_FCB_HEADER PtrCommonFCBHeader
= NULL
;
1242 PtrUDFObjectName RootName
;
1244 PDIR_INDEX_HDR hDirNdx
;
1245 PDIR_INDEX_ITEM DirNdx
;
1247 // Create the root index and reference it in the Vcb.
1249 Vcb
->RootDirFCB
= UDFAllocateFCB();
1250 if(!RootFcb
) return STATUS_INSUFFICIENT_RESOURCES
;
1251 RtlZeroMemory(RootFcb
,sizeof(UDFFCB
));
1253 // Allocate and set root FCB unique name
1254 RootName
= UDFAllocateObjectName();
1257 UDFCleanUpFCB(RootFcb
);
1258 Vcb
->RootDirFCB
= NULL
;
1259 return STATUS_INSUFFICIENT_RESOURCES
;
1261 RC
= MyInitUnicodeString(&(RootName
->ObjectName
),UDF_ROOTDIR_NAME
);
1265 RootFcb
->NodeIdentifier
.NodeType
= UDF_NODE_TYPE_FCB
;
1266 RootFcb
->NodeIdentifier
.NodeSize
= sizeof(UDFFCB
);
1268 RootFcb
->FileInfo
= (PUDF_FILE_INFO
)MyAllocatePool__(NonPagedPool
,sizeof(UDF_FILE_INFO
));
1269 if(!RootFcb
->FileInfo
) {
1270 MyFreePool__(RootName
->ObjectName
.Buffer
);
1271 RC
= STATUS_INSUFFICIENT_RESOURCES
;
1273 UDFReleaseObjectName(RootName
);
1274 UDFCleanUpFCB(RootFcb
);
1275 Vcb
->RootDirFCB
= NULL
;
1278 RtlZeroMemory(RootFcb
->FileInfo
, sizeof(UDF_FILE_INFO
));
1279 if(!OS_SUCCESS(RC
= UDFStoreDloc(Vcb
, RootFcb
->FileInfo
, 1))) {
1280 MyFreePool__(RootFcb
->FileInfo
);
1281 RootFcb
->FileInfo
= NULL
;
1282 MyFreePool__(RootName
->ObjectName
.Buffer
);
1285 RootFcb
->FileInfo
->NextLinkedFile
=
1286 RootFcb
->FileInfo
->PrevLinkedFile
= RootFcb
->FileInfo
;
1288 hDirNdx
= UDFDirIndexAlloc(2);
1289 DirNdx
= UDFDirIndex(hDirNdx
,0);
1290 DirNdx
->FileCharacteristics
= FILE_DIRECTORY
;
1291 DirNdx
->FI_Flags
= UDF_FI_FLAG_SYS_ATTR
;
1292 DirNdx
->SysAttr
= FILE_ATTRIBUTE_READONLY
;
1293 DirNdx
->FName
.Buffer
= L
".";
1294 DirNdx
->FName
.Length
=
1295 (DirNdx
->FName
.MaximumLength
= sizeof(L
".")) - sizeof(WCHAR
);
1296 DirNdx
->FileInfo
= RootFcb
->FileInfo
;
1297 DirNdx
->FI_Flags
|= UDFBuildHashEntry(Vcb
, &(DirNdx
->FName
), &(DirNdx
->hashes
), HASH_ALL
| HASH_KEEP_NAME
);
1299 DirNdx
= UDFDirIndex(hDirNdx
,1);
1300 DirNdx
->FI_Flags
= UDF_FI_FLAG_SYS_ATTR
;
1301 if(Vcb
->ShowBlankCd
== 2) {
1302 DirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_INTERNAL
;
1304 DirNdx
->SysAttr
= FILE_ATTRIBUTE_READONLY
;
1305 DirNdx
->FName
.Buffer
= L
"Blank.CD";
1306 DirNdx
->FName
.Length
=
1307 (DirNdx
->FName
.MaximumLength
= sizeof(L
"Blank.CD")) - sizeof(WCHAR
);
1308 DirNdx
->FI_Flags
|= UDFBuildHashEntry(Vcb
, &(DirNdx
->FName
), &(DirNdx
->hashes
), HASH_ALL
);
1310 RootFcb
->FileInfo
->Dloc
->DirIndex
= hDirNdx
;
1311 RootFcb
->FileInfo
->Fcb
= RootFcb
;
1313 if(!(RootFcb
->NTRequiredFCB
= RootFcb
->FileInfo
->Dloc
->CommonFcb
)) {
1314 if(!(RootFcb
->NTRequiredFCB
=
1315 (PtrUDFNTRequiredFCB
)MyAllocatePool__(NonPagedPool
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
))) ) ) {
1316 MyFreePool__(RootName
->ObjectName
.Buffer
);
1317 UDFReleaseObjectName(RootName
);
1318 UDFCleanUpFCB(RootFcb
);
1319 Vcb
->RootDirFCB
= NULL
;
1320 return STATUS_INSUFFICIENT_RESOURCES
;
1322 RtlZeroMemory(RootFcb
->NTRequiredFCB
, UDFQuadAlign(sizeof(UDFNTRequiredFCB
)));
1323 RootFcb
->FileInfo
->Dloc
->CommonFcb
= RootFcb
->NTRequiredFCB
;
1325 RC
= UDFInitializeFCB(RootFcb
,Vcb
,RootName
,UDF_FCB_ROOT_DIRECTORY
| UDF_FCB_DIRECTORY
,NULL
);
1326 if(!NT_SUCCESS(RC
)) {
1327 // if we get here, no resources are inited
1328 RootFcb
->OpenHandleCount
=
1329 RootFcb
->ReferenceCount
=
1330 RootFcb
->NTRequiredFCB
->CommonRefCount
= 0;
1332 UDFCleanUpFile__(Vcb
, RootFcb
->FileInfo
);
1333 MyFreePool__(RootFcb
->FileInfo
);
1334 MyFreePool__(RootFcb
->NTRequiredFCB
);
1335 UDFCleanUpFCB(RootFcb
);
1336 Vcb
->RootDirFCB
= NULL
;
1340 // this is a part of UDF_RESIDUAL_REFERENCE
1341 UDFInterlockedIncrement((PLONG
)&(Vcb
->VCBOpenCount
));
1342 RootFcb
->OpenHandleCount
=
1343 RootFcb
->ReferenceCount
=
1344 RootFcb
->NTRequiredFCB
->CommonRefCount
=
1345 RootFcb
->FileInfo
->RefCount
=
1346 RootFcb
->FileInfo
->Dloc
->LinkRefCount
= 1;
1348 // this is a part of UDF_RESIDUAL_REFERENCE
1349 UDFInterlockedIncrement((PLONG
)&(Vcb
->VCBOpenCount
));
1351 NtReqFcb
= RootFcb
->NTRequiredFCB
;
1353 // Start initializing the fields contained in the CommonFCBHeader.
1354 PtrCommonFCBHeader
= &(NtReqFcb
->CommonFCBHeader
);
1356 // DisAllow fast-IO for now.
1357 PtrCommonFCBHeader
->IsFastIoPossible
= FastIoIsNotPossible
;
1359 // Initialize the MainResource and PagingIoResource pointers in
1360 // the CommonFCBHeader structure to point to the ERESOURCE structures we
1361 // have allocated and already initialized above.
1362 PtrCommonFCBHeader
->Resource
= &(NtReqFcb
->MainResource
);
1363 PtrCommonFCBHeader
->PagingIoResource
= &(NtReqFcb
->PagingIoResource
);
1365 // Initialize the file size values here.
1366 PtrCommonFCBHeader
->AllocationSize
.QuadPart
= 0;
1367 PtrCommonFCBHeader
->FileSize
.QuadPart
= 0;
1369 // The following will disable ValidDataLength support.
1370 PtrCommonFCBHeader
->ValidDataLength
.QuadPart
= 0x7FFFFFFFFFFFFFFFLL
;
1373 } // end UDFBlankMount()
1380 // Deinitialize Non-alloc file
1381 if(Vcb
->VCBOpenCount
)
1382 UDFInterlockedDecrement((PLONG
)&(Vcb
->VCBOpenCount
));
1383 KdPrint(("UDFCloseResidual: NonAllocFileInfo %x\n", Vcb
->NonAllocFileInfo
));
1384 if(Vcb
->NonAllocFileInfo
) {
1385 UDFCloseFile__(Vcb
,Vcb
->NonAllocFileInfo
);
1386 UDFCleanUpFile__(Vcb
, Vcb
->NonAllocFileInfo
);
1387 MyFreePool__(Vcb
->NonAllocFileInfo
);
1388 Vcb
->NonAllocFileInfo
= NULL
;
1390 // Deinitialize Unique ID Mapping
1391 KdPrint(("UDFCloseResidual: NonAllocFileInfo %x\n", Vcb
->NonAllocFileInfo
));
1392 if(Vcb
->UniqueIDMapFileInfo
) {
1393 UDFCloseFile__(Vcb
,Vcb
->UniqueIDMapFileInfo
);
1394 UDFCleanUpFile__(Vcb
, Vcb
->UniqueIDMapFileInfo
);
1395 MyFreePool__(Vcb
->UniqueIDMapFileInfo
);
1396 Vcb
->UniqueIDMapFileInfo
= NULL
;
1398 // Deinitialize VAT file
1399 KdPrint(("UDFCloseResidual: VatFileInfo %x\n", Vcb
->VatFileInfo
));
1400 if(Vcb
->VatFileInfo
) {
1401 UDFCloseFile__(Vcb
,Vcb
->VatFileInfo
);
1402 UDFCleanUpFile__(Vcb
, Vcb
->VatFileInfo
);
1403 MyFreePool__(Vcb
->VatFileInfo
);
1404 Vcb
->VatFileInfo
= NULL
;
1407 KdPrint(("UDFCloseResidual: SysSDirFileInfo %x\n", Vcb
->SysSDirFileInfo
));
1408 if(Vcb
->SysSDirFileInfo
) {
1409 UDFCloseFile__(Vcb
, Vcb
->SysSDirFileInfo
);
1410 UDFCleanUpFile__(Vcb
, Vcb
->SysSDirFileInfo
);
1411 MyFreePool__(Vcb
->SysSDirFileInfo
);
1412 Vcb
->SysSDirFileInfo
= NULL
;
1414 /* // Deinitialize root dir fcb
1415 if(Vcb->RootDirFCB) {
1416 UDFCloseFile__(Vcb,Vcb->RootDirFCB->FileInfo);
1417 UDFCleanUpFile__(Vcb, Vcb->RootDirFCB->FileInfo);
1418 MyFreePool__(Vcb->RootDirFCB->FileInfo);
1419 UDFCleanUpFCB(Vcb->RootDirFCB);
1420 // Remove root FCB reference in vcb
1421 if(Vcb->VCBOpenCount) Vcb->VCBOpenCount--;
1424 // Deinitialize Non-alloc file
1425 if(Vcb->VCBOpenCount) Vcb->VCBOpenCount--;
1426 if(Vcb->NonAllocFileInfo) {
1427 UDFCloseFile__(Vcb,Vcb->NonAllocFileInfo);
1428 // We must release VCB here !!!!
1429 // UDFCleanUpFcbChain(Vcb, Vcb->NonAllocFileInfo, 1);
1430 Vcb->NonAllocFileInfo = NULL;
1432 // Deinitialize VAT file
1433 if(Vcb->VatFileInfo) {
1434 UDFCloseFile__(Vcb,Vcb->VatFileInfo);
1435 // We must release VCB here !!!!
1436 // UDFCleanUpFcbChain(Vcb, Vcb->VatFileInfo, 1);
1437 Vcb->VatFileInfo = NULL;
1440 // Deinitialize root dir fcb
1441 KdPrint(("UDFCloseResidual: RootDirFCB %x\n", Vcb
->RootDirFCB
));
1442 if(Vcb
->RootDirFCB
) {
1443 UDFCloseFile__(Vcb
,Vcb
->RootDirFCB
->FileInfo
);
1444 if(Vcb
->RootDirFCB
->OpenHandleCount
)
1445 Vcb
->RootDirFCB
->OpenHandleCount
--;
1446 UDFCleanUpFcbChain(Vcb
, Vcb
->RootDirFCB
->FileInfo
, 1, TRUE
);
1447 // Remove root FCB reference in vcb
1448 if(Vcb
->VCBOpenCount
)
1449 UDFInterlockedDecrement((PLONG
)&(Vcb
->VCBOpenCount
));
1450 Vcb
->RootDirFCB
= NULL
;
1452 } // end UDFCloseResidual()
1460 UDFReleaseFileIdCache(Vcb
);
1461 UDFReleaseDlocList(Vcb
);
1462 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1466 if(Vcb
->ShutdownRegistered
&& Vcb
->VCBDeviceObject
) {
1467 IoUnregisterShutdownNotification(Vcb
->VCBDeviceObject
);
1468 Vcb
->ShutdownRegistered
= FALSE
;
1471 MyFreeMemoryAndPointer(Vcb
->Partitions
);
1472 MyFreeMemoryAndPointer(Vcb
->LVid
);
1473 MyFreeMemoryAndPointer(Vcb
->Vat
);
1474 MyFreeMemoryAndPointer(Vcb
->SparingTable
);
1476 if(Vcb
->FSBM_Bitmap
) {
1477 DbgFreePool(Vcb
->FSBM_Bitmap
);
1478 Vcb
->FSBM_Bitmap
= NULL
;
1480 if(Vcb
->ZSBM_Bitmap
) {
1481 DbgFreePool(Vcb
->ZSBM_Bitmap
);
1482 Vcb
->ZSBM_Bitmap
= NULL
;
1484 if(Vcb
->BSBM_Bitmap
) {
1485 DbgFreePool(Vcb
->BSBM_Bitmap
);
1486 Vcb
->BSBM_Bitmap
= NULL
;
1488 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1489 if(Vcb
->FSBM_Bitmap_owners
) {
1490 DbgFreePool(Vcb
->FSBM_Bitmap_owners
);
1491 Vcb
->FSBM_Bitmap_owners
= NULL
;
1493 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1494 if(Vcb
->FSBM_OldBitmap
) {
1495 DbgFreePool(Vcb
->FSBM_OldBitmap
);
1496 Vcb
->FSBM_OldBitmap
= NULL
;
1499 MyFreeMemoryAndPointer(Vcb
->Statistics
);
1500 MyFreeMemoryAndPointer(Vcb
->NTRequiredFCB
);
1501 MyFreeMemoryAndPointer(Vcb
->VolIdent
.Buffer
);
1502 MyFreeMemoryAndPointer(Vcb
->TargetDevName
.Buffer
);
1505 DbgFreePool(Vcb
->ZBuffer
);
1506 Vcb
->ZBuffer
= NULL
;
1510 DbgFreePool(Vcb
->fZBuffer
);
1511 Vcb
->fZBuffer
= NULL
;
1514 MyFreeMemoryAndPointer(Vcb
->OPCh
);
1515 MyFreeMemoryAndPointer(Vcb
->WParams
);
1516 MyFreeMemoryAndPointer(Vcb
->Error
);
1517 MyFreeMemoryAndPointer(Vcb
->TrackMap
);
1519 } // end UDFCleanupVCB()
1523 Routine Description:
1525 This routine walks through the list of Vcb's looking for any which may
1526 now be deleted. They may have been left on the list because there were
1527 outstanding references.
1537 UDFScanForDismountedVcb(
1538 IN PtrUDFIrpContext IrpContext
1545 // Walk through all of the Vcb's attached to the global data.
1546 Link
= UDFGlobalData
.VCBQueue
.Flink
;
1548 while (Link
!= &(UDFGlobalData
.VCBQueue
)) {
1550 Vcb
= CONTAINING_RECORD( Link
, VCB
, NextVCB
);
1552 // Move to the next link now since the current Vcb may be deleted.
1555 // If dismount is already underway then check if this Vcb can
1557 if((Vcb
->VCBFlags
& UDF_VCB_FLAGS_BEING_DISMOUNTED
) ||
1558 ((!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
)) && (Vcb
->VCBOpenCount
<= UDF_RESIDUAL_REFERENCE
))) {
1560 UDFCheckForDismount( IrpContext
, Vcb
, FALSE
);
1565 } // end UDFScanForDismountedVcb()
1568 Routine Description:
1569 This routine determines if a volume is currently mounted.
1572 Irp - Supplies the Irp to process
1575 NTSTATUS - The return status for the operation
1580 IN PtrUDFIrpContext IrpContext
,
1584 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1589 KdPrint(("UDFIsVolumeMounted\n"));
1591 Ccb
= (PtrUDFCCB
)IrpSp
->FileObject
->FsContext2
;
1593 KdPrint((" !Ccb\n"));
1594 Irp
->IoStatus
.Information
= 0;
1595 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1596 return STATUS_INVALID_PARAMETER
;
1601 !(Fcb
->Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
) &&
1602 !(Fcb
->Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_LOCKED
) ) {
1604 // Disable PopUps, we want to return any error.
1605 IrpContext
->IrpContextFlags
|= UDF_IRP_CONTEXT_FLAG_DISABLE_POPUPS
;
1607 // Verify the Vcb. This will raise in the error condition.
1608 UDFVerifyVcb( IrpContext
, Fcb
->Vcb
);
1611 Irp
->IoStatus
.Information
= 0;
1612 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1614 return STATUS_SUCCESS
;
1615 } // end UDFIsVolumeMounted()
1618 This routine returns the filesystem performance counters from the
1622 Irp - Supplies the Irp to process
1625 NTSTATUS - The return status for the operation
1629 IN PtrUDFIrpContext IrpContext
,
1633 PEXTENDED_IO_STACK_LOCATION IrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
1637 PFILE_SYSTEM_STATISTICS Buffer
;
1642 KdPrint(("UDFGetStatistics\n"));
1644 // Extract the buffer
1645 BufferLength
= IrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
1646 // Get a pointer to the output buffer.
1647 Buffer
= (PFILE_SYSTEM_STATISTICS
)(Irp
->AssociatedIrp
.SystemBuffer
);
1649 // Make sure the buffer is big enough for at least the common part.
1650 if (BufferLength
< sizeof(FILESYSTEM_STATISTICS
)) {
1651 status
= STATUS_BUFFER_TOO_SMALL
;
1652 Irp
->IoStatus
.Information
= 0;
1656 // Now see how many bytes we can copy.
1657 StatsSize
= sizeof(FILE_SYSTEM_STATISTICS
) * KeNumberProcessors
;
1658 if (BufferLength
< StatsSize
) {
1659 BytesToCopy
= BufferLength
;
1660 status
= STATUS_BUFFER_OVERFLOW
;
1662 BytesToCopy
= StatsSize
;
1663 status
= STATUS_SUCCESS
;
1666 Vcb
= (PVCB
)(((PDEVICE_OBJECT
)IrpSp
->DeviceObject
)->DeviceExtension
);
1667 // Fill in the output buffer
1668 RtlCopyMemory( Buffer
, Vcb
->Statistics
, BytesToCopy
);
1669 Irp
->IoStatus
.Information
= BytesToCopy
;
1671 Irp
->IoStatus
.Status
= status
;
1674 } // end UDFGetStatistics()
1678 This routine determines if pathname is valid path for UDF Filesystem
1681 Irp - Supplies the Irp to process
1684 NTSTATUS - The return status for the operation
1688 IN PtrUDFIrpContext IrpContext
,
1692 PEXTENDED_IO_STACK_LOCATION IrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
1694 PPATHNAME_BUFFER PathnameBuffer
;
1695 UNICODE_STRING PathName
;
1696 UNICODE_STRING CurName
;
1699 KdPrint(("UDFIsPathnameValid\n"));
1701 // Extract the pathname
1702 PathnameBuffer
= (PPATHNAME_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
1703 PathName
.Buffer
= PathnameBuffer
->Name
;
1704 PathName
.Length
= (USHORT
)PathnameBuffer
->PathNameLength
;
1707 // Check for an invalid buffer
1708 if (FIELD_OFFSET(PATHNAME_BUFFER
, Name
[0]) + PathnameBuffer
->PathNameLength
>
1709 IrpSp
->Parameters
.FileSystemControl
.InputBufferLength
) {
1710 try_return( RC
= STATUS_INVALID_PARAMETER
);
1713 // get next path part...
1714 TmpBuffer
= PathName
.Buffer
;
1715 PathName
.Buffer
= UDFDissectName(PathName
.Buffer
,&(CurName
.Length
) );
1716 PathName
.Length
-= (USHORT
)((ULONG
)(PathName
.Buffer
) - (ULONG
)TmpBuffer
);
1717 CurName
.Buffer
= PathName
.Buffer
- CurName
.Length
;
1718 CurName
.Length
*= sizeof(WCHAR
);
1719 CurName
.MaximumLength
-= CurName
.Length
;
1721 if (CurName
.Length
) {
1722 // check path fragment size
1723 if (CurName
.Length
> UDF_NAME_LEN
*sizeof(WCHAR
)) {
1724 try_return(RC
= STATUS_OBJECT_NAME_INVALID
);
1726 if (!UDFIsNameValid(&CurName
, NULL
, NULL
)) {
1727 try_return(RC
= STATUS_OBJECT_NAME_INVALID
);
1730 try_return(RC
= STATUS_SUCCESS
);
1735 Irp
->IoStatus
.Information
= 0;
1736 Irp
->IoStatus
.Status
= RC
;
1740 } // end UDFIsPathnameValid()
1743 This routine performs the lock volume operation. It is responsible for
1744 either completing of enqueuing the input Irp.
1746 Irp - Supplies the Irp to process
1748 NTSTATUS - The return status for the operation
1752 IN PtrUDFIrpContext IrpContext
,
1760 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1765 BOOLEAN VcbAcquired
= FALSE
;
1767 KdPrint(("UDFLockVolume: PID %x\n", PID
));
1769 // Decode the file object, the only type of opens we accept are
1770 // user volume opens.
1771 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
1773 KdPrint((" !Ccb\n"));
1774 Irp
->IoStatus
.Information
= 0;
1775 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1776 return STATUS_INVALID_PARAMETER
;
1781 // Check for volume open
1782 if (Vcb
!= (PVCB
)Fcb
|| !(Ccb
->CCBFlags
& UDF_CCB_VOLUME_OPEN
)) {
1783 Irp
->IoStatus
.Information
= 0;
1784 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1785 return STATUS_INVALID_PARAMETER
;
1788 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_LOCK
);
1792 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
))
1793 UDFCloseAllSystemDelayedInDir(Vcb
, Vcb
->RootDirFCB
->FileInfo
);
1794 #ifdef UDF_DELAYED_CLOSE
1795 UDFCloseAllDelayed(Vcb
);
1796 #endif //UDF_DELAYED_CLOSE
1798 // Acquire exclusive access to the Vcb.
1799 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
1803 UDFVerifyVcb( IrpContext
, Vcb
);
1805 // If the volume is already locked then complete with success if this file
1806 // object has the volume locked, fail otherwise.
1807 /* if (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) {
1809 if (Vcb->VolumeLockFileObject == IrpSp->FileObject) {
1810 RC = STATUS_SUCCESS;
1812 RC = STATUS_ACCESS_DENIED;
1814 // If the open count for the volume is greater than 1 then this request
1816 } else if (Vcb->VCBOpenCount > UDF_RESIDUAL_REFERENCE+1) {
1817 RC = STATUS_ACCESS_DENIED;
1818 // We will try to get rid of all of the user references. If there is only one
1819 // remaining after the purge then we can allow the volume to be locked.
1821 // flush system cache
1822 UDFReleaseResource( &(Vcb->VCBResource) );
1823 VcbAcquired = FALSE;
1830 UDFReleaseResource( &(Vcb
->VCBResource
) );
1831 VcbAcquired
= FALSE
;
1835 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
1837 UDFFlushLogicalVolume(NULL
, NULL
, Vcb
/*, 0*/);
1838 UDFReleaseResource( &(Vcb
->VCBResource
) );
1839 VcbAcquired
= FALSE
;
1840 // Check if the Vcb is already locked, or if the open file count
1841 // is greater than 1 (which implies that someone else also is
1842 // currently using the volume, or a file on the volume).
1843 IoAcquireVpbSpinLock( &SavedIrql
);
1845 if (!(Vcb
->Vpb
->Flags
& VPB_LOCKED
) &&
1846 (Vcb
->VolumeLockPID
== -1) &&
1847 (Vcb
->VCBOpenCount
<= UDF_RESIDUAL_REFERENCE
+1) &&
1848 (Vcb
->Vpb
->ReferenceCount
== 2)) {
1850 // Mark volume as locked
1852 Vcb
->Vpb
->Flags
|= VPB_LOCKED
;
1854 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_VOLUME_LOCKED
;
1855 Vcb
->VolumeLockFileObject
= IrpSp
->FileObject
;
1856 Vcb
->VolumeLockPID
= PID
;
1858 RC
= STATUS_SUCCESS
;
1862 RC
= STATUS_ACCESS_DENIED
;
1865 IoReleaseVpbSpinLock( SavedIrql
);
1867 if(!NT_SUCCESS(RC
)) {
1868 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_LOCK_FAILED
);
1871 // Complete the request if there haven't been any exceptions.
1872 Irp
->IoStatus
.Information
= 0;
1873 Irp
->IoStatus
.Status
= RC
;
1875 } // end UDFLockVolume()
1878 This routine performs the unlock volume operation. It is responsible for
1879 either completing of enqueuing the input Irp.
1881 Irp - Supplies the Irp to process
1883 NTSTATUS - The return status for the operation
1887 IN PtrUDFIrpContext IrpContext
,
1892 NTSTATUS RC
= STATUS_INVALID_PARAMETER
;
1895 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1901 KdPrint(("UDFUnlockVolume: PID %x\n", PID
));
1903 // Decode the file object, the only type of opens we accept are
1904 // user volume opens.
1905 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
1907 KdPrint((" !Ccb\n"));
1908 Irp
->IoStatus
.Information
= 0;
1909 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1910 return STATUS_INVALID_PARAMETER
;
1915 // Check for volume open
1916 if(Vcb
!= (PVCB
)Fcb
|| !(Ccb
->CCBFlags
& UDF_CCB_VOLUME_OPEN
)) {
1917 Irp
->IoStatus
.Information
= 0;
1918 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1919 return STATUS_INVALID_PARAMETER
;
1922 // Acquire exclusive access to the Vcb/Vpb.
1923 IoAcquireVpbSpinLock( &SavedIrql
);
1927 // We won't check for a valid Vcb for this request. An unlock will always
1928 // succeed on a locked volume.
1929 if(Vcb
->Vpb
->Flags
& VPB_LOCKED
||
1930 Vcb
->VolumeLockPID
== PID
) {
1931 Vcb
->Vpb
->Flags
&= ~VPB_LOCKED
;
1932 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_VOLUME_LOCKED
;
1933 Vcb
->VolumeLockFileObject
= NULL
;
1934 Vcb
->VolumeLockPID
= -1;
1935 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_UNLOCK
);
1936 RC
= STATUS_SUCCESS
;
1938 RC
= STATUS_NOT_LOCKED
;
1939 RC
= STATUS_SUCCESS
;
1940 RC
= STATUS_VOLUME_DISMOUNTED
;
1947 // Release all of our resources
1948 IoReleaseVpbSpinLock( SavedIrql
);
1950 // Complete the request if there haven't been any exceptions.
1951 Irp
->IoStatus
.Information
= 0;
1952 Irp
->IoStatus
.Status
= RC
;
1954 } // end UDFUnlockVolume()
1958 This routine performs the dismount volume operation. It is responsible for
1959 either completing of enqueuing the input Irp. We only dismount a volume which
1960 has been locked. The intent here is that someone has locked the volume (they are the
1961 only remaining handle). We set the verify bit here and the user will close his handle.
1962 We will dismount a volume with no user's handles in the verify path.
1964 Irp - Supplies the Irp to process
1966 NTSTATUS - The return status for the operation
1970 IN PtrUDFIrpContext IrpContext
,
1976 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation( Irp
);
1981 PPREVENT_MEDIA_REMOVAL_USER_IN Buf
= NULL
;
1982 BOOLEAN VcbAcquired
= FALSE
;
1984 KdPrint(("\n ### UDFDismountVolume ###\n\n"));
1986 // Decode the file object, the only type of opens we accept are
1987 // user volume opens.
1988 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
1990 KdPrint((" !Ccb\n"));
1991 Irp
->IoStatus
.Information
= 0;
1992 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
1993 return STATUS_INVALID_PARAMETER
;
1998 // Check for volume open
1999 if(Vcb
!= (PVCB
)Fcb
|| !(Ccb
->CCBFlags
& UDF_CCB_VOLUME_OPEN
)) {
2000 Irp
->IoStatus
.Information
= 0;
2001 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2002 return STATUS_INVALID_PARAMETER
;
2005 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_DISMOUNT
);
2007 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_RAW_DISK
))
2008 UDFCloseAllSystemDelayedInDir(Vcb
, Vcb
->RootDirFCB
->FileInfo
);
2009 #ifdef UDF_DELAYED_CLOSE
2010 UDFCloseAllDelayed(Vcb
);
2011 #endif //UDF_DELAYED_CLOSE
2013 // Acquire exclusive access to the Vcb.
2014 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
2019 // Mark the volume as needs to be verified, but only do it if
2020 // the vcb is locked by this handle and the volume is currently mounted.
2022 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
)) {
2023 // disable Eject Request Waiter if any
2024 UDFReleaseResource( &(Vcb
->VCBResource
) );
2025 VcbAcquired
= FALSE
;
2027 UDFStopEjectWaiter(Vcb
);
2028 RC
= STATUS_SUCCESS
;
2030 if(/*!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) ||*/
2031 !(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_LOCKED
) ||
2032 (Vcb
->VCBOpenCount
> (UDF_RESIDUAL_REFERENCE
+1))) {
2034 RC
= STATUS_NOT_LOCKED
;
2036 if((Vcb
->VolumeLockFileObject
!= IrpSp
->FileObject
)) {
2038 RC
= STATUS_INVALID_PARAMETER
;
2042 Vcb
->Vpb
->RealDevice
->Flags
|= DO_VERIFY_VOLUME
;
2043 Buf
= (PPREVENT_MEDIA_REMOVAL_USER_IN
)MyAllocatePool__(NonPagedPool
, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
));
2044 if(!Buf
) try_return(RC
= STATUS_INSUFFICIENT_RESOURCES
);
2045 UDFDoDismountSequence(Vcb
, Buf
, FALSE
);
2046 Vcb
->VCBFlags
&= ~UDF_VCB_FLAGS_VOLUME_MOUNTED
;
2047 Vcb
->WriteSecurity
= FALSE
;
2048 // disable Eject Request Waiter if any
2049 UDFReleaseResource( &(Vcb
->VCBResource
) );
2050 VcbAcquired
= FALSE
;
2052 UDFStopEjectWaiter(Vcb
);
2053 RC
= STATUS_SUCCESS
;
2058 if(Buf
) MyFreePool__(Buf
);
2059 // Release all of our resources
2061 UDFReleaseResource( &(Vcb
->VCBResource
) );
2064 if(!NT_SUCCESS(RC
)) {
2065 UDFNotifyVolumeEvent(IrpSp
->FileObject
, FSRTL_VOLUME_DISMOUNT_FAILED
);
2068 // Complete the request if there haven't been any exceptions.
2069 Irp
->IoStatus
.Information
= 0;
2070 Irp
->IoStatus
.Status
= RC
;
2072 } // end UDFDismountVolume()
2076 This routine returns the volume allocation bitmap.
2078 Input = the STARTING_LCN_INPUT_BUFFER data structure is passed in
2079 through the input buffer.
2080 Output = the VOLUME_BITMAP_BUFFER data structure is returned through
2083 We return as much as the user buffer allows starting the specified input
2084 LCN (trucated to a byte). If there is no input buffer, we start at zero.
2088 Irp - Supplies the Irp being processed.
2092 NTSTATUS - The return status for the operation.
2097 IN PtrUDFIrpContext IrpContext
,
2103 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2104 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2110 KdPrint(("UDFGetVolumeBitmap\n"));
2113 ULONG TotalClusters
;
2114 ULONG DesiredClusters
;
2115 ULONG StartingCluster
;
2116 ULONG InputBufferLength
;
2117 ULONG OutputBufferLength
;
2118 LARGE_INTEGER StartingLcn
;
2119 PVOLUME_BITMAP_BUFFER OutputBuffer
;
2124 // Decode the file object, the only type of opens we accept are
2125 // user volume opens.
2126 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
2128 KdPrint((" !Ccb\n"));
2129 Irp
->IoStatus
.Information
= 0;
2130 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2131 return STATUS_INVALID_PARAMETER
;
2136 InputBufferLength
= IrpSp
->Parameters
.FileSystemControl
.InputBufferLength
;
2137 OutputBufferLength
= IrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
2139 OutputBuffer
= (PVOLUME_BITMAP_BUFFER
)UDFGetCallersBuffer(IrpContext
, Irp
);
2141 return STATUS_INVALID_USER_BUFFER
;
2143 // Check for a minimum length on the input and output buffers.
2144 if ((InputBufferLength
< sizeof(STARTING_LCN_INPUT_BUFFER
)) ||
2145 (OutputBufferLength
< sizeof(VOLUME_BITMAP_BUFFER
))) {
2147 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2148 Irp
->IoStatus
.Information
= 0;
2149 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
2150 return STATUS_BUFFER_TOO_SMALL
;
2153 // Check if a starting cluster was specified.
2154 TotalClusters
= Vcb
->FSBM_BitCount
;
2155 StartingLcn
= ((PSTARTING_LCN_INPUT_BUFFER
)IrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
)->StartingLcn
;
2157 if (StartingLcn
.HighPart
|| StartingLcn
.LowPart
>= TotalClusters
) {
2159 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2160 Irp
->IoStatus
.Information
= 0;
2161 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2162 return STATUS_INVALID_PARAMETER
;
2166 StartingCluster
= StartingLcn
.LowPart
& ~7;
2169 OutputBufferLength
-= FIELD_OFFSET(VOLUME_BITMAP_BUFFER
, Buffer
);
2170 DesiredClusters
= TotalClusters
- StartingCluster
;
2172 if (OutputBufferLength
< (DesiredClusters
+ 7) / 8) {
2174 BytesToCopy
= OutputBufferLength
;
2175 RC
= STATUS_BUFFER_OVERFLOW
;
2179 BytesToCopy
= (DesiredClusters
+ 7) / 8;
2180 RC
= STATUS_SUCCESS
;
2183 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
2187 // Fill in the fixed part of the output buffer
2188 OutputBuffer
->StartingLcn
.QuadPart
= StartingCluster
;
2189 OutputBuffer
->BitmapSize
.QuadPart
= DesiredClusters
;
2191 RtlZeroMemory( &OutputBuffer
->Buffer
[0], BytesToCopy
);
2192 lim
= BytesToCopy
* 8;
2193 FSBM
= (PULONG
)(Vcb
->FSBM_Bitmap
);
2194 LSh
= Vcb
->LB2B_Bits
;
2195 Dest
= (PULONG
)(&OutputBuffer
->Buffer
[0]);
2197 for(i
=StartingCluster
& ~7; i
<lim
; i
++) {
2198 if(UDFGetFreeBit(FSBM
, i
<<LSh
))
2199 UDFSetFreeBit(FSBM
, i
);
2202 } _SEH2_EXCEPT(UDFExceptionFilter(IrpContext
, _SEH2_GetExceptionInformation())) {
2205 KdPrint(("UDFGetVolumeBitmap: Exception\n"));
2206 // UDFUnlockCallersBuffer(IrpContext, Irp, OutputBuffer);
2208 // RC = UDFExceptionHandler(IrpContext, Irp);
2209 UDFReleaseResource(&(Vcb
->VCBResource
));
2210 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2212 Irp
->IoStatus
.Information
= 0;
2213 Irp
->IoStatus
.Status
= STATUS_INVALID_USER_BUFFER
;
2214 return STATUS_INVALID_USER_BUFFER
;
2217 UDFReleaseResource(&(Vcb
->VCBResource
));
2219 UDFUnlockCallersBuffer(IrpContext
, Irp
, OutputBuffer
);
2220 Irp
->IoStatus
.Information
= FIELD_OFFSET(VOLUME_BITMAP_BUFFER
, Buffer
) +
2222 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2224 return STATUS_SUCCESS
;
2227 } // end UDFGetVolumeBitmap()
2231 UDFGetRetrievalPointers(
2232 IN PtrUDFIrpContext IrpContext
,
2239 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2240 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2245 PUDF_FILE_INFO FileInfo
;
2247 ULONG InputBufferLength
;
2248 ULONG OutputBufferLength
;
2250 PRETRIEVAL_POINTERS_BUFFER OutputBuffer
;
2251 PSTARTING_VCN_INPUT_BUFFER InputBuffer
;
2253 LARGE_INTEGER StartingVcn
;
2254 int64 AllocationSize
;
2256 PEXTENT_MAP SubMapping
= NULL
;
2263 KdPrint(("UDFGetRetrievalPointers\n"));
2265 // Decode the file object, the only type of opens we accept are
2266 // user volume opens.
2267 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
2269 KdPrint((" !Ccb\n"));
2270 Irp
->IoStatus
.Information
= 0;
2271 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2272 return STATUS_INVALID_PARAMETER
;
2277 // Get the input and output buffer lengths and pointers.
2278 // Initialize some variables.
2279 InputBufferLength
= IrpSp
->Parameters
.FileSystemControl
.InputBufferLength
;
2280 OutputBufferLength
= IrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
2282 //OutputBuffer = (PRETRIEVAL_POINTERS_BUFFER)UDFGetCallersBuffer( IrpContext, Irp );
2284 OutputBuffer
= (PRETRIEVAL_POINTERS_BUFFER
)Irp
->AssociatedIrp
.SystemBuffer
;
2286 OutputBuffer
= (PRETRIEVAL_POINTERS_BUFFER
)Irp
->UserBuffer
;
2288 InputBuffer
= (PSTARTING_VCN_INPUT_BUFFER
)IrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
;
2290 InputBuffer
= (PSTARTING_VCN_INPUT_BUFFER
)OutputBuffer
;
2295 Irp
->IoStatus
.Information
= 0;
2296 // Check for a minimum length on the input and ouput buffers.
2297 if ((InputBufferLength
< sizeof(STARTING_VCN_INPUT_BUFFER
)) ||
2298 (OutputBufferLength
< sizeof(RETRIEVAL_POINTERS_BUFFER
))) {
2300 try_return( RC
= STATUS_BUFFER_TOO_SMALL
);
2305 if (Irp
->RequestorMode
!= KernelMode
) {
2306 ProbeForRead( IrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
,
2309 ProbeForWrite( OutputBuffer
, OutputBufferLength
, sizeof(UCHAR
) );
2311 StartingVcn
= InputBuffer
->StartingVcn
;
2313 } _SEH2_EXCEPT(Irp
->RequestorMode
!= KernelMode
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
) {
2315 RC
= _SEH2_GetExceptionCode();
2316 RC
= FsRtlIsNtstatusExpected(RC
) ?
2317 RC
: STATUS_INVALID_USER_BUFFER
;
2323 FileInfo
= Fcb
->FileInfo
;
2326 FileInfo
= Vcb
->NonAllocFileInfo
;
2329 try_return( RC
= STATUS_INVALID_PARAMETER
);
2333 try_return( RC
= STATUS_OBJECT_NAME_NOT_FOUND
);
2336 AllocationSize
= UDFGetFileAllocationSize(Vcb
, FileInfo
);
2338 LBS
= Vcb
->LBlockSize
;
2339 LBSh
= Vcb
->LBlockSizeBits
;
2340 L2BSh
= Vcb
->LB2B_Bits
;
2342 if (StartingVcn
.HighPart
||
2343 StartingVcn
.LowPart
>= (ULONG
)(AllocationSize
>> LBSh
)) {
2345 try_return( RC
= STATUS_END_OF_FILE
);
2348 SubExtInfoSz
= (OutputBufferLength
- FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER
, Extents
[0])) / (sizeof(LARGE_INTEGER
)*2);
2349 // re-use AllocationSize as NextVcn
2350 RC
= UDFReadFileLocation__(Vcb
, FileInfo
, StartingVcn
.QuadPart
<< LBSh
,
2351 &SubMapping
, &SubExtInfoSz
, &AllocationSize
);
2355 OutputBuffer
->ExtentCount
= SubExtInfoSz
;
2356 OutputBuffer
->StartingVcn
= StartingVcn
;
2357 for(i
=0; i
<SubExtInfoSz
; i
++) {
2359 // for not-allocated extents we have start Lba = -1
2360 // for not-recorded extents start Lba.LowPart contains real Lba, Lba.HighPart = 0x80000000
2361 // for recorded extents Lba.LowPart contains real Lba, Lba.HighPart = 0
2362 if(SubMapping
[i
].extLocation
== LBA_NOT_ALLOCATED
) {
2363 OutputBuffer
->Extents
[i
].Lcn
.QuadPart
= (int64
)(-1);
2365 if(SubMapping
[i
].extLocation
& 0x80000000) {
2366 OutputBuffer
->Extents
[i
].Lcn
.LowPart
= (SubMapping
[i
].extLocation
& 0x7fffffff) >> L2BSh
;
2367 OutputBuffer
->Extents
[i
].Lcn
.HighPart
= 0x80000000;
2369 OutputBuffer
->Extents
[i
].Lcn
.LowPart
= SubMapping
[i
].extLocation
>> L2BSh
;
2370 OutputBuffer
->Extents
[i
].Lcn
.HighPart
= 0;
2372 // alignment for last sector
2373 SubMapping
[i
].extLength
+= LBS
-1;
2374 StartingVcn
.QuadPart
+= SubMapping
[i
].extLength
>> LBSh
;
2375 OutputBuffer
->Extents
[i
].NextVcn
= StartingVcn
;
2378 Irp
->IoStatus
.Information
= FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER
, Extents
[0]) + i
* sizeof(LARGE_INTEGER
) * 2;
2384 MyFreePool__(SubMapping
);
2385 Irp
->IoStatus
.Status
= RC
;
2389 } // end UDFGetRetrievalPointers()
2394 IN PtrUDFIrpContext IrpContext
,
2399 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2400 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2406 KdPrint(("UDFIsVolumeDirty\n"));
2408 Irp
->IoStatus
.Information
= 0;
2410 if (Irp
->AssociatedIrp
.SystemBuffer
!= NULL
) {
2411 VolumeState
= (PULONG
)(Irp
->AssociatedIrp
.SystemBuffer
);
2412 } else if (Irp
->MdlAddress
!= NULL
) {
2413 VolumeState
= (PULONG
)MmGetSystemAddressForMdl(Irp
->MdlAddress
);
2415 KdPrint((" STATUS_INVALID_USER_BUFFER\n"));
2416 Irp
->IoStatus
.Status
= STATUS_INVALID_USER_BUFFER
;
2417 return STATUS_INVALID_USER_BUFFER
;
2420 if (IrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
< sizeof(ULONG
)) {
2421 KdPrint((" STATUS_BUFFER_TOO_SMALL\n"));
2422 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
2423 return STATUS_BUFFER_TOO_SMALL
;
2428 // Decode the file object, the only type of opens we accept are
2429 // user volume opens.
2430 Ccb
= (PtrUDFCCB
)(IrpSp
->FileObject
->FsContext2
);
2432 KdPrint((" !Ccb\n"));
2433 Irp
->IoStatus
.Information
= 0;
2434 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2435 return STATUS_INVALID_PARAMETER
;
2440 if(Vcb
!= (PVCB
)Fcb
|| !(Ccb
->CCBFlags
& UDF_CCB_VOLUME_OPEN
)) {
2441 KdPrint((" !Volume\n"));
2442 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2443 return STATUS_INVALID_PARAMETER
;
2446 if(!(Vcb
->VCBFlags
& UDF_VCB_FLAGS_VOLUME_MOUNTED
)) {
2447 KdPrint((" !Mounted\n"));
2448 Irp
->IoStatus
.Status
= STATUS_VOLUME_DISMOUNTED
;
2449 return STATUS_VOLUME_DISMOUNTED
;
2452 if(Vcb
->origIntegrityType
== INTEGRITY_TYPE_OPEN
) {
2453 KdPrint((" Dirty\n"));
2454 (*VolumeState
) |= VOLUME_IS_DIRTY
;
2455 Irp
->IoStatus
.Information
= sizeof(ULONG
);
2457 KdPrint((" Clean\n"));
2459 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2461 return STATUS_SUCCESS
;
2463 } // end UDFIsVolumeDirty()
2467 UDFInvalidateVolumes(
2468 IN PtrUDFIrpContext IrpContext
,
2473 PEXTENDED_IO_STACK_LOCATION IrpSp
=
2474 (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation( Irp
);
2475 PPREVENT_MEDIA_REMOVAL_USER_IN Buf
= NULL
;
2477 KdPrint(("UDFInvalidateVolumes\n"));
2481 LUID TcbPrivilege
= {SE_TCB_PRIVILEGE
, 0};
2490 PFILE_OBJECT FileToMarkBad
;
2491 PDEVICE_OBJECT DeviceToMarkBad
;
2493 Irp
->IoStatus
.Information
= 0;
2495 // Check for the correct security access.
2496 // The caller must have the SeTcbPrivilege.
2497 if (IrpSp
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
&&
2498 IrpSp
->MinorFunction
== IRP_MN_USER_FS_REQUEST
&&
2499 IrpSp
->Parameters
.FileSystemControl
.FsControlCode
== FSCTL_INVALIDATE_VOLUMES
&&
2500 !SeSinglePrivilegeCheck( TcbPrivilege
, UserMode
)) {
2501 KdPrint(("UDFInvalidateVolumes: STATUS_PRIVILEGE_NOT_HELD\n"));
2502 Irp
->IoStatus
.Status
= STATUS_PRIVILEGE_NOT_HELD
;
2503 return STATUS_PRIVILEGE_NOT_HELD
;
2505 // Try to get a pointer to the device object from the handle passed in.
2506 if (IrpSp
->Parameters
.FileSystemControl
.InputBufferLength
!= sizeof( HANDLE
)) {
2507 KdPrint(("UDFInvalidateVolumes: STATUS_INVALID_PARAMETER\n"));
2508 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
2509 return STATUS_INVALID_PARAMETER
;
2512 Handle
= *((PHANDLE
) Irp
->AssociatedIrp
.SystemBuffer
);
2514 RC
= ObReferenceObjectByHandle( Handle
,
2518 (PVOID
*)&FileToMarkBad
,
2521 if (!NT_SUCCESS(RC
)) {
2522 KdPrint(("UDFInvalidateVolumes: can't get handle, RC=%x\n", RC
));
2523 Irp
->IoStatus
.Status
= RC
;
2527 // We only needed the pointer, not a reference.
2528 ObDereferenceObject( FileToMarkBad
);
2530 // Grab the DeviceObject from the FileObject.
2531 DeviceToMarkBad
= FileToMarkBad
->DeviceObject
;
2533 // Create a new Vpb for this device so that any new opens will mount
2535 NewVpb
= (PVPB
)DbgAllocatePoolWithTag( NonPagedPool
, sizeof( VPB
), 'bpvU' );
2537 KdPrint(("UDFInvalidateVolumes: STATUS_INSUFFICIENT_RESOURCES\n"));
2538 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
2539 return STATUS_INSUFFICIENT_RESOURCES
;
2541 RtlZeroMemory( NewVpb
, sizeof( VPB
) );
2543 NewVpb
->Type
= IO_TYPE_VPB
;
2544 NewVpb
->Size
= sizeof( VPB
);
2545 NewVpb
->RealDevice
= DeviceToMarkBad
;
2546 NewVpb
->Flags
= DeviceToMarkBad
->Vpb
->Flags
& VPB_REMOVE_PENDING
;
2548 // Acquire GlobalDataResource
2549 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
2551 // Nothing can go wrong now.
2552 IoAcquireVpbSpinLock( &SavedIrql
);
2553 if (DeviceToMarkBad
->Vpb
->Flags
& VPB_MOUNTED
) {
2554 DeviceToMarkBad
->Vpb
= NewVpb
;
2557 ASSERT( DeviceToMarkBad
->Vpb
->DeviceObject
== NULL
);
2558 IoReleaseVpbSpinLock( SavedIrql
);
2561 DbgFreePool( NewVpb
);
2564 // Walk through all of the Vcb's attached to the global data.
2565 Link
= UDFGlobalData
.VCBQueue
.Flink
;
2569 while (Link
!= &(UDFGlobalData
.VCBQueue
)) {
2571 Vcb
= CONTAINING_RECORD( Link
, VCB
, NextVCB
);
2572 // Move to the next link now since the current Vcb may be deleted.
2575 // Acquire Vcb resource
2576 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
2578 if (Vcb
->Vpb
->RealDevice
== DeviceToMarkBad
) {
2581 Buf
= (PPREVENT_MEDIA_REMOVAL_USER_IN
)MyAllocatePool__(NonPagedPool
, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN
)*2);
2583 KdPrint(("UDFInvalidateVolumes: STATUS_INSUFFICIENT_RESOURCES (2)\n"));
2584 UDFReleaseResource(&(Vcb
->VCBResource
));
2585 MyFreePool__(NewVpb
);
2586 Irp
->IoStatus
.Status
= STATUS_INSUFFICIENT_RESOURCES
;
2587 return STATUS_INSUFFICIENT_RESOURCES
;
2591 #ifdef UDF_DELAYED_CLOSE
2592 KdPrint((" UDFInvalidateVolumes: set UDF_VCB_FLAGS_NO_DELAYED_CLOSE\n"));
2593 Vcb
->VCBFlags
|= UDF_VCB_FLAGS_NO_DELAYED_CLOSE
;
2594 UDFReleaseResource(&(Vcb
->VCBResource
));
2595 #endif //UDF_DELAYED_CLOSE
2597 if(Vcb
->RootDirFCB
&& Vcb
->RootDirFCB
->FileInfo
) {
2598 KdPrint((" UDFInvalidateVolumes: UDFCloseAllSystemDelayedInDir\n"));
2599 RC
= UDFCloseAllSystemDelayedInDir(Vcb
, Vcb
->RootDirFCB
->FileInfo
);
2600 ASSERT(OS_SUCCESS(RC
));
2602 #ifdef UDF_DELAYED_CLOSE
2603 KdPrint((" UDFInvalidateVolumes: UDFCloseAllDelayed\n"));
2604 UDFCloseAllDelayed(Vcb
);
2605 //ASSERT(OS_SUCCESS(RC));
2606 #endif //UDF_DELAYED_CLOSE
2608 UDFAcquireResourceExclusive(&(Vcb
->VCBResource
), TRUE
);
2610 UDFDoDismountSequence(Vcb
, Buf
, FALSE
);
2611 UDFReleaseResource(&(Vcb
->VCBResource
));
2613 UDFStopEjectWaiter(Vcb
);
2614 KdPrint(("UDFInvalidateVolumes: Vcb %x dismounted\n", Vcb
));
2617 KdPrint(("UDFInvalidateVolumes: skip Vcb %x\n", Vcb
));
2618 UDFReleaseResource(&(Vcb
->VCBResource
));
2622 // Once we have processed all the mounted logical volumes, we can release
2623 // all acquired global resources and leave (in peace :-)
2624 UDFReleaseResource( &(UDFGlobalData
.GlobalDataResource
) );
2626 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
2629 KdPrint(("UDFInvalidateVolumes: free buffer\n"));
2633 // drop volume completly
2634 KdPrint(("UDFInvalidateVolumes: drop volume completly\n"));
2635 UDFAcquireResourceExclusive(&(UDFGlobalData
.GlobalDataResource
), TRUE
);
2636 UDFScanForDismountedVcb(IrpContext
);
2637 UDFReleaseResource( &(UDFGlobalData
.GlobalDataResource
) );
2639 KdPrint(("UDFInvalidateVolumes: done\n"));
2640 return STATUS_SUCCESS
;
2642 } // end UDFInvalidateVolumes()