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

📄 block.c

📁 FSD file system driver
💻 C
字号:
/* 
 * FFS File System Driver for Windows
 *
 * block.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 */

typedef struct _FFS_RW_CONTEXT {
	PIRP        MasterIrp;
	KEVENT      Event;
	BOOLEAN     Wait;
	ULONG       Blocks;
	ULONG       Length;
} FFS_RW_CONTEXT, *PFFS_RW_CONTEXT;


NTSTATUS
FFSReadWriteBlockSyncCompletionRoutine(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP           Irp,
	IN PVOID          Context);

NTSTATUS
FFSReadWriteBlockAsyncCompletionRoutine(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP           Irp,
	IN PVOID          Context);


NTSTATUS
FFSMediaEjectControlCompletion(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP           Irp,
	IN PVOID          Contxt);


#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSLockUserBuffer)
#pragma alloc_text(PAGE, FFSGetUserBuffer)
#pragma alloc_text(PAGE, FFSReadSync)
#pragma alloc_text(PAGE, FFSReadDisk)
#pragma alloc_text(PAGE, FFSDiskIoControl)
#pragma alloc_text(PAGE, FFSReadWriteBlocks)
#pragma alloc_text(PAGE, FFSMediaEjectControl)
#pragma alloc_text(PAGE, FFSDiskShutDown)
#endif


NTSTATUS
FFSLockUserBuffer(
	IN PIRP             Irp,
	IN ULONG            Length,
	IN LOCK_OPERATION   Operation)
{
	NTSTATUS Status;

	ASSERT(Irp != NULL);

	if (Irp->MdlAddress != NULL)
	{
		return STATUS_SUCCESS;
	}

	IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);

	if (Irp->MdlAddress == NULL)
	{
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	__try
	{
		MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);

		Status = STATUS_SUCCESS;
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		IoFreeMdl(Irp->MdlAddress);

		Irp->MdlAddress = NULL;

		FFSBreakPoint();

		Status = STATUS_INVALID_USER_BUFFER;
	}

	return Status;
}


PVOID
FFSGetUserBuffer(
	IN PIRP Irp)
{
	ASSERT(Irp != NULL);

	if (Irp->MdlAddress)
	{
#if (_WIN32_WINNT >= 0x0500)
		return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
#else
		return MmGetSystemAddressForMdl(Irp->MdlAddress);
#endif
	}
	else
	{
		return Irp->UserBuffer;
	}
}


NTSTATUS
FFSReadWriteBlockSyncCompletionRoutine(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP           Irp,
	IN PVOID          Context)
{
	PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context;

	if (!NT_SUCCESS(Irp->IoStatus.Status))
	{

		pContext->MasterIrp->IoStatus = Irp->IoStatus;
	}

	IoFreeMdl(Irp->MdlAddress);
	IoFreeIrp(Irp);

	if (InterlockedDecrement(&pContext->Blocks) == 0)
	{
		pContext->MasterIrp->IoStatus.Information = 0;

		if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
		{
			pContext->MasterIrp->IoStatus.Information =
				pContext->Length;
		}

		KeSetEvent(&pContext->Event, 0, FALSE);
	}

	UNREFERENCED_PARAMETER(DeviceObject);

	return STATUS_MORE_PROCESSING_REQUIRED;
}

NTSTATUS
FFSReadWriteBlockAsyncCompletionRoutine(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp,
	IN PVOID Context)
{
	PFFS_RW_CONTEXT pContext = (PFFS_RW_CONTEXT)Context;

	if (!NT_SUCCESS(Irp->IoStatus.Status))
	{
		pContext->MasterIrp->IoStatus = Irp->IoStatus;
	}

	if (InterlockedDecrement(&pContext->Blocks) == 0)
	{
		pContext->MasterIrp->IoStatus.Information = 0;

		if (NT_SUCCESS(pContext->MasterIrp->IoStatus.Status))
		{
			pContext->MasterIrp->IoStatus.Information =
				pContext->Length;
		}

		IoMarkIrpPending(pContext->MasterIrp);

		ExFreePool(pContext);
	}

	UNREFERENCED_PARAMETER(DeviceObject);

	return STATUS_SUCCESS;

}

