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

📄 write.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
 * FFS File System Driver for Windows
 *
 * write.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_FLPFLUSH_CONTEXT {

	PFFS_VCB     Vcb;
	PFFS_FCB     Fcb;
	PFILE_OBJECT FileObject;

	KDPC         Dpc;
	KTIMER       Timer;
	WORK_QUEUE_ITEM Item;

} FFS_FLPFLUSH_CONTEXT, *PFFS_FLPFLUSH_CONTEXT;

VOID
FFSFloppyFlush(
	IN PVOID Parameter);

VOID
FFSFloppyFlushDpc(
	IN PKDPC Dpc,
	IN PVOID DeferredContext,
	IN PVOID SystemArgument1,
	IN PVOID SystemArgument2);



NTSTATUS
FFSWriteComplete(
	IN PFFS_IRP_CONTEXT IrpContext);

NTSTATUS
FFSWriteFile(
	IN PFFS_IRP_CONTEXT IrpContext);

NTSTATUS
FFSWriteVolume(
	IN PFFS_IRP_CONTEXT IrpContext);

VOID
FFSDeferWrite(
	IN   PFFS_IRP_CONTEXT,
	PIRP Irp);

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSFloppyFlush)
#pragma alloc_text(PAGE, FFSStartFloppyFlushDpc)
#pragma alloc_text(PAGE, FFSZeroHoles)
#pragma alloc_text(PAGE, FFSWrite)
#pragma alloc_text(PAGE, FFSWriteVolume)
#pragma alloc_text(PAGE, FFSv1WriteInode)
#pragma alloc_text(PAGE, FFSWriteFile)
#pragma alloc_text(PAGE, FFSWriteComplete)
#endif


VOID
FFSFloppyFlush(
	IN PVOID Parameter)
{
	PFFS_FLPFLUSH_CONTEXT Context;
	PFILE_OBJECT          FileObject;
	PFFS_FCB              Fcb;
	PFFS_VCB              Vcb;

	Context = (PFFS_FLPFLUSH_CONTEXT) Parameter;
	FileObject = Context->FileObject;
	Fcb = Context->Fcb;
	Vcb = Context->Vcb;

	FFSPrint((DBG_USER, "FFSFloppyFlushing ...\n"));

	IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);

	if (Vcb)
	{
		ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
		ExReleaseResource(&Vcb->PagingIoResource);

		CcFlushCache(&(Vcb->SectionObject), NULL, 0, NULL);
	}

	if (FileObject)
	{
		ASSERT(Fcb == (PFFS_FCB)FileObject->FsContext);

		ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE);
		ExReleaseResource(&Fcb->PagingIoResource);

		CcFlushCache(&(Fcb->SectionObject), NULL, 0, NULL);

		ObDereferenceObject(FileObject);
	}

	IoSetTopLevelIrp(NULL);

	ExFreePool(Parameter);
}


VOID
FFSFloppyFlushDpc(
	IN PKDPC Dpc,
	IN PVOID DeferredContext,
	IN PVOID SystemArgument1,
	IN PVOID SystemArgument2)
{
	PFFS_FLPFLUSH_CONTEXT Context;

	Context = (PFFS_FLPFLUSH_CONTEXT)DeferredContext;

	FFSPrint((DBG_USER, "FFSFloppyFlushDpc is to be started...\n"));

	ExInitializeWorkItem(&Context->Item,
			FFSFloppyFlush,
			Context);

	ExQueueWorkItem(&Context->Item, CriticalWorkQueue);
}


VOID
FFSStartFloppyFlushDpc(
	PFFS_VCB     Vcb,
	PFFS_FCB     Fcb,
	PFILE_OBJECT FileObject)
{
	LARGE_INTEGER          OneSecond;
	PFFS_FLPFLUSH_CONTEXT Context;

	ASSERT(IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK));

	Context = ExAllocatePool(NonPagedPool, sizeof(PFFS_FLPFLUSH_CONTEXT));

	if (!Context)
	{
		FFSBreakPoint();
		return;
	}

	KeInitializeTimer(&Context->Timer);

	KeInitializeDpc(&Context->Dpc,
			FFSFloppyFlushDpc,
			Context);

	Context->Vcb = Vcb;
	Context->Fcb = Fcb;
	Context->FileObject = FileObject;

	if (FileObject)
	{
		ObReferenceObject(FileObject);
	}

	OneSecond.QuadPart = (LONGLONG) - 1 * 1000 * 1000 * 10;
	KeSetTimer(&Context->Timer,
			OneSecond,
			&Context->Dpc);
}


