2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
10 /* INCLUDES *****************************************************************/
14 /* GLOBALS ***************************************************************/
16 extern PEXT2_GLOBAL Ext2Global
;
18 /* DEFINITIONS *************************************************************/
21 #pragma alloc_text(PAGE, Ext2IsHandleCountZero)
22 #pragma alloc_text(PAGE, Ext2LockVcb)
23 #pragma alloc_text(PAGE, Ext2LockVolume)
24 #pragma alloc_text(PAGE, Ext2UnlockVcb)
25 #pragma alloc_text(PAGE, Ext2UnlockVolume)
26 #pragma alloc_text(PAGE, Ext2AllowExtendedDasdIo)
27 #pragma alloc_text(PAGE, Ext2GetRetrievalPointerBase)
28 #pragma alloc_text(PAGE, Ext2QueryExtentMappings)
29 #pragma alloc_text(PAGE, Ext2QueryRetrievalPointers)
30 #pragma alloc_text(PAGE, Ext2GetRetrievalPointers)
31 #pragma alloc_text(PAGE, Ext2UserFsRequest)
32 #pragma alloc_text(PAGE, Ext2IsMediaWriteProtected)
33 #pragma alloc_text(PAGE, Ext2MountVolume)
34 #pragma alloc_text(PAGE, Ext2PurgeVolume)
35 #pragma alloc_text(PAGE, Ext2PurgeFile)
36 #pragma alloc_text(PAGE, Ext2DismountVolume)
37 #pragma alloc_text(PAGE, Ext2IsVolumeMounted)
38 #pragma alloc_text(PAGE, Ext2VerifyVolume)
39 #pragma alloc_text(PAGE, Ext2FileSystemControl)
50 IoAcquireVpbSpinLock(&OldIrql
);
52 IoReleaseVpbSpinLock(OldIrql
);
62 IoAcquireVpbSpinLock(&OldIrql
);
64 IoReleaseVpbSpinLock(OldIrql
);
68 Ext2IsHandleCountZero(IN PEXT2_VCB Vcb
)
73 for ( List
= Vcb
->FcbList
.Flink
;
74 List
!= &Vcb
->FcbList
;
75 List
= List
->Flink
) {
77 Fcb
= CONTAINING_RECORD(List
, EXT2_FCB
, Next
);
79 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
80 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
82 DEBUG(DL_INF
, ( "Ext2IsHandleCountZero: Inode:%xh File:%S OpenHandleCount=%xh\n",
83 Fcb
->Inode
->i_ino
, Fcb
->Mcb
->ShortName
.Buffer
, Fcb
->OpenHandleCount
));
85 if (Fcb
->OpenHandleCount
) {
94 Ext2LockVcb (IN PEXT2_VCB Vcb
,
95 IN PFILE_OBJECT FileObject
)
97 NTSTATUS Status
= STATUS_SUCCESS
;
101 if (FlagOn(Vcb
->Flags
, VCB_VOLUME_LOCKED
)) {
102 DEBUG(DL_INF
, ( "Ext2LockVolume: Volume is already locked.\n"));
103 Status
= STATUS_ACCESS_DENIED
;
107 if (Vcb
->OpenHandleCount
> (ULONG
)(FileObject
? 1 : 0)) {
108 DEBUG(DL_INF
, ( "Ext2LockVcb: There are still opened files.\n"));
110 Status
= STATUS_ACCESS_DENIED
;
114 if (!Ext2IsHandleCountZero(Vcb
)) {
115 DEBUG(DL_INF
, ( "Ext2LockVcb: Thare are still opened files.\n"));
117 Status
= STATUS_ACCESS_DENIED
;
121 SetLongFlag(Vcb
->Flags
, VCB_VOLUME_LOCKED
);
122 Ext2SetVpbFlag(Vcb
->Vpb
, VPB_LOCKED
);
123 Vcb
->LockFile
= FileObject
;
125 DEBUG(DL_INF
, ( "Ext2LockVcb: Volume locked.\n"));
136 Ext2LockVolume (IN PEXT2_IRP_CONTEXT IrpContext
)
138 PIO_STACK_LOCATION IrpSp
;
139 PDEVICE_OBJECT DeviceObject
;
142 BOOLEAN VcbResourceAcquired
= FALSE
;
146 ASSERT(IrpContext
!= NULL
);
148 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
149 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
151 DeviceObject
= IrpContext
->DeviceObject
;
153 Status
= STATUS_UNSUCCESSFUL
;
156 // This request is not allowed on the main device object
158 if (IsExt2FsDevice(DeviceObject
)) {
159 Status
= STATUS_INVALID_PARAMETER
;
163 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
167 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
168 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
170 ASSERT(IsMounted(Vcb
));
172 IrpSp
= IoGetCurrentIrpStackLocation(IrpContext
->Irp
);
174 #if (_WIN32_WINNT >= 0x0500)
175 CcWaitForCurrentLazyWriterActivity();
177 ExAcquireResourceExclusiveLite(
181 VcbResourceAcquired
= TRUE
;
183 /* flush dirty data before locking the volume */
184 if (!IsVcbReadOnly(Vcb
)) {
185 Ext2FlushFiles(IrpContext
, Vcb
, FALSE
);
186 Ext2FlushVolume(IrpContext
, Vcb
, FALSE
);
189 Status
= Ext2LockVcb(Vcb
, IrpSp
->FileObject
);
193 if (VcbResourceAcquired
) {
194 ExReleaseResourceLite(&Vcb
->MainResource
);
197 if (!IrpContext
->ExceptionInProgress
) {
198 Ext2CompleteIrpContext(IrpContext
, Status
);
206 Ext2UnlockVcb ( IN PEXT2_VCB Vcb
,
207 IN PFILE_OBJECT FileObject
)
213 if (FileObject
&& FileObject
->FsContext
!= Vcb
) {
214 Status
= STATUS_NOT_LOCKED
;
218 if (!FlagOn(Vcb
->Flags
, VCB_VOLUME_LOCKED
)) {
219 DEBUG(DL_ERR
, ( ": Ext2UnlockVcb: Volume is not locked.\n"));
220 Status
= STATUS_NOT_LOCKED
;
224 if (Vcb
->LockFile
== FileObject
) {
225 ClearFlag(Vcb
->Flags
, VCB_VOLUME_LOCKED
);
226 Ext2ClearVpbFlag(Vcb
->Vpb
, VPB_LOCKED
);
227 DEBUG(DL_INF
, ( "Ext2UnlockVcb: Volume unlocked.\n"));
228 Status
= STATUS_SUCCESS
;
230 Status
= STATUS_NOT_LOCKED
;
242 IN PEXT2_IRP_CONTEXT IrpContext
245 PIO_STACK_LOCATION IrpSp
;
246 PDEVICE_OBJECT DeviceObject
;
249 BOOLEAN VcbResourceAcquired
= FALSE
;
253 ASSERT(IrpContext
!= NULL
);
254 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
255 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
257 DeviceObject
= IrpContext
->DeviceObject
;
258 IrpSp
= IoGetCurrentIrpStackLocation(IrpContext
->Irp
);
261 // This request is not allowed on the main device object
263 if (IsExt2FsDevice(DeviceObject
)) {
264 Status
= STATUS_INVALID_PARAMETER
;
268 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
270 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
271 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
273 ExAcquireResourceExclusiveLite(
276 VcbResourceAcquired
= TRUE
;
278 Status
= Ext2UnlockVcb(Vcb
, IrpSp
->FileObject
);
282 if (VcbResourceAcquired
) {
283 ExReleaseResourceLite(&Vcb
->MainResource
);
286 if (!IrpContext
->ExceptionInProgress
) {
287 Ext2CompleteIrpContext(IrpContext
, Status
);
296 Ext2InvalidateVolumes ( IN PEXT2_IRP_CONTEXT IrpContext
)
300 PIO_STACK_LOCATION IrpSp
;
306 PLIST_ENTRY ListEntry
;
308 ULONG InputLength
= 0;
309 PFILE_OBJECT FileObject
;
310 PDEVICE_OBJECT DeviceObject
;
311 BOOLEAN GlobalResourceAcquired
= FALSE
;
313 LUID Privilege
= {SE_TCB_PRIVILEGE
, 0};
317 Irp
= IrpContext
->Irp
;
318 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
320 if (!IsExt2FsDevice(IrpSp
->DeviceObject
)) {
321 Status
= STATUS_INVALID_DEVICE_REQUEST
;
325 if (!SeSinglePrivilegeCheck(Privilege
, Irp
->RequestorMode
)) {
326 Status
= STATUS_PRIVILEGE_NOT_HELD
;
332 InputLength
= IrpSp
->Parameters
.FileSystemControl
.InputBufferLength
;
334 InputLength
= ((PEXTENDED_IO_STACK_LOCATION
)(IrpSp
))->
335 Parameters
.FileSystemControl
.InputBufferLength
;
339 if (IoIs32bitProcess(Irp
)) {
340 if (InputLength
!= sizeof(UINT32
)) {
341 Status
= STATUS_INVALID_PARAMETER
;
344 Handle
= (HANDLE
) LongToHandle( (*(PUINT32
)Irp
->AssociatedIrp
.SystemBuffer
) );
348 if (InputLength
!= sizeof(HANDLE
)) {
349 Status
= STATUS_INVALID_PARAMETER
;
352 Handle
= *(PHANDLE
)Irp
->AssociatedIrp
.SystemBuffer
;
355 Status
= ObReferenceObjectByHandle( Handle
,
359 (void **)&FileObject
,
362 if (!NT_SUCCESS(Status
)) {
365 DeviceObject
= FileObject
->DeviceObject
;
366 ObDereferenceObject(FileObject
);
369 ExAcquireResourceExclusiveLite(&Ext2Global
->Resource
, TRUE
);
370 GlobalResourceAcquired
= TRUE
;
372 ListEntry
= Ext2Global
->VcbList
.Flink
;
373 while (ListEntry
!= &Ext2Global
->VcbList
) {
375 PEXT2_VCB Vcb
= CONTAINING_RECORD(ListEntry
, EXT2_VCB
, Next
);
376 ListEntry
= ListEntry
->Flink
;
378 DEBUG(DL_DBG
, ( "Ext2InvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh "
379 "Blink = %p &Vcb->Next = %p\n",
380 Vcb
, Vcb
->Vpb
, ListEntry
->Blink
, &Vcb
->Next
));
382 if (Vcb
->Vpb
&& (Vcb
->Vpb
->RealDevice
== DeviceObject
)) {
384 DEBUG(DL_DBG
, ( "Ext2InvalidateVolumes: Got Vcb=%xh Vcb->Vpb=%xh "
385 "Blink = %p &Vcb->Next = %p\n",
386 Vcb
, Vcb
->Vpb
, ListEntry
->Blink
, &Vcb
->Next
));
387 /* dismount the volume */
388 Ext2CheckDismount(IrpContext
, Vcb
, FALSE
);
394 if (GlobalResourceAcquired
) {
395 ExReleaseResourceLite(&Ext2Global
->Resource
);
398 if (!IrpContext
->ExceptionInProgress
) {
399 Ext2CompleteIrpContext(IrpContext
, Status
);
407 Ext2AllowExtendedDasdIo(IN PEXT2_IRP_CONTEXT IrpContext
)
409 PIO_STACK_LOCATION IrpSp
;
414 IrpSp
= IoGetCurrentIrpStackLocation(IrpContext
->Irp
);
416 Vcb
= (PEXT2_VCB
) IrpSp
->FileObject
->FsContext
;
417 Ccb
= (PEXT2_CCB
) IrpSp
->FileObject
->FsContext2
;
421 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
422 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
424 ASSERT(IsMounted(Vcb
));
427 SetLongFlag(Ccb
->Flags
, CCB_ALLOW_EXTENDED_DASD_IO
);
428 status
= STATUS_SUCCESS
;
430 status
= STATUS_INVALID_PARAMETER
;
433 Ext2CompleteIrpContext(IrpContext
, status
);
440 * oplock requests handler routine
443 * IrpContext: the ext2 irp context
446 * NTSTATUS: The return status for the operation
452 IN PEXT2_IRP_CONTEXT IrpContext
458 PDEVICE_OBJECT DeviceObject
;
459 PFILE_OBJECT FileObject
;
462 PIO_STACK_LOCATION IrpSp
;
463 PEXTENDED_IO_STACK_LOCATION EIrpSp
;
465 PEXT2_VCB Vcb
= NULL
;
466 PEXT2_FCB Fcb
= NULL
;
467 PEXT2_CCB Ccb
= NULL
;
469 ULONG OplockCount
= 0;
471 BOOLEAN VcbResourceAcquired
= FALSE
;
472 BOOLEAN FcbResourceAcquired
= FALSE
;
478 Irp
= IrpContext
->Irp
;
481 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
483 EIrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IrpSp
;
485 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
486 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
488 DeviceObject
= IrpContext
->DeviceObject
;
491 // This request is not allowed on the main device object
493 if (IsExt2FsDevice(DeviceObject
)) {
494 Status
= STATUS_INVALID_DEVICE_REQUEST
;
498 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
502 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
503 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
505 ASSERT(IsMounted(Vcb
));
507 FileObject
= IrpContext
->FileObject
;
509 Fcb
= (PEXT2_FCB
) FileObject
->FsContext
;
512 // This request is not allowed on volumes
515 if (Fcb
== NULL
|| Fcb
->Identifier
.Type
== EXT2VCB
) {
516 Status
= STATUS_INVALID_PARAMETER
;
520 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
521 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
523 if (IsFlagOn(Fcb
->Mcb
->Flags
, MCB_FILE_DELETED
)) {
524 Status
= STATUS_FILE_DELETED
;
528 Ccb
= (PEXT2_CCB
) FileObject
->FsContext2
;
530 Status
= STATUS_INVALID_PARAMETER
;
535 ASSERT((Ccb
->Identifier
.Type
== EXT2CCB
) &&
536 (Ccb
->Identifier
.Size
== sizeof(EXT2_CCB
)));
538 FsCtrlCode
= EIrpSp
->Parameters
.FileSystemControl
.FsControlCode
;
540 switch (FsCtrlCode
) {
542 case FSCTL_REQUEST_OPLOCK_LEVEL_1
:
543 case FSCTL_REQUEST_OPLOCK_LEVEL_2
:
544 case FSCTL_REQUEST_BATCH_OPLOCK
:
546 VcbResourceAcquired
=
547 ExAcquireResourceSharedLite(
549 IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
) );
551 ClearFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
);
553 FcbResourceAcquired
=
554 ExAcquireResourceExclusiveLite (
556 IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
));
558 if (FsCtrlCode
== FSCTL_REQUEST_OPLOCK_LEVEL_2
) {
559 OplockCount
= (ULONG
) FsRtlAreThereCurrentFileLocks(&Fcb
->FileLockAnchor
);
561 OplockCount
= Fcb
->OpenHandleCount
;
566 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
:
567 case FSCTL_OPBATCH_ACK_CLOSE_PENDING
:
568 case FSCTL_OPLOCK_BREAK_NOTIFY
:
569 case FSCTL_OPLOCK_BREAK_ACK_NO_2
:
571 FcbResourceAcquired
=
572 ExAcquireResourceSharedLite (
574 IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
));
580 Ext2BugCheck(EXT2_BUGCHK_FSCTL
, FsCtrlCode
, 0, 0);
585 // Call the FsRtl routine to grant/acknowledge oplock.
588 Status
= FsRtlOplockFsctrl( &Fcb
->Oplock
,
593 // Set the flag indicating if Fast I/O is possible
596 Fcb
->Header
.IsFastIoPossible
= Ext2IsFastIoPossible(Fcb
);
597 IrpContext
->Irp
= NULL
;
601 if (FcbResourceAcquired
) {
602 ExReleaseResourceLite(&Fcb
->MainResource
);
605 if (VcbResourceAcquired
) {
606 ExReleaseResourceLite(&Vcb
->MainResource
);
609 if (!_SEH2_AbnormalTermination()) {
610 Ext2CompleteIrpContext(IrpContext
, Status
);
619 IN PEXT2_IRP_CONTEXT IrpContext
622 NTSTATUS status
= STATUS_SUCCESS
;
624 PEXTENDED_IO_STACK_LOCATION IrpSp
;
629 Irp
= IrpContext
->Irp
;
630 IrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
633 // Get a pointer to the output buffer. Look at the system buffer field in th
634 // irp first. Then the Irp Mdl.
637 if (Irp
->AssociatedIrp
.SystemBuffer
!= NULL
) {
639 VolumeState
= Irp
->AssociatedIrp
.SystemBuffer
;
641 } else if (Irp
->MdlAddress
!= NULL
) {
643 VolumeState
= MmGetSystemAddressForMdl( Irp
->MdlAddress
);
647 status
= STATUS_INVALID_USER_BUFFER
;
651 if (IrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
< sizeof(ULONG
)) {
652 status
= STATUS_INVALID_PARAMETER
;
660 if (!IrpContext
->ExceptionInProgress
) {
661 Ext2CompleteIrpContext(IrpContext
, status
);
670 Ext2QueryExtentMappings(
671 IN PEXT2_IRP_CONTEXT IrpContext
,
674 IN PLARGE_INTEGER RequestVbn
,
675 OUT PLARGE_INTEGER
* pMappedRuns
678 PLARGE_INTEGER MappedRuns
= NULL
;
679 PLARGE_INTEGER PartialRuns
= NULL
;
681 PEXT2_EXTENT Chain
= NULL
;
682 PEXT2_EXTENT Extent
= NULL
;
688 NTSTATUS Status
= STATUS_SUCCESS
;
692 /* now building all the request extents */
693 while (Vbn
< RequestVbn
->QuadPart
) {
695 Length
= 0x80000000; /* 2g bytes */
696 if (RequestVbn
->QuadPart
< Vbn
+ Length
) {
697 Length
= (ULONG
)(RequestVbn
->QuadPart
- Vbn
);
700 /* build extents for sub-range */
702 Status
= Ext2BuildExtents(
711 if (!NT_SUCCESS(Status
)) {
716 Ext2JointExtents(Chain
, Extent
);
721 /* allocate extent array */
722 PartialRuns
= Ext2AllocatePool(
724 (Ext2CountExtents(Chain
) + 2) *
725 (2 * sizeof(LARGE_INTEGER
)),
728 if (PartialRuns
== NULL
) {
729 Status
= STATUS_INSUFFICIENT_RESOURCES
;
732 RtlZeroMemory( PartialRuns
,
733 (Ext2CountExtents(Chain
) + 2) *
734 (2 * sizeof(LARGE_INTEGER
)));
737 RtlMoveMemory(PartialRuns
,
739 i
* 2 * sizeof(LARGE_INTEGER
));
740 Ext2FreePool(MappedRuns
, 'RE2E');
742 MappedRuns
= PartialRuns
;
744 /* walk all the Mcb runs in Extent */
745 for (; Extent
!= NULL
; Extent
= Extent
->Next
) {
746 MappedRuns
[i
*2 + 0].QuadPart
= Vbn
+ Extent
->Offset
;
747 MappedRuns
[i
*2 + 1].QuadPart
= Extent
->Lba
;
754 *pMappedRuns
= MappedRuns
;
758 if (!NT_SUCCESS(Status
) || Status
== STATUS_PENDING
) {
760 Ext2FreePool(MappedRuns
, 'RE2E');
766 Ext2DestroyExtentChain(Chain
);
774 Ext2QueryRetrievalPointers (
775 IN PEXT2_IRP_CONTEXT IrpContext
779 PIO_STACK_LOCATION IrpSp
;
780 PEXTENDED_IO_STACK_LOCATION EIrpSp
;
782 PDEVICE_OBJECT DeviceObject
;
783 PFILE_OBJECT FileObject
;
785 PEXT2_VCB Vcb
= NULL
;
786 PEXT2_FCB Fcb
= NULL
;
787 PEXT2_CCB Ccb
= NULL
;
789 PLARGE_INTEGER RequestVbn
;
790 PLARGE_INTEGER
* pMappedRuns
;
795 NTSTATUS Status
= STATUS_SUCCESS
;
797 BOOLEAN FcbResourceAcquired
= FALSE
;
802 Irp
= IrpContext
->Irp
;
805 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
806 EIrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IrpSp
;
809 InputSize
= EIrpSp
->Parameters
.FileSystemControl
.InputBufferLength
;
810 OutputSize
= EIrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
812 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
813 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
815 DeviceObject
= IrpContext
->DeviceObject
;
819 /* This request is not allowed on the main device object */
820 if (IsExt2FsDevice(DeviceObject
)) {
821 Status
= STATUS_INVALID_DEVICE_REQUEST
;
825 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
827 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
828 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
829 ASSERT(IsMounted(Vcb
));
831 FileObject
= IrpContext
->FileObject
;
832 Fcb
= (PEXT2_FCB
) FileObject
->FsContext
;
834 /* check Fcb is valid or not */
835 if (Fcb
== NULL
|| Fcb
->Identifier
.Type
== EXT2VCB
) {
836 Status
= STATUS_INVALID_PARAMETER
;
840 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
841 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
842 if (IsFlagOn(Fcb
->Mcb
->Flags
, MCB_FILE_DELETED
)) {
843 Status
= STATUS_FILE_DELETED
;
847 Ccb
= (PEXT2_CCB
) FileObject
->FsContext2
;
849 Status
= STATUS_INVALID_PARAMETER
;
853 ASSERT((Ccb
->Identifier
.Type
== EXT2CCB
) &&
854 (Ccb
->Identifier
.Size
== sizeof(EXT2_CCB
)));
856 /* Is requstor in kernel and Fcb a paging file ? */
857 if (Irp
->RequestorMode
!= KernelMode
||
858 !IsFlagOn(Fcb
->Flags
, FCB_PAGE_FILE
) ||
859 InputSize
!= sizeof(LARGE_INTEGER
) ||
860 OutputSize
!= sizeof(PVOID
)) {
861 Status
= STATUS_INVALID_PARAMETER
;
865 if (!ExAcquireResourceExclusiveLite (
866 &Fcb
->MainResource
, Ext2CanIWait())) {
867 Status
= STATUS_PENDING
;
870 FcbResourceAcquired
= TRUE
;
872 RequestVbn
= EIrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
;
873 pMappedRuns
= Irp
->UserBuffer
;
877 /* request size beyonds whole file size */
878 if (RequestVbn
->QuadPart
>= Fcb
->Header
.AllocationSize
.QuadPart
) {
879 Status
= STATUS_END_OF_FILE
;
883 Status
= Ext2QueryExtentMappings(
893 if (FcbResourceAcquired
) {
894 ExReleaseResourceLite(&Fcb
->MainResource
);
897 if (!_SEH2_AbnormalTermination()) {
898 if (Status
== STATUS_PENDING
|| Status
== STATUS_CANT_WAIT
) {
899 Status
= Ext2QueueRequest(IrpContext
);
901 Ext2CompleteIrpContext(IrpContext
, Status
);
911 Ext2GetRetrievalPointers (
912 IN PEXT2_IRP_CONTEXT IrpContext
916 PIO_STACK_LOCATION IrpSp
;
917 PEXTENDED_IO_STACK_LOCATION EIrpSp
;
919 PDEVICE_OBJECT DeviceObject
;
920 PFILE_OBJECT FileObject
;
922 PEXT2_VCB Vcb
= NULL
;
923 PEXT2_FCB Fcb
= NULL
;
924 PEXT2_CCB Ccb
= NULL
;
926 PSTARTING_VCN_INPUT_BUFFER SVIB
;
927 PRETRIEVAL_POINTERS_BUFFER RPSB
;
929 PEXT2_EXTENT Chain
= NULL
;
930 PEXT2_EXTENT Extent
= NULL
;
940 NTSTATUS Status
= STATUS_SUCCESS
;
942 BOOLEAN FcbResourceAcquired
= FALSE
;
947 Irp
= IrpContext
->Irp
;
950 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
951 EIrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IrpSp
;
954 InputSize
= EIrpSp
->Parameters
.FileSystemControl
.InputBufferLength
;
955 OutputSize
= EIrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
957 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
958 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
960 DeviceObject
= IrpContext
->DeviceObject
;
962 /* This request is not allowed on the main device object */
963 if (IsExt2FsDevice(DeviceObject
)) {
964 Status
= STATUS_INVALID_DEVICE_REQUEST
;
968 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
970 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
971 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
972 ASSERT(IsMounted(Vcb
));
974 FileObject
= IrpContext
->FileObject
;
975 Fcb
= (PEXT2_FCB
) FileObject
->FsContext
;
977 /* check Fcb is valid or not */
978 if (Fcb
== NULL
|| Fcb
->Identifier
.Type
== EXT2VCB
) {
979 Status
= STATUS_INVALID_PARAMETER
;
983 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
984 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
986 if (IsFlagOn(Fcb
->Mcb
->Flags
, MCB_FILE_DELETED
)) {
987 Status
= STATUS_FILE_DELETED
;
991 Ccb
= (PEXT2_CCB
) FileObject
->FsContext2
;
993 Status
= STATUS_INVALID_PARAMETER
;
997 ASSERT((Ccb
->Identifier
.Type
== EXT2CCB
) &&
998 (Ccb
->Identifier
.Size
== sizeof(EXT2_CCB
)));
1000 if (InputSize
< sizeof(STARTING_VCN_INPUT_BUFFER
) ||
1001 OutputSize
< sizeof(RETRIEVAL_POINTERS_BUFFER
) ) {
1002 Status
= STATUS_BUFFER_TOO_SMALL
;
1006 if (!ExAcquireResourceExclusiveLite (
1007 &Fcb
->MainResource
, Ext2CanIWait())) {
1008 Status
= STATUS_PENDING
;
1011 FcbResourceAcquired
= TRUE
;
1013 SVIB
= (PSTARTING_VCN_INPUT_BUFFER
)
1014 EIrpSp
->Parameters
.FileSystemControl
.Type3InputBuffer
;
1015 RPSB
= (PRETRIEVAL_POINTERS_BUFFER
) Ext2GetUserBuffer(Irp
);
1017 /* probe user buffer */
1020 if (Irp
->RequestorMode
!= KernelMode
) {
1021 ProbeForRead (SVIB
, InputSize
, sizeof(UCHAR
));
1022 ProbeForWrite(RPSB
, OutputSize
, sizeof(UCHAR
));
1024 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1025 Status
= STATUS_INVALID_USER_BUFFER
;
1028 if (!NT_SUCCESS(Status
)) {
1032 UsedSize
= FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER
, Extents
[0]);
1034 /* request size beyonds whole file size ? */
1035 DEBUG(DL_DBG
, ("Ext2GetRetrievalPointers: Startin from Vbn: %I64xh\n",
1036 SVIB
->StartingVcn
.QuadPart
));
1037 Vbn
= (SVIB
->StartingVcn
.QuadPart
<< BLOCK_BITS
);
1038 if (Vbn
>= Fcb
->Header
.AllocationSize
.QuadPart
) {
1039 Status
= STATUS_END_OF_FILE
;
1043 /* now building all the request extents */
1044 while (Vbn
< Fcb
->Header
.AllocationSize
.QuadPart
) {
1046 ASSERT(Chain
== NULL
);
1047 Length
= 0x80000000; /* 2g bytes */
1048 if (Fcb
->Header
.AllocationSize
.QuadPart
< Vbn
+ Length
) {
1049 Length
= (ULONG
)(Fcb
->Header
.AllocationSize
.QuadPart
- Vbn
);
1052 /* build extents for sub-range */
1053 Status
= Ext2BuildExtents(
1062 if (!NT_SUCCESS(Status
)) {
1067 /* fill user buffer of RETRIEVAL_POINTERS_BUFFER */
1071 DEBUG(DL_MAP
, ("Ext2GetRetrievalPointers: %wZ %d Vbn = %I64xh Lbn = %I64xh\n",
1072 &Fcb
->Mcb
->FullName
, i
,
1073 ((Vbn
+ Extent
->Offset
) >> BLOCK_BITS
),
1076 RPSB
->Extents
[i
].Lcn
.QuadPart
= (Extent
->Lba
>> BLOCK_BITS
);
1077 RPSB
->Extents
[i
].NextVcn
.QuadPart
= ((Vbn
+ Extent
->Offset
+ Extent
->Length
) >> BLOCK_BITS
);
1079 RPSB
->StartingVcn
.QuadPart
= ((Vbn
+ Extent
->Offset
) >> BLOCK_BITS
);
1081 ASSERT(RPSB
->Extents
[i
-1].NextVcn
.QuadPart
== ((Vbn
+ Extent
->Offset
) >> BLOCK_BITS
));
1083 if (UsedSize
+ sizeof(RETRIEVAL_POINTERS_BUFFER
) > OutputSize
) {
1084 Status
= STATUS_BUFFER_OVERFLOW
;
1087 UsedSize
+= sizeof(LARGE_INTEGER
) * 2;
1088 Irp
->IoStatus
.Information
= (ULONG_PTR
)UsedSize
;
1089 RPSB
->ExtentCount
= ++i
;
1090 Extent
= Extent
->Next
;
1094 Ext2DestroyExtentChain(Chain
);
1105 LARGE_INTEGER RequestVbn
= Fcb
->Header
.AllocationSize
;
1106 PLARGE_INTEGER MappedRuns
= NULL
;
1108 _s
= Ext2QueryExtentMappings(
1115 if (!NT_SUCCESS(_s
) || NULL
== MappedRuns
) {
1117 goto exit_to_get_rps
;
1120 while (MappedRuns
[_i
*2 + 0].QuadPart
!= 0 ||
1121 MappedRuns
[_i
*2 + 1].QuadPart
!= 0 ) {
1122 DEBUG(DL_MAP
, ("Ext2QueryExtentMappings: %wZ %d Vbn = %I64xh Lbn = %I64xh\n",
1123 &Fcb
->Mcb
->FullName
, _i
,
1124 MappedRuns
[_i
*2 + 0].QuadPart
,
1125 MappedRuns
[_i
*2 + 1].QuadPart
));
1132 Ext2FreePool(MappedRuns
, 'RE2E');
1139 if (FcbResourceAcquired
) {
1140 ExReleaseResourceLite(&Fcb
->MainResource
);
1144 Ext2DestroyExtentChain(Chain
);
1147 if (!_SEH2_AbnormalTermination()) {
1148 if (Status
== STATUS_PENDING
|| Status
== STATUS_CANT_WAIT
) {
1149 Status
= Ext2QueueRequest(IrpContext
);
1151 Ext2CompleteIrpContext(IrpContext
, Status
);
1160 Ext2GetRetrievalPointerBase (
1161 IN PEXT2_IRP_CONTEXT IrpContext
1165 PIO_STACK_LOCATION IrpSp
;
1166 PEXTENDED_IO_STACK_LOCATION EIrpSp
;
1168 PDEVICE_OBJECT DeviceObject
;
1169 PFILE_OBJECT FileObject
;
1171 PEXT2_VCB Vcb
= NULL
;
1172 PEXT2_FCB Fcb
= NULL
;
1173 PEXT2_CCB Ccb
= NULL
;
1175 PLARGE_INTEGER FileAreaOffset
;
1179 NTSTATUS Status
= STATUS_SUCCESS
;
1181 BOOLEAN FcbResourceAcquired
= FALSE
;
1186 Irp
= IrpContext
->Irp
;
1189 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1190 EIrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IrpSp
;
1193 OutputSize
= EIrpSp
->Parameters
.FileSystemControl
.OutputBufferLength
;
1195 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1196 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1198 DeviceObject
= IrpContext
->DeviceObject
;
1200 /* This request is not allowed on the main device object */
1201 if (IsExt2FsDevice(DeviceObject
)) {
1202 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1206 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
1207 ASSERT(Vcb
!= NULL
);
1208 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
1209 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
1210 ASSERT(IsMounted(Vcb
));
1212 FileObject
= IrpContext
->FileObject
;
1213 Fcb
= (PEXT2_FCB
) FileObject
->FsContext
;
1215 /* check Fcb is valid or not */
1216 if (Fcb
== NULL
|| Fcb
->Identifier
.Type
== EXT2VCB
) {
1217 Status
= STATUS_INVALID_PARAMETER
;
1221 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
1222 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
1224 if (IsFlagOn(Fcb
->Mcb
->Flags
, MCB_FILE_DELETED
)) {
1225 Status
= STATUS_FILE_DELETED
;
1229 Ccb
= (PEXT2_CCB
) FileObject
->FsContext2
;
1231 Status
= STATUS_INVALID_PARAMETER
;
1235 ASSERT((Ccb
->Identifier
.Type
== EXT2CCB
) &&
1236 (Ccb
->Identifier
.Size
== sizeof(EXT2_CCB
)));
1238 if (OutputSize
< sizeof(LARGE_INTEGER
)) {
1239 Status
= STATUS_BUFFER_TOO_SMALL
;
1243 if (!ExAcquireResourceExclusiveLite (
1244 &Fcb
->MainResource
, Ext2CanIWait())) {
1245 Status
= STATUS_PENDING
;
1248 FcbResourceAcquired
= TRUE
;
1250 FileAreaOffset
= (PLARGE_INTEGER
) Ext2GetUserBuffer(Irp
);
1252 /* probe user buffer */
1255 if (Irp
->RequestorMode
!= KernelMode
) {
1256 ProbeForWrite(FileAreaOffset
, OutputSize
, sizeof(UCHAR
));
1259 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
1261 Status
= STATUS_INVALID_USER_BUFFER
;
1264 if (!NT_SUCCESS(Status
)) {
1268 DEBUG(DL_DBG
, ("Ext2GetRetrievalPointerBase: FileAreaOffset is 0.\n"));
1270 FileAreaOffset
->QuadPart
= 0; // sector offset to the first allocatable unit on the filesystem
1272 Irp
->IoStatus
.Information
= sizeof(LARGE_INTEGER
);
1276 if (FcbResourceAcquired
) {
1277 ExReleaseResourceLite(&Fcb
->MainResource
);
1280 if (!_SEH2_AbnormalTermination()) {
1281 if (Status
== STATUS_PENDING
|| Status
== STATUS_CANT_WAIT
) {
1282 Status
= Ext2QueueRequest(IrpContext
);
1284 Ext2CompleteIrpContext(IrpContext
, Status
);
1294 Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext
)
1297 PIO_STACK_LOCATION IoStackLocation
;
1298 ULONG FsControlCode
;
1303 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1304 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1306 Irp
= IrpContext
->Irp
;
1308 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1312 IoStackLocation
->Parameters
.FileSystemControl
.FsControlCode
;
1314 FsControlCode
= ((PEXTENDED_IO_STACK_LOCATION
)
1315 IoStackLocation
)->Parameters
.FileSystemControl
.FsControlCode
;
1318 switch (FsControlCode
) {
1320 case FSCTL_LOCK_VOLUME
:
1321 Status
= Ext2LockVolume(IrpContext
);
1324 case FSCTL_UNLOCK_VOLUME
:
1325 Status
= Ext2UnlockVolume(IrpContext
);
1328 case FSCTL_DISMOUNT_VOLUME
:
1329 Status
= Ext2DismountVolume(IrpContext
);
1332 case FSCTL_IS_VOLUME_MOUNTED
:
1333 Status
= Ext2IsVolumeMounted(IrpContext
);
1336 case FSCTL_INVALIDATE_VOLUMES
:
1337 Status
= Ext2InvalidateVolumes(IrpContext
);
1340 #if (_WIN32_WINNT >= 0x0500)
1341 case FSCTL_ALLOW_EXTENDED_DASD_IO
:
1342 Status
= Ext2AllowExtendedDasdIo(IrpContext
);
1344 #endif //(_WIN32_WINNT >= 0x0500)
1346 case FSCTL_REQUEST_OPLOCK_LEVEL_1
:
1347 case FSCTL_REQUEST_OPLOCK_LEVEL_2
:
1348 case FSCTL_REQUEST_BATCH_OPLOCK
:
1349 case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
:
1350 case FSCTL_OPBATCH_ACK_CLOSE_PENDING
:
1351 case FSCTL_OPLOCK_BREAK_NOTIFY
:
1352 case FSCTL_OPLOCK_BREAK_ACK_NO_2
:
1354 Status
= Ext2OplockRequest(IrpContext
);
1357 case FSCTL_IS_VOLUME_DIRTY
:
1358 Status
= Ext2IsVolumeDirty(IrpContext
);
1361 case FSCTL_QUERY_RETRIEVAL_POINTERS
:
1362 Status
= Ext2QueryRetrievalPointers(IrpContext
);
1365 case FSCTL_GET_RETRIEVAL_POINTERS
:
1366 Status
= Ext2GetRetrievalPointers(IrpContext
);
1369 case FSCTL_GET_RETRIEVAL_POINTER_BASE
:
1370 Status
= Ext2GetRetrievalPointerBase(IrpContext
);
1375 DEBUG(DL_INF
, ( "Ext2UserFsRequest: Invalid User Request: %xh.\n", FsControlCode
));
1376 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1378 Ext2CompleteIrpContext(IrpContext
, Status
);
1385 Ext2IsMediaWriteProtected (
1386 IN PEXT2_IRP_CONTEXT IrpContext
,
1387 IN PDEVICE_OBJECT TargetDevice
1393 IO_STATUS_BLOCK IoStatus
;
1395 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1397 Irp
= IoBuildDeviceIoControlRequest( IOCTL_DISK_IS_WRITABLE
,
1411 SetFlag(IoGetNextIrpStackLocation(Irp
)->Flags
, SL_OVERRIDE_VERIFY_VOLUME
);
1413 Status
= IoCallDriver(TargetDevice
, Irp
);
1415 if (Status
== STATUS_PENDING
) {
1417 (VOID
) KeWaitForSingleObject( &Event
,
1421 (PLARGE_INTEGER
)NULL
);
1423 Status
= IoStatus
.Status
;
1426 return (BOOLEAN
)(Status
== STATUS_MEDIA_WRITE_PROTECTED
);
1430 Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext
)
1432 PDEVICE_OBJECT MainDeviceObject
;
1433 BOOLEAN GlobalDataResourceAcquired
= FALSE
;
1435 PIO_STACK_LOCATION IoStackLocation
;
1436 PDEVICE_OBJECT TargetDeviceObject
;
1437 NTSTATUS Status
= STATUS_UNRECOGNIZED_VOLUME
;
1438 PDEVICE_OBJECT VolumeDeviceObject
= NULL
;
1439 PEXT2_VCB Vcb
= NULL
, OldVcb
= NULL
;
1440 PVPB OldVpb
= NULL
, Vpb
= NULL
;
1441 PEXT2_SUPER_BLOCK Ext2Sb
= NULL
;
1443 DISK_GEOMETRY DiskGeometry
;
1447 ASSERT(IrpContext
!= NULL
);
1448 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1449 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1451 MainDeviceObject
= IrpContext
->DeviceObject
;
1454 // Make sure we can wait.
1457 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_WAIT
);
1460 // This request is only allowed on the main device object
1462 if (!IsExt2FsDevice(MainDeviceObject
)) {
1463 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1467 if (IsFlagOn(Ext2Global
->Flags
, EXT2_UNLOAD_PENDING
)) {
1468 Status
= STATUS_UNRECOGNIZED_VOLUME
;
1473 if (IrpContext
->RealDevice
->Size
>= sizeof(ULONG
) + sizeof(DEVICE_OBJECT
) &&
1474 *((PULONG
)IrpContext
->RealDevice
->DeviceExtension
) == 'DSSA') {
1476 Status
= STATUS_UNRECOGNIZED_VOLUME
;
1481 Irp
= IrpContext
->Irp
;
1482 IoStackLocation
= IoGetCurrentIrpStackLocation(Irp
);
1483 TargetDeviceObject
=
1484 IoStackLocation
->Parameters
.MountVolume
.DeviceObject
;
1486 dwBytes
= sizeof(DISK_GEOMETRY
);
1487 Status
= Ext2DiskIoControl(
1489 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
1495 if (!NT_SUCCESS(Status
)) {
1499 Status
= IoCreateDevice(
1500 MainDeviceObject
->DriverObject
,
1503 FILE_DEVICE_DISK_FILE_SYSTEM
,
1506 &VolumeDeviceObject
);
1508 if (!NT_SUCCESS(Status
)) {
1511 INC_MEM_COUNT(PS_VCB
, VolumeDeviceObject
, sizeof(EXT2_VCB
));
1513 VolumeDeviceObject
->StackSize
= (CCHAR
)(TargetDeviceObject
->StackSize
+ 1);
1514 ClearFlag(VolumeDeviceObject
->Flags
, DO_DEVICE_INITIALIZING
);
1516 if (TargetDeviceObject
->AlignmentRequirement
>
1517 VolumeDeviceObject
->AlignmentRequirement
) {
1519 VolumeDeviceObject
->AlignmentRequirement
=
1520 TargetDeviceObject
->AlignmentRequirement
;
1523 (IoStackLocation
->Parameters
.MountVolume
.Vpb
)->DeviceObject
=
1525 Vpb
= IoStackLocation
->Parameters
.MountVolume
.Vpb
;
1527 Vcb
= (PEXT2_VCB
) VolumeDeviceObject
->DeviceExtension
;
1529 RtlZeroMemory(Vcb
, sizeof(EXT2_VCB
));
1530 Vcb
->Identifier
.Type
= EXT2VCB
;
1531 Vcb
->Identifier
.Size
= sizeof(EXT2_VCB
);
1532 Vcb
->TargetDeviceObject
= TargetDeviceObject
;
1533 Vcb
->DiskGeometry
= DiskGeometry
;
1534 InitializeListHead(&Vcb
->Next
);
1536 Status
= Ext2LoadSuper(Vcb
, FALSE
, &Ext2Sb
);
1537 if (!NT_SUCCESS(Status
)) {
1539 Status
= STATUS_UNRECOGNIZED_VOLUME
;
1542 ASSERT (NULL
!= Ext2Sb
);
1544 /* check Linux Ext2/Ext3 volume magic */
1545 if (Ext2Sb
->s_magic
== EXT2_SUPER_MAGIC
) {
1546 DEBUG(DL_INF
, ( "Volume of ext2 file system is found.\n"));
1548 Status
= STATUS_UNRECOGNIZED_VOLUME
;
1553 DEBUG(DL_DBG
, ("Ext2MountVolume: DevObject=%p Vcb=%p\n", VolumeDeviceObject
, Vcb
));
1555 /* initialize Vcb structure */
1556 Status
= Ext2InitializeVcb( IrpContext
, Vcb
, Ext2Sb
,
1558 VolumeDeviceObject
, Vpb
);
1560 if (NT_SUCCESS(Status
)) {
1564 ExAcquireResourceExclusiveLite(&(Ext2Global
->Resource
), TRUE
);
1565 GlobalDataResourceAcquired
= TRUE
;
1567 for (List
= Ext2Global
->VcbList
.Flink
;
1568 List
!= &Ext2Global
->VcbList
;
1569 List
= List
->Flink
) {
1571 OldVcb
= CONTAINING_RECORD(List
, EXT2_VCB
, Next
);
1572 OldVpb
= OldVcb
->Vpb
;
1574 /* in case we are already in the queue, should not happen */
1575 if (OldVpb
== Vpb
) {
1579 if ( (OldVpb
->SerialNumber
== Vpb
->SerialNumber
) &&
1580 (!IsMounted(OldVcb
)) && (IsFlagOn(OldVcb
->Flags
, VCB_NEW_VPB
)) &&
1581 (OldVpb
->RealDevice
== TargetDeviceObject
) &&
1582 (OldVpb
->VolumeLabelLength
== Vpb
->VolumeLabelLength
) &&
1583 (RtlEqualMemory(&OldVpb
->VolumeLabel
[0],
1584 &Vpb
->VolumeLabel
[0],
1585 Vpb
->VolumeLabelLength
)) &&
1586 (RtlEqualMemory(&OldVcb
->SuperBlock
->s_uuid
[0],
1587 &Vcb
->SuperBlock
->s_uuid
[0], 16)) ) {
1588 ClearFlag(OldVcb
->Flags
, VCB_MOUNTED
);
1592 SetLongFlag(Vcb
->Flags
, VCB_MOUNTED
);
1593 SetFlag(Vcb
->Vpb
->Flags
, VPB_MOUNTED
);
1597 ObDereferenceObject(TargetDeviceObject
);
1606 if (GlobalDataResourceAcquired
) {
1607 ExReleaseResourceLite(&Ext2Global
->Resource
);
1610 if (!NT_SUCCESS(Status
)) {
1612 if (!NT_SUCCESS(Status
)) {
1613 if ( Vpb
!= NULL
) {
1614 Vpb
->DeviceObject
= NULL
;
1619 Ext2DestroyVcb(Vcb
);
1622 Ext2FreePool(Ext2Sb
, EXT2_SB_MAGIC
);
1624 if (VolumeDeviceObject
) {
1625 IoDeleteDevice(VolumeDeviceObject
);
1626 DEC_MEM_COUNT(PS_VCB
, VolumeDeviceObject
, sizeof(EXT2_VCB
));
1631 if (!IrpContext
->ExceptionInProgress
) {
1632 Ext2CompleteIrpContext(IrpContext
, Status
);
1640 Ext2VerifyVcb (IN PEXT2_IRP_CONTEXT IrpContext
,
1643 NTSTATUS Status
= STATUS_SUCCESS
;
1645 BOOLEAN bVerify
= FALSE
;
1646 ULONG ChangeCount
= 0;
1650 PEXTENDED_IO_STACK_LOCATION IrpSp
;
1654 ASSERT(IrpContext
!= NULL
);
1656 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1657 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1659 Irp
= IrpContext
->Irp
;
1660 IrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
1662 bVerify
= IsFlagOn(Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
);
1664 if ( (IsFlagOn(Vcb
->Flags
, VCB_REMOVABLE_MEDIA
) ||
1665 IsFlagOn(Vcb
->Flags
, VCB_FLOPPY_DISK
)) && !bVerify
) {
1667 dwBytes
= sizeof(ULONG
);
1668 Status
= Ext2DiskIoControl(
1669 Vcb
->TargetDeviceObject
,
1670 IOCTL_DISK_CHECK_VERIFY
,
1676 if ( STATUS_VERIFY_REQUIRED
== Status
||
1677 STATUS_DEVICE_NOT_READY
== Status
||
1678 STATUS_NO_MEDIA_IN_DEVICE
== Status
||
1679 (NT_SUCCESS(Status
) &&
1680 (ChangeCount
!= Vcb
->ChangeCount
))) {
1684 IoAcquireVpbSpinLock(&Irql
);
1685 if (Vcb
->Vpb
== Vcb
->Vpb
->RealDevice
->Vpb
) {
1686 SetFlag(Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
);
1688 IoReleaseVpbSpinLock(Irql
);
1692 if (!NT_SUCCESS(Status
)) {
1693 Ext2NormalizeAndRaiseStatus(IrpContext
, Status
);
1698 if ( IsFlagOn(Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
)) {
1699 IoSetHardErrorOrVerifyDevice( Irp
, Vcb
->Vpb
->RealDevice
);
1700 Ext2NormalizeAndRaiseStatus ( IrpContext
,
1701 STATUS_VERIFY_REQUIRED
);
1704 if (IsMounted(Vcb
)) {
1706 if ( (IrpContext
->MajorFunction
== IRP_MJ_WRITE
) ||
1707 (IrpContext
->MajorFunction
== IRP_MJ_SET_INFORMATION
) ||
1708 (IrpContext
->MajorFunction
== IRP_MJ_SET_EA
) ||
1709 (IrpContext
->MajorFunction
== IRP_MJ_FLUSH_BUFFERS
) ||
1710 (IrpContext
->MajorFunction
== IRP_MJ_SET_VOLUME_INFORMATION
) ||
1711 (IrpContext
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
&&
1712 IrpContext
->MinorFunction
== IRP_MN_USER_FS_REQUEST
&&
1713 IrpSp
->Parameters
.FileSystemControl
.FsControlCode
==
1714 FSCTL_MARK_VOLUME_DIRTY
)) {
1716 if (IsFlagOn(Vcb
->Flags
, VCB_WRITE_PROTECTED
)) {
1720 IoAcquireVpbSpinLock(&Irql
);
1721 if (Vcb
->Vpb
== Vcb
->Vpb
->RealDevice
->Vpb
) {
1722 SetFlag (Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
);
1724 IoReleaseVpbSpinLock(Irql
);
1726 IoSetHardErrorOrVerifyDevice( Irp
, Vcb
->Vpb
->RealDevice
);
1728 Ext2RaiseStatus(IrpContext
, STATUS_MEDIA_WRITE_PROTECTED
);
1741 Ext2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext
)
1743 PDEVICE_OBJECT DeviceObject
;
1744 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1745 PEXT2_SUPER_BLOCK ext2_sb
= NULL
;
1746 PEXT2_VCB Vcb
= NULL
;
1747 BOOLEAN VcbResourceAcquired
= FALSE
;
1749 ULONG ChangeCount
= 0;
1754 ASSERT(IrpContext
!= NULL
);
1755 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1756 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1758 DeviceObject
= IrpContext
->DeviceObject
;
1760 // This request is not allowed on the main device object
1762 if (IsExt2FsDevice(DeviceObject
)) {
1763 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1767 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
1768 ASSERT(Vcb
!= NULL
);
1769 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
1770 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
1772 VcbResourceAcquired
=
1773 ExAcquireResourceExclusiveLite(
1777 if (!FlagOn(Vcb
->TargetDeviceObject
->Flags
, DO_VERIFY_VOLUME
)) {
1778 Status
= STATUS_SUCCESS
;
1782 if (!IsMounted(Vcb
)) {
1783 Status
= STATUS_WRONG_VOLUME
;
1787 dwBytes
= sizeof(ULONG
);
1788 Status
= Ext2DiskIoControl(
1789 Vcb
->TargetDeviceObject
,
1790 IOCTL_DISK_CHECK_VERIFY
,
1797 if (!NT_SUCCESS(Status
)) {
1798 Status
= STATUS_WRONG_VOLUME
;
1801 Vcb
->ChangeCount
= ChangeCount
;
1804 Irp
= IrpContext
->Irp
;
1806 Status
= Ext2LoadSuper(Vcb
, TRUE
, &ext2_sb
);
1808 if (!NT_SUCCESS(Status
)) {
1812 ASSERT(NULL
!= ext2_sb
);
1813 if ((ext2_sb
->s_magic
== EXT2_SUPER_MAGIC
) &&
1814 (memcmp(ext2_sb
->s_uuid
, SUPER_BLOCK
->s_uuid
, 16) == 0) &&
1815 (memcmp(ext2_sb
->s_volume_name
, SUPER_BLOCK
->s_volume_name
, 16) ==0)) {
1817 ClearFlag(Vcb
->TargetDeviceObject
->Flags
, DO_VERIFY_VOLUME
);
1819 if (Ext2IsMediaWriteProtected(IrpContext
, Vcb
->TargetDeviceObject
)) {
1820 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
1822 ClearLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
1825 DEBUG(DL_INF
, ( "Ext2VerifyVolume: Volume verify succeeded.\n"));
1829 Status
= STATUS_WRONG_VOLUME
;
1830 if (VcbResourceAcquired
) {
1831 ExReleaseResourceLite(&Vcb
->MainResource
);
1832 VcbResourceAcquired
= FALSE
;
1834 Ext2PurgeVolume(Vcb
, FALSE
);
1835 VcbResourceAcquired
=
1836 ExAcquireResourceExclusiveLite(&Vcb
->MainResource
, TRUE
);
1838 SetLongFlag(Vcb
->Flags
, VCB_DISMOUNT_PENDING
);
1839 ClearFlag(Vcb
->TargetDeviceObject
->Flags
, DO_VERIFY_VOLUME
);
1841 DEBUG(DL_INF
, ( "Ext2VerifyVolume: Volume verify failed.\n"));
1847 Ext2FreePool(ext2_sb
, EXT2_SB_MAGIC
);
1849 if (VcbResourceAcquired
) {
1850 ExReleaseResourceLite(&Vcb
->MainResource
);
1853 if (!IrpContext
->ExceptionInProgress
) {
1854 Ext2CompleteIrpContext(IrpContext
, Status
);
1863 Ext2IsVolumeMounted (IN PEXT2_IRP_CONTEXT IrpContext
)
1865 PDEVICE_OBJECT DeviceObject
;
1867 NTSTATUS Status
= STATUS_SUCCESS
;
1871 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1872 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1875 DeviceObject
= IrpContext
->DeviceObject
;
1877 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
1879 ASSERT(IsMounted(Vcb
));
1881 Ext2VerifyVcb (IrpContext
, Vcb
);
1883 Ext2CompleteIrpContext(IrpContext
, Status
);
1890 Ext2DismountVolume (IN PEXT2_IRP_CONTEXT IrpContext
)
1892 PDEVICE_OBJECT DeviceObject
;
1893 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1895 BOOLEAN VcbResourceAcquired
= FALSE
;
1899 ASSERT(IrpContext
!= NULL
);
1901 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1902 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1904 DeviceObject
= IrpContext
->DeviceObject
;
1907 // This request is not allowed on the main device object
1909 if (IsExt2FsDevice(DeviceObject
)) {
1910 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1914 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
1916 ASSERT(Vcb
!= NULL
);
1918 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
1919 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
1921 ASSERT(IsMounted(Vcb
));
1923 ExAcquireResourceExclusiveLite(
1927 VcbResourceAcquired
= TRUE
;
1929 if ( IsFlagOn(Vcb
->Flags
, VCB_DISMOUNT_PENDING
)) {
1930 Status
= STATUS_VOLUME_DISMOUNTED
;
1934 Ext2FlushFiles(IrpContext
, Vcb
, FALSE
);
1935 Ext2FlushVolume(IrpContext
, Vcb
, FALSE
);
1937 ExReleaseResourceLite(&Vcb
->MainResource
);
1938 VcbResourceAcquired
= FALSE
;
1940 Ext2PurgeVolume(Vcb
, TRUE
);
1941 Ext2CheckDismount(IrpContext
, Vcb
, TRUE
);
1943 DEBUG(DL_INF
, ( "Ext2Dismount: Volume dismount pending.\n"));
1944 Status
= STATUS_SUCCESS
;
1948 if (VcbResourceAcquired
) {
1949 ExReleaseResourceLite(&Vcb
->MainResource
);
1952 if (!IrpContext
->ExceptionInProgress
) {
1953 Ext2CompleteIrpContext(IrpContext
, Status
);
1962 IN PEXT2_IRP_CONTEXT IrpContext
,
1967 PVPB Vpb
= Vcb
->Vpb
, NewVpb
= NULL
;
1968 BOOLEAN bDeleted
= FALSE
, bTearDown
= FALSE
;
1969 ULONG UnCleanCount
= 0;
1971 NewVpb
= Ext2AllocatePool(NonPagedPool
, VPB_SIZE
, TAG_VPB
);
1972 if (NewVpb
== NULL
) {
1973 DEBUG(DL_ERR
, ( "Ex2CheckDismount: failed to allocate NewVpb.\n"));
1976 INC_MEM_COUNT(PS_VPB
, NewVpb
, sizeof(VPB
));
1977 memset(NewVpb
, '_', VPB_SIZE
);
1978 RtlZeroMemory(NewVpb
, sizeof(VPB
));
1980 ExAcquireResourceExclusiveLite(
1981 &Ext2Global
->Resource
, TRUE
);
1983 ExAcquireResourceExclusiveLite(
1984 &Vcb
->MainResource
, TRUE
);
1986 if ((IrpContext
->MajorFunction
== IRP_MJ_CREATE
) &&
1987 (IrpContext
->RealDevice
== Vcb
->RealDevice
)) {
1993 IoAcquireVpbSpinLock (&Irql
);
1995 DEBUG(DL_DBG
, ("Ext2CheckDismount: Vpb %p ioctl=%d Device %p\n",
1996 Vpb
, Vpb
->ReferenceCount
, Vpb
->RealDevice
));
1997 if (Vpb
->ReferenceCount
<= UnCleanCount
) {
1999 if (!IsFlagOn(Vcb
->Flags
, VCB_DISMOUNT_PENDING
)) {
2001 ClearFlag(Vpb
->Flags
, VPB_MOUNTED
);
2002 ClearFlag(Vpb
->Flags
, VPB_LOCKED
);
2004 if ((Vcb
->RealDevice
!= Vpb
->RealDevice
) &&
2005 (Vcb
->RealDevice
->Vpb
== Vpb
)) {
2006 SetFlag(Vcb
->RealDevice
->Flags
, DO_DEVICE_INITIALIZING
);
2007 SetFlag(Vpb
->Flags
, VPB_PERSISTENT
);
2011 SetLongFlag(Vcb
->Flags
, VCB_DISMOUNT_PENDING
);
2014 if (Vpb
->ReferenceCount
) {
2018 Vpb
->DeviceObject
= NULL
;
2021 } else if (bForce
) {
2023 DEBUG(DL_DBG
, ( "Ext2CheckDismount: NewVpb %p Realdevice = %p\n",
2024 NewVpb
, Vpb
->RealDevice
));
2026 Vcb
->Vpb2
= Vcb
->Vpb
;
2027 NewVpb
->Type
= IO_TYPE_VPB
;
2028 NewVpb
->Size
= sizeof(VPB
);
2029 NewVpb
->Flags
= Vpb
->Flags
& VPB_REMOVE_PENDING
;
2030 NewVpb
->RealDevice
= Vpb
->RealDevice
;
2031 NewVpb
->RealDevice
->Vpb
= NewVpb
;
2033 ClearFlag(Vpb
->Flags
, VPB_MOUNTED
);
2034 SetLongFlag(Vcb
->Flags
, VCB_NEW_VPB
);
2035 ClearLongFlag(Vcb
->Flags
, VCB_MOUNTED
);
2038 IoReleaseVpbSpinLock(Irql
);
2040 ExReleaseResourceLite(&Vcb
->MainResource
);
2041 ExReleaseResourceLite(&Ext2Global
->Resource
);
2044 DEBUG(DL_DBG
, ( "Ext2CheckDismount: Tearing vcb %p ...\n", Vcb
));
2045 Ext2TearDownStream(Vcb
);
2049 DEBUG(DL_DBG
, ( "Ext2CheckDismount: Deleting vcb %p ...\n", Vcb
));
2050 Ext2DestroyVcb(Vcb
);
2053 if (NewVpb
!= NULL
) {
2054 DEBUG(DL_DBG
, ( "Ext2CheckDismount: freeing Vpb %p\n", NewVpb
));
2055 Ext2FreePool(NewVpb
, TAG_VPB
);
2056 DEC_MEM_COUNT(PS_VPB
, NewVpb
, sizeof(VPB
));
2063 Ext2PurgeVolume (IN PEXT2_VCB Vcb
,
2064 IN BOOLEAN FlushBeforePurge
)
2068 PLIST_ENTRY ListEntry
;
2069 PFCB_LIST_ENTRY FcbListEntry
;
2070 BOOLEAN VcbResourceAcquired
= FALSE
;
2073 ASSERT(Vcb
!= NULL
);
2074 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2075 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2077 VcbResourceAcquired
=
2078 ExAcquireResourceExclusiveLite(&Vcb
->MainResource
, TRUE
);
2080 if (IsVcbReadOnly(Vcb
)) {
2081 FlushBeforePurge
= FALSE
;
2087 InitializeListHead(&FcbList
);
2089 for (ListEntry
= Vcb
->FcbList
.Flink
;
2090 ListEntry
!= &Vcb
->FcbList
;
2091 ListEntry
= ListEntry
->Flink
) {
2093 Fcb
= CONTAINING_RECORD(ListEntry
, EXT2_FCB
, Next
);
2095 DEBUG(DL_INF
, ( "Ext2PurgeVolume: %wZ refercount=%xh\n", &Fcb
->Mcb
->FullName
, Fcb
->ReferenceCount
));
2097 FcbListEntry
= Ext2AllocatePool(
2099 sizeof(FCB_LIST_ENTRY
),
2104 FcbListEntry
->Fcb
= Fcb
;
2105 Ext2ReferXcb(&Fcb
->ReferenceCount
);
2106 InsertTailList(&FcbList
, &FcbListEntry
->Next
);
2108 DEBUG(DL_ERR
, ( "Ext2PurgeVolume: failed to allocate FcbListEntry ...\n"));
2112 while (!IsListEmpty(&FcbList
)) {
2114 ListEntry
= RemoveHeadList(&FcbList
);
2116 FcbListEntry
= CONTAINING_RECORD(ListEntry
, FCB_LIST_ENTRY
, Next
);
2118 Fcb
= FcbListEntry
->Fcb
;
2120 if (ExAcquireResourceExclusiveLite(
2124 Ext2PurgeFile(Fcb
, FlushBeforePurge
);
2126 if (!Fcb
->OpenHandleCount
&& Fcb
->ReferenceCount
== 1) {
2129 ExReleaseResourceLite(&Fcb
->MainResource
);
2133 Ext2FreePool(FcbListEntry
, EXT2_FLIST_MAGIC
);
2136 if (FlushBeforePurge
) {
2137 ExAcquireSharedStarveExclusive(&Vcb
->PagingIoResource
, TRUE
);
2138 ExReleaseResourceLite(&Vcb
->PagingIoResource
);
2140 CcFlushCache(&Vcb
->SectionObject
, NULL
, 0, NULL
);
2143 if (Vcb
->SectionObject
.ImageSectionObject
) {
2144 MmFlushImageSection(&Vcb
->SectionObject
, MmFlushForWrite
);
2147 if (VcbResourceAcquired
) {
2148 ExReleaseResourceLite(&Vcb
->MainResource
);
2149 VcbResourceAcquired
= FALSE
;
2152 if (Vcb
->SectionObject
.DataSectionObject
) {
2153 CcPurgeCacheSection(&Vcb
->SectionObject
, NULL
, 0, FALSE
);
2156 DEBUG(DL_INF
, ( "Ext2PurgeVolume: Volume flushed and purged.\n"));
2160 if (VcbResourceAcquired
) {
2161 ExReleaseResourceLite(&Vcb
->MainResource
);
2165 return STATUS_SUCCESS
;
2169 Ext2PurgeFile ( IN PEXT2_FCB Fcb
,
2170 IN BOOLEAN FlushBeforePurge
)
2172 IO_STATUS_BLOCK IoStatus
;
2174 ASSERT(Fcb
!= NULL
);
2176 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
2177 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
2180 if (!IsVcbReadOnly(Fcb
->Vcb
) && FlushBeforePurge
) {
2182 DEBUG(DL_INF
, ( "Ext2PurgeFile: CcFlushCache on %wZ.\n",
2183 &Fcb
->Mcb
->FullName
));
2185 ExAcquireSharedStarveExclusive(&Fcb
->PagingIoResource
, TRUE
);
2186 ExReleaseResourceLite(&Fcb
->PagingIoResource
);
2188 CcFlushCache(&Fcb
->SectionObject
, NULL
, 0, &IoStatus
);
2189 ClearFlag(Fcb
->Flags
, FCB_FILE_MODIFIED
);
2192 if (Fcb
->SectionObject
.ImageSectionObject
) {
2194 DEBUG(DL_INF
, ( "Ext2PurgeFile: MmFlushImageSection on %wZ.\n",
2195 &Fcb
->Mcb
->FullName
));
2197 MmFlushImageSection(&Fcb
->SectionObject
, MmFlushForWrite
);
2200 if (Fcb
->SectionObject
.DataSectionObject
) {
2202 DEBUG(DL_INF
, ( "Ext2PurgeFile: CcPurgeCacheSection on %wZ.\n",
2203 &Fcb
->Mcb
->FullName
));
2205 CcPurgeCacheSection(&Fcb
->SectionObject
, NULL
, 0, FALSE
);
2208 return STATUS_SUCCESS
;
2213 Ext2FileSystemControl (IN PEXT2_IRP_CONTEXT IrpContext
)
2219 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
2220 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
2222 switch (IrpContext
->MinorFunction
) {
2224 case IRP_MN_USER_FS_REQUEST
:
2225 Status
= Ext2UserFsRequest(IrpContext
);
2228 case IRP_MN_MOUNT_VOLUME
:
2229 Status
= Ext2MountVolume(IrpContext
);
2232 case IRP_MN_VERIFY_VOLUME
:
2233 Status
= Ext2VerifyVolume(IrpContext
);
2238 DEBUG(DL_ERR
, ( "Ext2FilsSystemControl: Invalid Device Request.\n"));
2239 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2240 Ext2CompleteIrpContext(IrpContext
, Status
);