NTSTATUS
FFSReadWriteBlocks(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN PFFS_BDL         FFSBDL,
	IN ULONG            Length,
	IN ULONG            Count,
	IN BOOLEAN          bVerify)
{
	PMDL                Mdl;
	PIRP                Irp;
	PIRP                MasterIrp = IrpContext->Irp;
	PIO_STACK_LOCATION  IrpSp;
	NTSTATUS            Status = STATUS_SUCCESS;
	PFFS_RW_CONTEXT     pContext = NULL;
	ULONG               i;
	BOOLEAN             bBugCheck = FALSE;

	ASSERT(MasterIrp);

	__try
	{

		pContext = ExAllocatePool(NonPagedPool, sizeof(FFS_RW_CONTEXT));

		if (!pContext)
		{
			Status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		RtlZeroMemory(pContext, sizeof(FFS_RW_CONTEXT));

		pContext->Wait = IrpContext->IsSynchronous;
		pContext->MasterIrp = MasterIrp;
		pContext->Blocks = Count;
		pContext->Length = 0;

		if (pContext->Wait)
		{
			KeInitializeEvent(&(pContext->Event), NotificationEvent, FALSE);
		}

		for (i = 0; i < Count; i++)
		{

			Irp = IoMakeAssociatedIrp(MasterIrp,
					(CCHAR)(Vcb->TargetDeviceObject->StackSize + 1));
			if (!Irp)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				__leave;
			}

			Mdl = IoAllocateMdl((PCHAR)MasterIrp->UserBuffer +
					FFSBDL[i].Offset,
					FFSBDL[i].Length,
					FALSE,
					FALSE,
					Irp);

			if (!Mdl)
			{
				Status = STATUS_INSUFFICIENT_RESOURCES;
				__leave;
			}

			IoBuildPartialMdl(MasterIrp->MdlAddress,
					Mdl,
					(PCHAR)MasterIrp->UserBuffer + FFSBDL[i].Offset,
					FFSBDL[i].Length);

			IoSetNextIrpStackLocation(Irp);
			IrpSp = IoGetCurrentIrpStackLocation(Irp);


			IrpSp->MajorFunction = IrpContext->MajorFunction;
			IrpSp->Parameters.Read.Length = FFSBDL[i].Length;
			IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba;

			IoSetCompletionRoutine(Irp,
					IrpContext->IsSynchronous ?
					&FFSReadWriteBlockSyncCompletionRoutine :
					&FFSReadWriteBlockAsyncCompletionRoutine,
					(PVOID) pContext,
					TRUE,
					TRUE,
					TRUE);

			IrpSp = IoGetNextIrpStackLocation(Irp);

			IrpSp->MajorFunction = IrpContext->MajorFunction;
			IrpSp->Parameters.Read.Length = FFSBDL[i].Length;
			IrpSp->Parameters.Read.ByteOffset.QuadPart = FFSBDL[i].Lba;

			if (bVerify)
			{
				SetFlag(IrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME);
			}

			FFSBDL[i].Irp = Irp;
		}

		MasterIrp->AssociatedIrp.IrpCount = Count;

		if (IrpContext->IsSynchronous)
		{
			MasterIrp->AssociatedIrp.IrpCount += 1;
		}

		pContext->Length = Length;

		bBugCheck = TRUE;

		for (i = 0; i < Count; i++)
		{
			Status = IoCallDriver(Vcb->TargetDeviceObject,
					FFSBDL[i].Irp);
		}

		if (IrpContext->IsSynchronous)
		{
			KeWaitForSingleObject(&(pContext->Event),
					Executive, KernelMode, FALSE, NULL);

			KeClearEvent(&(pContext->Event));
		}
	}

	__finally
	{
		if (IrpContext->IsSynchronous)
		{
			if (MasterIrp)
				Status = MasterIrp->IoStatus.Status;

			if (pContext)
				ExFreePool(pContext);

		}
		else
		{
			IrpContext->Irp = NULL;
			Status = STATUS_PENDING;
		}

		if (AbnormalTermination())
		{
			if (bBugCheck)
			{
				FFSBugCheck(FFS_BUGCHK_BLOCK, 0, 0, 0);
			}

			for (i = 0; i < Count; i++)
			{
				if (FFSBDL[i].Irp != NULL)
				{
					if (FFSBDL[i].Irp->MdlAddress != NULL)
					{
						IoFreeMdl(FFSBDL[i].Irp->MdlAddress);
					}

					IoFreeIrp(FFSBDL[i].Irp);
				}
			}
		}
	}

	return Status;
}


