📄 write.c
字号:
/*
* 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 + -