BOOLEAN
FFSZeroHoles(
	IN PFFS_IRP_CONTEXT IrpContext,
	IN PFFS_VCB         Vcb,
	IN PFILE_OBJECT     FileObject,
	IN LONGLONG         Offset,
	IN LONGLONG         Count)
{
	LARGE_INTEGER StartAddr = {0, 0};
	LARGE_INTEGER EndAddr = {0, 0};

	StartAddr.QuadPart = (Offset + (SECTOR_SIZE - 1)) &
		~((LONGLONG)SECTOR_SIZE - 1);

	EndAddr.QuadPart = (Offset + Count + (SECTOR_SIZE - 1)) &
		~((LONGLONG)SECTOR_SIZE - 1);

	if (StartAddr.QuadPart < EndAddr.QuadPart)
	{
		return CcZeroData(FileObject,
				&StartAddr,
				&EndAddr,
				IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
	}

	return TRUE;
}


VOID
FFSDeferWrite(
	IN PFFS_IRP_CONTEXT IrpContext,
	PIRP Irp)
{
	ASSERT(IrpContext->Irp == Irp);

	FFSQueueRequest(IrpContext);
}


NTSTATUS
FFSWriteVolume(
	IN PFFS_IRP_CONTEXT IrpContext)
{
	NTSTATUS            Status = STATUS_UNSUCCESSFUL;

	PFFS_VCB            Vcb;
	PFFS_CCB            Ccb;
	PFFS_FCBVCB         FcbOrVcb;
	PFILE_OBJECT        FileObject;

	PDEVICE_OBJECT      DeviceObject;

	PIRP                Irp;
	PIO_STACK_LOCATION  IoStackLocation;

	ULONG               Length;
	LARGE_INTEGER       ByteOffset;

	BOOLEAN             PagingIo;
	BOOLEAN             Nocache;
	BOOLEAN             SynchronousIo;
	BOOLEAN             MainResourceAcquired = FALSE;
	BOOLEAN             PagingIoResourceAcquired = FALSE;

	BOOLEAN             bDeferred = FALSE;

	PUCHAR              Buffer;

	__try
	{
		ASSERT(IrpContext);

		ASSERT((IrpContext->Identifier.Type == FFSICX) &&
				(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));

		DeviceObject = IrpContext->DeviceObject;

		Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;

		ASSERT(Vcb != NULL);

		ASSERT((Vcb->Identifier.Type == FFSVCB) &&
				(Vcb->Identifier.Size == sizeof(FFS_VCB)));

		FileObject = IrpContext->FileObject;

		FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;

		ASSERT(FcbOrVcb);

		if (!(FcbOrVcb->Identifier.Type == FFSVCB && (PVOID)FcbOrVcb == (PVOID)Vcb))
		{
			Status = STATUS_INVALID_DEVICE_REQUEST;
			__leave;
		}

		Ccb = (PFFS_CCB)FileObject->FsContext2;

		Irp = IrpContext->Irp;

		IoStackLocation = IoGetCurrentIrpStackLocation(Irp);

		Length = IoStackLocation->Parameters.Write.Length;
		ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;

		PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
		Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
		SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);

		FFSPrint((DBG_INFO, "FFSWriteVolume: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
					ByteOffset.QuadPart, Length, PagingIo, Nocache));

		if (Length == 0)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_SUCCESS;
			__leave;
		}

		// For the case of "Direct Access Storage Device", we
		// need flush/purge the cache

		if (Ccb != NULL)
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			Status = FFSPurgeVolume(Vcb, TRUE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;

			if(!IsFlagOn(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO))
			{
				if (ByteOffset.QuadPart + Length > Vcb->Header.FileSize.QuadPart)
				{
					Length = (ULONG)(Vcb->Header.FileSize.QuadPart - ByteOffset.QuadPart);
				}
			}

			{
				FFS_BDL BlockArray;

				if ((ByteOffset.LowPart & (SECTOR_SIZE - 1)) ||
						(Length & (SECTOR_SIZE - 1)))
				{
					Status = STATUS_INVALID_PARAMETER;
					__leave;
				}

				Status = FFSLockUserBuffer(
							IrpContext->Irp,
							Length,
							IoReadAccess);

				if (!NT_SUCCESS(Status))
				{
					__leave;
				}

				BlockArray.Irp = NULL;
				BlockArray.Lba = ByteOffset.QuadPart;;
				BlockArray.Offset = 0;
				BlockArray.Length = Length;

				Status = FFSReadWriteBlocks(IrpContext,
							Vcb,
							&BlockArray,
							Length,
							1,
							FALSE);
				Irp = IrpContext->Irp;

				__leave;
			}
		}                    

		if (Nocache &&
				(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
				 Length & (SECTOR_SIZE - 1)))
		{
			Status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC))
		{
			ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
			Status = STATUS_PENDING;
			__leave;
		}

		if (ByteOffset.QuadPart >=
				Vcb->PartitionInformation.PartitionLength.QuadPart)
		{
			Irp->IoStatus.Information = 0;
			Status = STATUS_END_OF_FILE;
			__leave;
		}

#if FALSE

		if (!Nocache)
		{
			BOOLEAN bAgain = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);
			BOOLEAN bWait  = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
			BOOLEAN bQueue = IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED);

			if (!CcCanIWrite(
						FileObject,
						Length,
						(bWait && bQueue),
						bAgain))
			{
				SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DEFERRED);

				CcDeferWrite(FileObject,
						(PCC_POST_DEFERRED_WRITE)FFSDeferWrite,
						IrpContext,
						Irp,
						Length,
						bAgain);

				bDeferred = TRUE;

				FFSBreakPoint();

				Status = STATUS_PENDING;

				__leave;
			}
		}

#endif

		if (Nocache && !PagingIo && (Vcb->SectionObject.DataSectionObject != NULL)) 
		{
			ExAcquireResourceExclusive(&Vcb->MainResource, TRUE);
			MainResourceAcquired = TRUE;

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcFlushCache(&(Vcb->SectionObject),
					&ByteOffset,
					Length,
					&(Irp->IoStatus));

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

			ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
			ExReleaseResource(&Vcb->PagingIoResource);

			CcPurgeCacheSection(&(Vcb->SectionObject),
					(PLARGE_INTEGER)&(ByteOffset),
					Length,
					FALSE);

			ExReleaseResource(&Vcb->MainResource);
			MainResourceAcquired = FALSE;
		}

		if (!PagingIo)
		{
			if (!ExAcquireResourceExclusiveLite(
						&Vcb->MainResource,
						IrpContext->IsSynchronous))
			{
				Status = STATUS_PENDING;
				__leave;
			}

			MainResourceAcquired = TRUE;
		}
		else
		{
			/*
			ULONG ResShCnt, ResExCnt; 
			ResShCnt = ExIsResourceAcquiredSharedLite(&Vcb->PagingIoResource);
			ResExCnt = ExIsResourceAcquiredExclusiveLite(&Vcb->PagingIoResource);

			FFSPrint((DBG_USER, "PagingIoRes: %xh:%xh Synchronous=%xh\n", ResShCnt, ResExCnt, IrpContext->IsSynchronous));
			*/

			if (Ccb)
			{
				if (!ExAcquireResourceSharedLite(
							&Vcb->PagingIoResource,
							IrpContext->IsSynchronous))
				{
					Status = STATUS_PENDING;
					__leave;
				}

				PagingIoResourceAcquired = TRUE;
			}
		}

		if (!Nocache)
		{
			if ((ByteOffset.QuadPart + Length) >
					Vcb->PartitionInformation.PartitionLength.QuadPart
			)
			{
				Length = (ULONG) (
						Vcb->PartitionInformation.PartitionLength.QuadPart -
						ByteOffset.QuadPart);

				Length &= ~((ULONG)SECTOR_SIZE - 1);
			}

			if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
			{

				CcPrepareMdlWrite(
						Vcb->StreamObj,
						&ByteOffset,
						Length,
						&Irp->MdlAddress,
						&Irp->IoStatus);

				Status = Irp->IoStatus.Status;
			}
			else
			{
				Buffer = FFSGetUserBuffer(Irp);

				if (Buffer == NULL)

⌨️ 快捷键说明

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