⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsctl.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
 * 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 + -