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
)) {
1500 if (DiskGeometry
.MediaType
== Unknown
)
1502 DiskGeometry
.BytesPerSector
= 512;
1506 Status
= IoCreateDevice(
1507 MainDeviceObject
->DriverObject
,
1510 FILE_DEVICE_DISK_FILE_SYSTEM
,
1513 &VolumeDeviceObject
);
1515 if (!NT_SUCCESS(Status
)) {
1518 INC_MEM_COUNT(PS_VCB
, VolumeDeviceObject
, sizeof(EXT2_VCB
));
1520 VolumeDeviceObject
->StackSize
= (CCHAR
)(TargetDeviceObject
->StackSize
+ 1);
1521 ClearFlag(VolumeDeviceObject
->Flags
, DO_DEVICE_INITIALIZING
);
1523 if (TargetDeviceObject
->AlignmentRequirement
>
1524 VolumeDeviceObject
->AlignmentRequirement
) {
1526 VolumeDeviceObject
->AlignmentRequirement
=
1527 TargetDeviceObject
->AlignmentRequirement
;
1530 (IoStackLocation
->Parameters
.MountVolume
.Vpb
)->DeviceObject
=
1532 Vpb
= IoStackLocation
->Parameters
.MountVolume
.Vpb
;
1534 Vcb
= (PEXT2_VCB
) VolumeDeviceObject
->DeviceExtension
;
1536 RtlZeroMemory(Vcb
, sizeof(EXT2_VCB
));
1537 Vcb
->Identifier
.Type
= EXT2VCB
;
1538 Vcb
->Identifier
.Size
= sizeof(EXT2_VCB
);
1539 Vcb
->TargetDeviceObject
= TargetDeviceObject
;
1540 Vcb
->DiskGeometry
= DiskGeometry
;
1541 InitializeListHead(&Vcb
->Next
);
1543 Status
= Ext2LoadSuper(Vcb
, FALSE
, &Ext2Sb
);
1544 if (!NT_SUCCESS(Status
)) {
1546 Status
= STATUS_UNRECOGNIZED_VOLUME
;
1549 ASSERT (NULL
!= Ext2Sb
);
1551 /* check Linux Ext2/Ext3 volume magic */
1552 if (Ext2Sb
->s_magic
== EXT2_SUPER_MAGIC
) {
1553 DEBUG(DL_INF
, ( "Volume of ext2 file system is found.\n"));
1555 Status
= STATUS_UNRECOGNIZED_VOLUME
;
1560 DEBUG(DL_DBG
, ("Ext2MountVolume: DevObject=%p Vcb=%p\n", VolumeDeviceObject
, Vcb
));
1562 /* initialize Vcb structure */
1563 Status
= Ext2InitializeVcb( IrpContext
, Vcb
, Ext2Sb
,
1565 VolumeDeviceObject
, Vpb
);
1567 if (NT_SUCCESS(Status
)) {
1571 ExAcquireResourceExclusiveLite(&(Ext2Global
->Resource
), TRUE
);
1572 GlobalDataResourceAcquired
= TRUE
;
1574 for (List
= Ext2Global
->VcbList
.Flink
;
1575 List
!= &Ext2Global
->VcbList
;
1576 List
= List
->Flink
) {
1578 OldVcb
= CONTAINING_RECORD(List
, EXT2_VCB
, Next
);
1579 OldVpb
= OldVcb
->Vpb
;
1581 /* in case we are already in the queue, should not happen */
1582 if (OldVpb
== Vpb
) {
1586 if ( (OldVpb
->SerialNumber
== Vpb
->SerialNumber
) &&
1587 (!IsMounted(OldVcb
)) && (IsFlagOn(OldVcb
->Flags
, VCB_NEW_VPB
)) &&
1588 (OldVpb
->RealDevice
== TargetDeviceObject
) &&
1589 (OldVpb
->VolumeLabelLength
== Vpb
->VolumeLabelLength
) &&
1590 (RtlEqualMemory(&OldVpb
->VolumeLabel
[0],
1591 &Vpb
->VolumeLabel
[0],
1592 Vpb
->VolumeLabelLength
)) &&
1593 (RtlEqualMemory(&OldVcb
->SuperBlock
->s_uuid
[0],
1594 &Vcb
->SuperBlock
->s_uuid
[0], 16)) ) {
1595 ClearFlag(OldVcb
->Flags
, VCB_MOUNTED
);
1599 SetLongFlag(Vcb
->Flags
, VCB_MOUNTED
);
1600 SetFlag(Vcb
->Vpb
->Flags
, VPB_MOUNTED
);
1604 ObDereferenceObject(TargetDeviceObject
);
1613 if (GlobalDataResourceAcquired
) {
1614 ExReleaseResourceLite(&Ext2Global
->Resource
);
1617 if (!NT_SUCCESS(Status
)) {
1619 if (!NT_SUCCESS(Status
)) {
1620 if ( Vpb
!= NULL
) {
1621 Vpb
->DeviceObject
= NULL
;
1626 Ext2DestroyVcb(Vcb
);
1629 Ext2FreePool(Ext2Sb
, EXT2_SB_MAGIC
);
1631 if (VolumeDeviceObject
) {
1632 IoDeleteDevice(VolumeDeviceObject
);
1633 DEC_MEM_COUNT(PS_VCB
, VolumeDeviceObject
, sizeof(EXT2_VCB
));
1638 if (!IrpContext
->ExceptionInProgress
) {
1639 Ext2CompleteIrpContext(IrpContext
, Status
);
1647 Ext2VerifyVcb (IN PEXT2_IRP_CONTEXT IrpContext
,
1650 NTSTATUS Status
= STATUS_SUCCESS
;
1652 BOOLEAN bVerify
= FALSE
;
1653 ULONG ChangeCount
= 0;
1657 PEXTENDED_IO_STACK_LOCATION IrpSp
;
1661 ASSERT(IrpContext
!= NULL
);
1663 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1664 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1666 Irp
= IrpContext
->Irp
;
1667 IrpSp
= (PEXTENDED_IO_STACK_LOCATION
)IoGetCurrentIrpStackLocation(Irp
);
1669 bVerify
= IsFlagOn(Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
);
1671 if ( (IsFlagOn(Vcb
->Flags
, VCB_REMOVABLE_MEDIA
) ||
1672 IsFlagOn(Vcb
->Flags
, VCB_FLOPPY_DISK
)) && !bVerify
) {
1674 dwBytes
= sizeof(ULONG
);
1675 Status
= Ext2DiskIoControl(
1676 Vcb
->TargetDeviceObject
,
1677 IOCTL_DISK_CHECK_VERIFY
,
1683 if ( STATUS_VERIFY_REQUIRED
== Status
||
1684 STATUS_DEVICE_NOT_READY
== Status
||
1685 STATUS_NO_MEDIA_IN_DEVICE
== Status
||
1686 (NT_SUCCESS(Status
) &&
1687 (ChangeCount
!= Vcb
->ChangeCount
))) {
1691 IoAcquireVpbSpinLock(&Irql
);
1692 if (Vcb
->Vpb
== Vcb
->Vpb
->RealDevice
->Vpb
) {
1693 SetFlag(Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
);
1695 IoReleaseVpbSpinLock(Irql
);
1699 if (!NT_SUCCESS(Status
)) {
1700 Ext2NormalizeAndRaiseStatus(IrpContext
, Status
);
1705 if ( IsFlagOn(Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
)) {
1706 IoSetHardErrorOrVerifyDevice( Irp
, Vcb
->Vpb
->RealDevice
);
1707 Ext2NormalizeAndRaiseStatus ( IrpContext
,
1708 STATUS_VERIFY_REQUIRED
);
1711 if (IsMounted(Vcb
)) {
1713 if ( (IrpContext
->MajorFunction
== IRP_MJ_WRITE
) ||
1714 (IrpContext
->MajorFunction
== IRP_MJ_SET_INFORMATION
) ||
1715 (IrpContext
->MajorFunction
== IRP_MJ_SET_EA
) ||
1716 (IrpContext
->MajorFunction
== IRP_MJ_FLUSH_BUFFERS
) ||
1717 (IrpContext
->MajorFunction
== IRP_MJ_SET_VOLUME_INFORMATION
) ||
1718 (IrpContext
->MajorFunction
== IRP_MJ_FILE_SYSTEM_CONTROL
&&
1719 IrpContext
->MinorFunction
== IRP_MN_USER_FS_REQUEST
&&
1720 IrpSp
->Parameters
.FileSystemControl
.FsControlCode
==
1721 FSCTL_MARK_VOLUME_DIRTY
)) {
1723 if (IsFlagOn(Vcb
->Flags
, VCB_WRITE_PROTECTED
)) {
1727 IoAcquireVpbSpinLock(&Irql
);
1728 if (Vcb
->Vpb
== Vcb
->Vpb
->RealDevice
->Vpb
) {
1729 SetFlag (Vcb
->Vpb
->RealDevice
->Flags
, DO_VERIFY_VOLUME
);
1731 IoReleaseVpbSpinLock(Irql
);
1733 IoSetHardErrorOrVerifyDevice( Irp
, Vcb
->Vpb
->RealDevice
);
1735 Ext2RaiseStatus(IrpContext
, STATUS_MEDIA_WRITE_PROTECTED
);
1748 Ext2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext
)
1750 PDEVICE_OBJECT DeviceObject
;
1751 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1752 PEXT2_SUPER_BLOCK ext2_sb
= NULL
;
1753 PEXT2_VCB Vcb
= NULL
;
1754 BOOLEAN VcbResourceAcquired
= FALSE
;
1756 ULONG ChangeCount
= 0;
1761 ASSERT(IrpContext
!= NULL
);
1762 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1763 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1765 DeviceObject
= IrpContext
->DeviceObject
;
1767 // This request is not allowed on the main device object
1769 if (IsExt2FsDevice(DeviceObject
)) {
1770 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1774 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
1775 ASSERT(Vcb
!= NULL
);
1776 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
1777 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
1779 VcbResourceAcquired
=
1780 ExAcquireResourceExclusiveLite(
1784 if (!FlagOn(Vcb
->TargetDeviceObject
->Flags
, DO_VERIFY_VOLUME
)) {
1785 Status
= STATUS_SUCCESS
;
1789 if (!IsMounted(Vcb
)) {
1790 Status
= STATUS_WRONG_VOLUME
;
1794 dwBytes
= sizeof(ULONG
);
1795 Status
= Ext2DiskIoControl(
1796 Vcb
->TargetDeviceObject
,
1797 IOCTL_DISK_CHECK_VERIFY
,
1804 if (!NT_SUCCESS(Status
)) {
1805 Status
= STATUS_WRONG_VOLUME
;
1808 Vcb
->ChangeCount
= ChangeCount
;
1811 Irp
= IrpContext
->Irp
;
1813 Status
= Ext2LoadSuper(Vcb
, TRUE
, &ext2_sb
);
1815 if (!NT_SUCCESS(Status
)) {
1819 ASSERT(NULL
!= ext2_sb
);
1820 if ((ext2_sb
->s_magic
== EXT2_SUPER_MAGIC
) &&
1821 (memcmp(ext2_sb
->s_uuid
, SUPER_BLOCK
->s_uuid
, 16) == 0) &&
1822 (memcmp(ext2_sb
->s_volume_name
, SUPER_BLOCK
->s_volume_name
, 16) ==0)) {
1824 ClearFlag(Vcb
->TargetDeviceObject
->Flags
, DO_VERIFY_VOLUME
);
1826 if (Ext2IsMediaWriteProtected(IrpContext
, Vcb
->TargetDeviceObject
)) {
1827 SetLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
1829 ClearLongFlag(Vcb
->Flags
, VCB_WRITE_PROTECTED
);
1832 DEBUG(DL_INF
, ( "Ext2VerifyVolume: Volume verify succeeded.\n"));
1836 Status
= STATUS_WRONG_VOLUME
;
1837 if (VcbResourceAcquired
) {
1838 ExReleaseResourceLite(&Vcb
->MainResource
);
1839 VcbResourceAcquired
= FALSE
;
1841 Ext2PurgeVolume(Vcb
, FALSE
);
1842 VcbResourceAcquired
=
1843 ExAcquireResourceExclusiveLite(&Vcb
->MainResource
, TRUE
);
1845 SetLongFlag(Vcb
->Flags
, VCB_DISMOUNT_PENDING
);
1846 ClearFlag(Vcb
->TargetDeviceObject
->Flags
, DO_VERIFY_VOLUME
);
1848 DEBUG(DL_INF
, ( "Ext2VerifyVolume: Volume verify failed.\n"));
1854 Ext2FreePool(ext2_sb
, EXT2_SB_MAGIC
);
1856 if (VcbResourceAcquired
) {
1857 ExReleaseResourceLite(&Vcb
->MainResource
);
1860 if (!IrpContext
->ExceptionInProgress
) {
1861 Ext2CompleteIrpContext(IrpContext
, Status
);
1870 Ext2IsVolumeMounted (IN PEXT2_IRP_CONTEXT IrpContext
)
1872 PDEVICE_OBJECT DeviceObject
;
1874 NTSTATUS Status
= STATUS_SUCCESS
;
1878 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1879 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1882 DeviceObject
= IrpContext
->DeviceObject
;
1884 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
1886 ASSERT(IsMounted(Vcb
));
1888 Ext2VerifyVcb (IrpContext
, Vcb
);
1890 Ext2CompleteIrpContext(IrpContext
, Status
);
1897 Ext2DismountVolume (IN PEXT2_IRP_CONTEXT IrpContext
)
1899 PDEVICE_OBJECT DeviceObject
;
1900 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1902 BOOLEAN VcbResourceAcquired
= FALSE
;
1906 ASSERT(IrpContext
!= NULL
);
1908 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
1909 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
1911 DeviceObject
= IrpContext
->DeviceObject
;
1914 // This request is not allowed on the main device object
1916 if (IsExt2FsDevice(DeviceObject
)) {
1917 Status
= STATUS_INVALID_DEVICE_REQUEST
;
1921 Vcb
= (PEXT2_VCB
) DeviceObject
->DeviceExtension
;
1923 ASSERT(Vcb
!= NULL
);
1925 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
1926 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
1928 ASSERT(IsMounted(Vcb
));
1930 ExAcquireResourceExclusiveLite(
1934 VcbResourceAcquired
= TRUE
;
1936 if ( IsFlagOn(Vcb
->Flags
, VCB_DISMOUNT_PENDING
)) {
1937 Status
= STATUS_VOLUME_DISMOUNTED
;
1941 Ext2FlushFiles(IrpContext
, Vcb
, FALSE
);
1942 Ext2FlushVolume(IrpContext
, Vcb
, FALSE
);
1944 ExReleaseResourceLite(&Vcb
->MainResource
);
1945 VcbResourceAcquired
= FALSE
;
1947 Ext2PurgeVolume(Vcb
, TRUE
);
1948 Ext2CheckDismount(IrpContext
, Vcb
, TRUE
);
1950 DEBUG(DL_INF
, ( "Ext2Dismount: Volume dismount pending.\n"));
1951 Status
= STATUS_SUCCESS
;
1955 if (VcbResourceAcquired
) {
1956 ExReleaseResourceLite(&Vcb
->MainResource
);
1959 if (!IrpContext
->ExceptionInProgress
) {
1960 Ext2CompleteIrpContext(IrpContext
, Status
);
1969 IN PEXT2_IRP_CONTEXT IrpContext
,
1974 PVPB Vpb
= Vcb
->Vpb
, NewVpb
= NULL
;
1975 BOOLEAN bDeleted
= FALSE
, bTearDown
= FALSE
;
1976 ULONG UnCleanCount
= 0;
1978 NewVpb
= Ext2AllocatePool(NonPagedPool
, VPB_SIZE
, TAG_VPB
);
1979 if (NewVpb
== NULL
) {
1980 DEBUG(DL_ERR
, ( "Ex2CheckDismount: failed to allocate NewVpb.\n"));
1983 INC_MEM_COUNT(PS_VPB
, NewVpb
, sizeof(VPB
));
1984 memset(NewVpb
, '_', VPB_SIZE
);
1985 RtlZeroMemory(NewVpb
, sizeof(VPB
));
1987 ExAcquireResourceExclusiveLite(
1988 &Ext2Global
->Resource
, TRUE
);
1990 ExAcquireResourceExclusiveLite(
1991 &Vcb
->MainResource
, TRUE
);
1993 if ((IrpContext
->MajorFunction
== IRP_MJ_CREATE
) &&
1994 (IrpContext
->RealDevice
== Vcb
->RealDevice
)) {
2000 IoAcquireVpbSpinLock (&Irql
);
2002 DEBUG(DL_DBG
, ("Ext2CheckDismount: Vpb %p ioctl=%d Device %p\n",
2003 Vpb
, Vpb
->ReferenceCount
, Vpb
->RealDevice
));
2004 if (Vpb
->ReferenceCount
<= UnCleanCount
) {
2006 if (!IsFlagOn(Vcb
->Flags
, VCB_DISMOUNT_PENDING
)) {
2008 ClearFlag(Vpb
->Flags
, VPB_MOUNTED
);
2009 ClearFlag(Vpb
->Flags
, VPB_LOCKED
);
2011 if ((Vcb
->RealDevice
!= Vpb
->RealDevice
) &&
2012 (Vcb
->RealDevice
->Vpb
== Vpb
)) {
2013 SetFlag(Vcb
->RealDevice
->Flags
, DO_DEVICE_INITIALIZING
);
2014 SetFlag(Vpb
->Flags
, VPB_PERSISTENT
);
2018 SetLongFlag(Vcb
->Flags
, VCB_DISMOUNT_PENDING
);
2021 if (Vpb
->ReferenceCount
) {
2025 Vpb
->DeviceObject
= NULL
;
2028 } else if (bForce
) {
2030 DEBUG(DL_DBG
, ( "Ext2CheckDismount: NewVpb %p Realdevice = %p\n",
2031 NewVpb
, Vpb
->RealDevice
));
2033 Vcb
->Vpb2
= Vcb
->Vpb
;
2034 NewVpb
->Type
= IO_TYPE_VPB
;
2035 NewVpb
->Size
= sizeof(VPB
);
2036 NewVpb
->Flags
= Vpb
->Flags
& VPB_REMOVE_PENDING
;
2037 NewVpb
->RealDevice
= Vpb
->RealDevice
;
2038 NewVpb
->RealDevice
->Vpb
= NewVpb
;
2040 ClearFlag(Vpb
->Flags
, VPB_MOUNTED
);
2041 SetLongFlag(Vcb
->Flags
, VCB_NEW_VPB
);
2042 ClearLongFlag(Vcb
->Flags
, VCB_MOUNTED
);
2045 IoReleaseVpbSpinLock(Irql
);
2047 ExReleaseResourceLite(&Vcb
->MainResource
);
2048 ExReleaseResourceLite(&Ext2Global
->Resource
);
2051 DEBUG(DL_DBG
, ( "Ext2CheckDismount: Tearing vcb %p ...\n", Vcb
));
2052 Ext2TearDownStream(Vcb
);
2056 DEBUG(DL_DBG
, ( "Ext2CheckDismount: Deleting vcb %p ...\n", Vcb
));
2057 Ext2DestroyVcb(Vcb
);
2060 if (NewVpb
!= NULL
) {
2061 DEBUG(DL_DBG
, ( "Ext2CheckDismount: freeing Vpb %p\n", NewVpb
));
2062 Ext2FreePool(NewVpb
, TAG_VPB
);
2063 DEC_MEM_COUNT(PS_VPB
, NewVpb
, sizeof(VPB
));
2070 Ext2PurgeVolume (IN PEXT2_VCB Vcb
,
2071 IN BOOLEAN FlushBeforePurge
)
2075 PLIST_ENTRY ListEntry
;
2076 PFCB_LIST_ENTRY FcbListEntry
;
2077 BOOLEAN VcbResourceAcquired
= FALSE
;
2080 ASSERT(Vcb
!= NULL
);
2081 ASSERT((Vcb
->Identifier
.Type
== EXT2VCB
) &&
2082 (Vcb
->Identifier
.Size
== sizeof(EXT2_VCB
)));
2084 VcbResourceAcquired
=
2085 ExAcquireResourceExclusiveLite(&Vcb
->MainResource
, TRUE
);
2087 if (IsVcbReadOnly(Vcb
)) {
2088 FlushBeforePurge
= FALSE
;
2094 InitializeListHead(&FcbList
);
2096 for (ListEntry
= Vcb
->FcbList
.Flink
;
2097 ListEntry
!= &Vcb
->FcbList
;
2098 ListEntry
= ListEntry
->Flink
) {
2100 Fcb
= CONTAINING_RECORD(ListEntry
, EXT2_FCB
, Next
);
2102 DEBUG(DL_INF
, ( "Ext2PurgeVolume: %wZ refercount=%xh\n", &Fcb
->Mcb
->FullName
, Fcb
->ReferenceCount
));
2104 FcbListEntry
= Ext2AllocatePool(
2106 sizeof(FCB_LIST_ENTRY
),
2111 FcbListEntry
->Fcb
= Fcb
;
2112 Ext2ReferXcb(&Fcb
->ReferenceCount
);
2113 InsertTailList(&FcbList
, &FcbListEntry
->Next
);
2115 DEBUG(DL_ERR
, ( "Ext2PurgeVolume: failed to allocate FcbListEntry ...\n"));
2119 while (!IsListEmpty(&FcbList
)) {
2121 ListEntry
= RemoveHeadList(&FcbList
);
2123 FcbListEntry
= CONTAINING_RECORD(ListEntry
, FCB_LIST_ENTRY
, Next
);
2125 Fcb
= FcbListEntry
->Fcb
;
2127 if (ExAcquireResourceExclusiveLite(
2131 Ext2PurgeFile(Fcb
, FlushBeforePurge
);
2133 if (!Fcb
->OpenHandleCount
&& Fcb
->ReferenceCount
== 1) {
2136 ExReleaseResourceLite(&Fcb
->MainResource
);
2140 Ext2FreePool(FcbListEntry
, EXT2_FLIST_MAGIC
);
2143 if (FlushBeforePurge
) {
2144 ExAcquireSharedStarveExclusive(&Vcb
->PagingIoResource
, TRUE
);
2145 ExReleaseResourceLite(&Vcb
->PagingIoResource
);
2147 CcFlushCache(&Vcb
->SectionObject
, NULL
, 0, NULL
);
2150 if (Vcb
->SectionObject
.ImageSectionObject
) {
2151 MmFlushImageSection(&Vcb
->SectionObject
, MmFlushForWrite
);
2154 if (VcbResourceAcquired
) {
2155 ExReleaseResourceLite(&Vcb
->MainResource
);
2156 VcbResourceAcquired
= FALSE
;
2159 if (Vcb
->SectionObject
.DataSectionObject
) {
2160 CcPurgeCacheSection(&Vcb
->SectionObject
, NULL
, 0, FALSE
);
2163 DEBUG(DL_INF
, ( "Ext2PurgeVolume: Volume flushed and purged.\n"));
2167 if (VcbResourceAcquired
) {
2168 ExReleaseResourceLite(&Vcb
->MainResource
);
2172 return STATUS_SUCCESS
;
2176 Ext2PurgeFile ( IN PEXT2_FCB Fcb
,
2177 IN BOOLEAN FlushBeforePurge
)
2179 IO_STATUS_BLOCK IoStatus
;
2181 ASSERT(Fcb
!= NULL
);
2183 ASSERT((Fcb
->Identifier
.Type
== EXT2FCB
) &&
2184 (Fcb
->Identifier
.Size
== sizeof(EXT2_FCB
)));
2187 if (!IsVcbReadOnly(Fcb
->Vcb
) && FlushBeforePurge
) {
2189 DEBUG(DL_INF
, ( "Ext2PurgeFile: CcFlushCache on %wZ.\n",
2190 &Fcb
->Mcb
->FullName
));
2192 ExAcquireSharedStarveExclusive(&Fcb
->PagingIoResource
, TRUE
);
2193 ExReleaseResourceLite(&Fcb
->PagingIoResource
);
2195 CcFlushCache(&Fcb
->SectionObject
, NULL
, 0, &IoStatus
);
2196 ClearFlag(Fcb
->Flags
, FCB_FILE_MODIFIED
);
2199 if (Fcb
->SectionObject
.ImageSectionObject
) {
2201 DEBUG(DL_INF
, ( "Ext2PurgeFile: MmFlushImageSection on %wZ.\n",
2202 &Fcb
->Mcb
->FullName
));
2204 MmFlushImageSection(&Fcb
->SectionObject
, MmFlushForWrite
);
2207 if (Fcb
->SectionObject
.DataSectionObject
) {
2209 DEBUG(DL_INF
, ( "Ext2PurgeFile: CcPurgeCacheSection on %wZ.\n",
2210 &Fcb
->Mcb
->FullName
));
2212 CcPurgeCacheSection(&Fcb
->SectionObject
, NULL
, 0, FALSE
);
2215 return STATUS_SUCCESS
;
2220 Ext2FileSystemControl (IN PEXT2_IRP_CONTEXT IrpContext
)
2226 ASSERT((IrpContext
->Identifier
.Type
== EXT2ICX
) &&
2227 (IrpContext
->Identifier
.Size
== sizeof(EXT2_IRP_CONTEXT
)));
2229 switch (IrpContext
->MinorFunction
) {
2231 case IRP_MN_USER_FS_REQUEST
:
2232 Status
= Ext2UserFsRequest(IrpContext
);
2235 case IRP_MN_MOUNT_VOLUME
:
2236 Status
= Ext2MountVolume(IrpContext
);
2239 case IRP_MN_VERIFY_VOLUME
:
2240 Status
= Ext2VerifyVolume(IrpContext
);
2245 DEBUG(DL_ERR
, ( "Ext2FilsSystemControl: Invalid Device Request.\n"));
2246 Status
= STATUS_INVALID_DEVICE_REQUEST
;
2247 Ext2CompleteIrpContext(IrpContext
, Status
);