NTSTATUS
FFSReadSync(
	IN PFFS_VCB         Vcb,
	IN ULONGLONG        Offset,
	IN ULONG            Length,
	OUT PVOID           Buffer,
	IN BOOLEAN          bVerify)
{
	KEVENT          Event;
	PIRP            Irp;
	IO_STATUS_BLOCK IoStatus;
	NTSTATUS        Status;


	ASSERT(Vcb != NULL);
	ASSERT(Vcb->TargetDeviceObject != NULL);
	ASSERT(Buffer != NULL);

	KeInitializeEvent(&Event, NotificationEvent, FALSE);

	Irp = IoBuildSynchronousFsdRequest(
			IRP_MJ_READ,
			Vcb->TargetDeviceObject,
			Buffer,
			Length,
			(PLARGE_INTEGER)(&Offset),
			&Event,
			&IoStatus);

	if (!Irp)
	{
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	if (bVerify)
	{
		SetFlag(IoGetNextIrpStackLocation(Irp)->Flags, 
				SL_OVERRIDE_VERIFY_VOLUME);
	}

	Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

	if (Status == STATUS_PENDING)
	{
		KeWaitForSingleObject(
				&Event,
				Suspended,
				KernelMode,
				FALSE,
				NULL);

		Status = IoStatus.Status;
	}

	return Status;
}


NTSTATUS
FFSReadDisk(
	IN PFFS_VCB    Vcb,
	IN ULONGLONG   Offset,
	IN ULONG       Size,
	IN PVOID       Buffer,
	IN BOOLEAN     bVerify)
{
	NTSTATUS    Status;
	PUCHAR      Buf;
	ULONG       Length;
	ULONGLONG   Lba;

	Lba = Offset & (~((ULONGLONG)SECTOR_SIZE - 1));
	Length = (ULONG)(Size + Offset + SECTOR_SIZE - 1 - Lba) &
		(~((ULONG)SECTOR_SIZE - 1));

	Buf = ExAllocatePool(PagedPool, Length);
	if (!Buf)
	{
		FFSPrint((DBG_ERROR, "FFSReadDisk: no enough memory.\n"));
		Status = STATUS_INSUFFICIENT_RESOURCES;

		goto errorout;
	}

	Status = FFSReadSync(Vcb, 
			Lba,
			Length,
			Buf,
			FALSE);

	if (!NT_SUCCESS(Status))
	{
		FFSPrint((DBG_ERROR, "FFSReadDisk: Read Block Device error.\n"));

		goto errorout;
	}

	RtlCopyMemory(Buffer, &Buf[Offset - Lba], Size);

errorout:

	if (Buf)
		ExFreePool(Buf);

	return Status;
}


NTSTATUS 
FFSDiskIoControl(
	IN PDEVICE_OBJECT   DeviceObject,
	IN ULONG            IoctlCode,
	IN PVOID            InputBuffer,
	IN ULONG            InputBufferSize,
	IN OUT PVOID        OutputBuffer,
	IN OUT PULONG       OutputBufferSize)
{
	ULONG           OutBufferSize = 0;
	KEVENT          Event;
	PIRP            Irp;
	IO_STATUS_BLOCK IoStatus;
	NTSTATUS        Status;

	ASSERT(DeviceObject != NULL);

	if (OutputBufferSize)
	{
		OutBufferSize = *OutputBufferSize;
	}

	KeInitializeEvent(&Event, NotificationEvent, FALSE);

	Irp = IoBuildDeviceIoControlRequest(
			IoctlCode,
			DeviceObject,
			InputBuffer,
			InputBufferSize,
			OutputBuffer,
			OutBufferSize,
			FALSE,
			&Event,
			&IoStatus);

	if (Irp == NULL)
	{
		FFSPrint((DBG_ERROR, "FFSDiskIoControl: Building IRQ error!\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	Status = IoCallDriver(DeviceObject, Irp);

	if (Status == STATUS_PENDING)
	{
		KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
		Status = IoStatus.Status;
	}

	if (OutputBufferSize)
	{
		*OutputBufferSize = IoStatus.Information;
	}

	return Status;
}


NTSTATUS
FFSMediaEjectControlCompletion(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP           Irp,
	IN PVOID          Contxt)
{
	PKEVENT Event = (PKEVENT)Contxt;

	KeSetEvent(Event, 0, FALSE);

	UNREFERENCED_PARAMETER(DeviceObject);

	return STATUS_SUCCESS;
}


VOID
FFSMediaEjectControl(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN BOOLEAN          bPrevent)
{
	PIRP                    Irp;
	KEVENT                  Event;
	NTSTATUS                Status;
	PREVENT_MEDIA_REMOVAL   Prevent;
	IO_STATUS_BLOCK         IoStatus;


	ExAcquireResourceExclusiveLite(
			&Vcb->MainResource,
			TRUE);

	if (bPrevent != IsFlagOn(Vcb->Flags, VCB_REMOVAL_PREVENTED))
	{
		if (bPrevent)
		{
			SetFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
		}
		else
		{
			ClearFlag(Vcb->Flags, VCB_REMOVAL_PREVENTED);
		}
	}

	ExReleaseResourceForThreadLite(
			&Vcb->MainResource,
			ExGetCurrentResourceThread());

	Prevent.PreventMediaRemoval = bPrevent;

	KeInitializeEvent(&Event, NotificationEvent, FALSE);

	Irp = IoBuildDeviceIoControlRequest(IOCTL_DISK_MEDIA_REMOVAL,
			Vcb->TargetDeviceObject,
			&Prevent,
			sizeof(PREVENT_MEDIA_REMOVAL),
			NULL,
			0,
			FALSE,
			NULL,
			&IoStatus);

	if (Irp != NULL)
	{
		IoSetCompletionRoutine(Irp,
				FFSMediaEjectControlCompletion,
				&Event,
				TRUE,
				TRUE,
				TRUE);

		Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

		if (Status == STATUS_PENDING)
		{
			Status = KeWaitForSingleObject(&Event,
					Executive,
					KernelMode,
					FALSE,
					NULL);
		}
	}
}


NTSTATUS
FFSDiskShutDown(
	PFFS_VCB Vcb)
{
	PIRP                Irp;
	KEVENT              Event;

	NTSTATUS            Status;
	IO_STATUS_BLOCK     IoStatus;

	KeInitializeEvent(&Event, NotificationEvent, FALSE);

	Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
			Vcb->TargetDeviceObject,
			NULL,
			0,
			NULL,
			&Event,
			&IoStatus);

	if (Irp)
	{
		Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

		if (Status == STATUS_PENDING)
		{
			KeWaitForSingleObject(&Event,
					Executive,
					KernelMode,
					FALSE,
					NULL);

			Status = IoStatus.Status;
		}
	}
	else
	{
		Status = IoStatus.Status;
	}

	return Status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -