📄 fsctl.c
字号:
/*
* COPYRIGHT: See COPYRIGHT.TXT
* PROJECT: Ext2 File System Driver for WinNT/2K/XP
* FILE: fsctl.c
* PROGRAMMER: Matt Wu <mattwu@163.com>
* HOMEPAGE: http://ext2.yeah.net
* UPDATE HISTORY:
*/
/* INCLUDES *****************************************************************/
#include "ntifs.h"
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL gExt2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, Ext2SetVpbFlag)
#pragma alloc_text(PAGE, Ext2ClearVpbFlag)
#pragma alloc_text(PAGE, Ext2LockVolume)
#pragma alloc_text(PAGE, Ext2UnlockVolume)
#pragma alloc_text(PAGE, Ext2UserFsRequest)
#pragma alloc_text(PAGE, Ext2MountVolume)
#pragma alloc_text(PAGE, Ext2PurgeVolume)
#pragma alloc_text(PAGE, Ext2PurgeFile)
#pragma alloc_text(PAGE, Ext2DismountVolume)
#pragma alloc_text(PAGE, Ext2IsVolumeMounted)
#pragma alloc_text(PAGE, Ext2VerifyVolume)
#pragma alloc_text(PAGE, Ext2FileSystemControl)
#endif
VOID
Ext2SetVpbFlag (IN PVPB Vpb,
IN USHORT Flag )
{
KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql);
Vpb->Flags |= Flag;
IoReleaseVpbSpinLock(OldIrql);
}
VOID
Ext2ClearVpbFlag (IN PVPB Vpb,
IN USHORT Flag )
{
KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql);
Vpb->Flags &= ~Flag;
IoReleaseVpbSpinLock(OldIrql);
}
NTSTATUS
Ext2LockVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_VCB Vcb;
BOOLEAN VcbResourceAcquired = FALSE;
__try
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == gExt2Global->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ExAcquireResourceSharedLite(
&Vcb->MainResource,
TRUE );
VcbResourceAcquired = TRUE;
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
{
Ext2DbgPrint(D_FSCTL, "Ext2LockVolume: Volume is already locked.\n");
Status = STATUS_ACCESS_DENIED;
__leave;
}
if (Vcb->OpenFileHandleCount)
{
Ext2DbgPrint(D_FSCTL, "Ext2LockVolume: Open files exists.\n");
Status = STATUS_ACCESS_DENIED;
__leave;
}
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread()
);
VcbResourceAcquired = FALSE;
Ext2PurgeVolume(Vcb, TRUE);
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE
);
VcbResourceAcquired = TRUE;
if (!IsListEmpty(&Vcb->FcbList))
{
Ext2DbgPrint(D_FSCTL, "Ext2LockVolume: Could not purge cached files.\n");
Status = STATUS_ACCESS_DENIED;
__leave;
}
SetFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
Ext2SetVpbFlag(Vcb->Vpb, VPB_LOCKED);
Ext2DbgPrint(D_FSCTL, "Ext2LockVolume: Volume locked.\n");
Status = STATUS_SUCCESS;
}
__finally
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
Ext2FreeIrpContext(IrpContext);
}
}
return Status;
}
NTSTATUS
Ext2UnlockVolume (
IN PEXT2_IRP_CONTEXT IrpContext
)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_VCB Vcb;
BOOLEAN VcbResourceAcquired = FALSE;
__try
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == gExt2Global->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE );
VcbResourceAcquired = TRUE;
if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
{
Ext2DbgPrint(D_FSCTL, ": Ext2UnlockVolume: Volume is not locked .\n");
Status = STATUS_ACCESS_DENIED;
__leave;
}
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
Ext2DbgPrint(D_FSCTL, "Ext2UnlockVolume: Volume unlocked.\n");
Status = STATUS_SUCCESS;
}
__finally
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread()
);
}
if (!IrpContext->ExceptionInProgress)
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
Ext2FreeIrpContext(IrpContext);
}
}
return Status;
}
NTSTATUS
Ext2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext)
{
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
ULONG FsControlCode;
NTSTATUS Status;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
#ifndef _GNU_NTIFS_
FsControlCode =
IoStackLocation->Parameters.FileSystemControl.FsControlCode;
#else
FsControlCode = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.FileSystemControl.FsControlCode;
#endif
switch (FsControlCode)
{
case FSCTL_LOCK_VOLUME:
Status = Ext2LockVolume(IrpContext);
break;
case FSCTL_UNLOCK_VOLUME:
Status = Ext2UnlockVolume(IrpContext);
break;
case FSCTL_DISMOUNT_VOLUME:
Status = Ext2DismountVolume(IrpContext);
break;
case FSCTL_IS_VOLUME_MOUNTED:
Status = Ext2IsVolumeMounted(IrpContext);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
Ext2FreeIrpContext(IrpContext);
}
return Status;
}
NTSTATUS
Ext2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT MainDeviceObject;
BOOLEAN GlobalDataResourceAcquired = FALSE;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
PDEVICE_OBJECT TargetDeviceObject;
NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME;
PDEVICE_OBJECT VolumeDeviceObject = NULL;
PEXT2_VCB Vcb;
PEXT2_SUPER_BLOCK Ext2Sb = NULL;
__try
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
MainDeviceObject = IrpContext->DeviceObject;
//
// Make sure we can wait.
//
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
//
// This request is only allowed on the main device object
//
if (MainDeviceObject != gExt2Global->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
ExAcquireResourceExclusiveLite(
&(gExt2Global->Resource),
TRUE );
GlobalDataResourceAcquired = TRUE;
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
TargetDeviceObject =
IoStackLocation->Parameters.MountVolume.DeviceObject;
Ext2Sb = Ext2LoadSuper(TargetDeviceObject);
if (Ext2Sb)
{
if (Ext2Sb->s_magic == EXT2_SUPER_MAGIC)
{
Ext2DbgPrint(D_FSCTL, "Win2fs: Ext2fs found.\n");
Status = STATUS_SUCCESS;
}
}
if (!NT_SUCCESS(Status))
{
__leave;
}
Status = IoCreateDevice(
MainDeviceObject->DriverObject,
sizeof(EXT2_VCB),
NULL,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
&VolumeDeviceObject );
if (!NT_SUCCESS(Status))
{
__leave;
}
VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
if (TargetDeviceObject->AlignmentRequirement >
VolumeDeviceObject->AlignmentRequirement) {
VolumeDeviceObject->AlignmentRequirement =
TargetDeviceObject->AlignmentRequirement;
}
(IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject =
VolumeDeviceObject;
Vcb = (PEXT2_VCB) VolumeDeviceObject->DeviceExtension;
Status = Ext2InitializeVcb(IrpContext, Vcb, Ext2Sb, TargetDeviceObject,
VolumeDeviceObject, IoStackLocation->Parameters.MountVolume.Vpb);
}
__finally
{
if (GlobalDataResourceAcquired)
{
ExReleaseResourceForThreadLite(
&gExt2Global->Resource,
ExGetCurrentResourceThread() );
}
if (!NT_SUCCESS(Status))
{
if (Ext2Sb)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -