📄 fsctl.c
字号:
/*
* FFS File System Driver for Windows
*
* fsctl.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
BOOLEAN
FFSIsMediaWriteProtected (
IN PFFS_IRP_CONTEXT IrpContext,
IN PDEVICE_OBJECT TargetDevice);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSSetVpbFlag)
#pragma alloc_text(PAGE, FFSClearVpbFlag)
#pragma alloc_text(PAGE, FFSGetPartition)
#pragma alloc_text(PAGE, FFSLoadDiskLabel)
#pragma alloc_text(PAGE, FFSIsHandleCountZero)
#pragma alloc_text(PAGE, FFSLockVcb)
#pragma alloc_text(PAGE, FFSLockVolume)
#pragma alloc_text(PAGE, FFSUnlockVcb)
#pragma alloc_text(PAGE, FFSUnlockVolume)
#pragma alloc_text(PAGE, FFSAllowExtendedDasdIo)
#pragma alloc_text(PAGE, FFSUserFsRequest)
#pragma alloc_text(PAGE, FFSIsMediaWriteProtected)
#pragma alloc_text(PAGE, FFSMountVolume)
#pragma alloc_text(PAGE, FFSCheckDismount)
#pragma alloc_text(PAGE, FFSPurgeVolume)
#pragma alloc_text(PAGE, FFSPurgeFile)
#pragma alloc_text(PAGE, FFSDismountVolume)
#pragma alloc_text(PAGE, FFSIsVolumeMounted)
#pragma alloc_text(PAGE, FFSVerifyVolume)
#pragma alloc_text(PAGE, FFSFileSystemControl)
#endif
VOID
FFSSetVpbFlag(
IN PVPB Vpb,
IN USHORT Flag)
{
KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql);
Vpb->Flags |= Flag;
IoReleaseVpbSpinLock(OldIrql);
}
VOID
FFSClearVpbFlag(
IN PVPB Vpb,
IN USHORT Flag)
{
KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql);
Vpb->Flags &= ~Flag;
IoReleaseVpbSpinLock(OldIrql);
}
NTSTATUS
FFSGetPartition(
IN PDEVICE_OBJECT DeviceObject,
OUT ULONGLONG *StartOffset)
{
CHAR Buffer[2048];
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
KEVENT Event;
NTSTATUS Status;
PARTITION_INFORMATION *PartInfo;
if (IsFlagOn(DeviceObject->Characteristics, FILE_FLOPPY_DISKETTE))
{
*StartOffset = 0;
return STATUS_SUCCESS;
}
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(
IOCTL_DISK_GET_PARTITION_INFO,
DeviceObject,
NULL,
0,
Buffer,
2048,
FALSE,
&Event,
&IoStatus);
if (!Irp)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoCallDriver(DeviceObject, Irp);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
if (!NT_SUCCESS(Status))
{
return Status;
}
PartInfo = (PARTITION_INFORMATION *)Buffer;
*StartOffset = PartInfo->StartingOffset.QuadPart;
return Status;
}
NTSTATUS
FFSLoadDiskLabel(
PDEVICE_OBJECT DeviceObject,
IN PFFS_VCB Vcb)
{
NTSTATUS Status;
PFFS_SUPER_BLOCK FFSSb;
PDISKLABEL Disklabel;
int i;
int RootFS_VERSION;
ULONGLONG StartOffset = 0;
ULONGLONG FSOffset = 0;
ULONGLONG FSRootOffset = 0;
Disklabel = (PDISKLABEL)ExAllocatePool(PagedPool, sizeof(DISKLABEL));
FFSReadDisk(Vcb, (LABELSECTOR * SECTOR_SIZE + LABELOFFSET), sizeof(DISKLABEL), (PVOID)Disklabel, FALSE);
if (Disklabel->d_magic == DISKMAGIC)
{
KdPrint(("FFSLoadDiskLabel() Disklabel magic ok\n"));
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_UNRECOGNIZED_VOLUME;
return Status;
}
Status = FFSGetPartition(DeviceObject, &StartOffset);
if (!NT_SUCCESS(Status))
{
KdPrint(("FFSLoadDiskLabel() Slice info failed, Status %u\n", Status));
return Status;
}
KdPrint(("FFSLoadDiskLabel() Selected BSD Partition : %d, StartOffset : %x\n", FFSGlobal->PartitionNumber, StartOffset));
for (i = 0; i < MAXPARTITIONS; i++)
{
if (Disklabel->d_partitions[i].p_fstype == FS_BSDFFS)
{
/* Important */
FSOffset = Disklabel->d_partitions[i].p_offset;
FSOffset = FSOffset * SECTOR_SIZE;
FSOffset = FSOffset - StartOffset;
FFSGlobal->FSOffset[i] = FSOffset;
/* Important */
KdPrint(("FFSLoadDiskLabel() Partition %d, FS_BSDFFS, %x\n", i, FFSGlobal->FSOffset[i]));
if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS1)) &&
(FFSSb->fs_magic == FS_UFS1_MAGIC))
{
FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Partition %d of FFSv1 file system is found.\n", i));
if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
{
FFSGlobal->RootPartition = i;
FSRootOffset = FSOffset;
RootFS_VERSION = 1;
}
FS_VERSION = 1;
if (i == (int)FFSGlobal->PartitionNumber)
{
Vcb->ffs_super_block = FFSSb;
}
Status = STATUS_SUCCESS;
}
else if ((FFSSb = FFSLoadSuper(Vcb, FALSE, FSOffset + SBLOCK_UFS2)) &&
(FFSSb->fs_magic == FS_UFS2_MAGIC))
{
FFSPrint((DBG_VITAL, "FFSLoadDiskLabel() Partition %d of FFSv2 file system is found.\n", i));
if ((FFSSb->fs_fsmnt[0] == '/') && (FFSSb->fs_fsmnt[1] == '\0'))
{
FFSGlobal->RootPartition = i;
FSRootOffset = FSOffset;
RootFS_VERSION = 2;
}
FS_VERSION = 2;
if (i == (int)FFSGlobal->PartitionNumber)
{
Vcb->ffs_super_block = FFSSb;
}
Status = STATUS_SUCCESS;
}
}
else if (i == (int)FFSGlobal->PartitionNumber)
{
/* 急琶等 BSD 颇萍记捞 叼胶农俊 绝阑 版快 Root 颇萍记栏肺 措眉 */
if (RootFS_VERSION == 1)
{
FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS1);
Vcb->ffs_super_block = FFSSb;
FFSGlobal->PartitionNumber = FFSGlobal->RootPartition;
}
else
{
FFSSb = FFSLoadSuper(Vcb, FALSE, FSRootOffset + SBLOCK_UFS2);
Vcb->ffs_super_block = FFSSb;
FFSGlobal->PartitionNumber = FFSGlobal->RootPartition;
}
}
}
if (FFSSb == NULL)
Status = STATUS_UNRECOGNIZED_VOLUME;
return Status;
}
BOOLEAN
FFSIsHandleCountZero(
IN PFFS_VCB Vcb)
{
PFFS_FCB Fcb;
PLIST_ENTRY List;
for(List = Vcb->FcbList.Flink;
List != &Vcb->FcbList;
List = List->Flink)
{
Fcb = CONTAINING_RECORD(List, FFS_FCB, Next);
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
FFSPrint((DBG_INFO, "FFSIsHandleCountZero: Inode:%xh File:%S OpenHandleCount=%xh\n",
Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, Fcb->OpenHandleCount));
if (Fcb->OpenHandleCount)
{
return FALSE;
}
}
return TRUE;
}
NTSTATUS
FFSLockVcb(
IN PFFS_VCB Vcb,
IN PFILE_OBJECT FileObject)
{
NTSTATUS Status;
__try
{
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
{
FFSPrint((DBG_INFO, "FFSLockVolume: Volume is already locked.\n"));
Status = STATUS_ACCESS_DENIED;
__leave;
}
if (Vcb->OpenFileHandleCount > (ULONG)(FileObject ? 1 : 0))
{
FFSPrint((DBG_INFO, "FFSLockVcb: There are still opened files.\n"));
Status = STATUS_ACCESS_DENIED;
__leave;
}
if (!FFSIsHandleCountZero(Vcb))
{
FFSPrint((DBG_INFO, "FFSLockVcb: Thare are still opened files.\n"));
Status = STATUS_ACCESS_DENIED;
__leave;
}
SetFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
FFSSetVpbFlag(Vcb->Vpb, VPB_LOCKED);
Vcb->LockFile = FileObject;
FFSPrint((DBG_INFO, "FFSLockVcb: Volume locked.\n"));
Status = STATUS_SUCCESS;
}
__finally
{
// Nothing
}
return Status;
}
NTSTATUS
FFSLockVolume(
IN PFFS_IRP_CONTEXT IrpContext)
{
PIO_STACK_LOCATION IrpSp;
PDEVICE_OBJECT DeviceObject;
PFFS_VCB Vcb;
NTSTATUS Status;
BOOLEAN VcbResourceAcquired = FALSE;
__try
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Status = STATUS_UNSUCCESSFUL;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
#if (_WIN32_WINNT >= 0x0500)
CcWaitForCurrentLazyWriterActivity();
#endif
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE);
VcbResourceAcquired = TRUE;
Status = FFSLockVcb(Vcb, IrpSp->FileObject);
}
__finally
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
NTSTATUS
FFSUnlockVcb(
IN PFFS_VCB Vcb,
IN PFILE_OBJECT FileObject)
{
NTSTATUS Status;
__try
{
if (FileObject && FileObject->FsContext != Vcb)
{
Status = STATUS_NOT_LOCKED;
__leave;
}
if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED))
{
FFSPrint((DBG_ERROR, ": FFSUnlockVcb: Volume is not locked.\n"));
Status = STATUS_NOT_LOCKED;
__leave;
}
if (Vcb->LockFile == FileObject)
{
ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
FFSPrint((DBG_INFO, "FFSUnlockVcb: Volume unlocked.\n"));
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_NOT_LOCKED;
}
}
__finally
{
// Nothing
}
return Status;
}
NTSTATUS
FFSUnlockVolume(
IN PFFS_IRP_CONTEXT IrpContext)
{
PIO_STACK_LOCATION IrpSp;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
PFFS_VCB Vcb;
BOOLEAN VcbResourceAcquired = FALSE;
__try
{
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
ExAcquireResourceExclusiveLite(
&Vcb->MainResource,
TRUE);
VcbResourceAcquired = TRUE;
Status = FFSUnlockVcb(Vcb, IrpSp->FileObject);
}
__finally
{
if (VcbResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
FFSCompleteIrpContext(IrpContext, Status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -