📄 write.c
字号:
{
Status = Ext2QueueRequest(IrpContext);
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
Ext2FreeIrpContext(IrpContext);
}
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
if (SynchronousIo && !PagingIo && NT_SUCCESS(Status))
{
FileObject->CurrentByteOffset.QuadPart =
ByteOffset.QuadPart + Irp->IoStatus.Information;
}
if (!PagingIo && NT_SUCCESS(Status))
{
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
}
Ext2CompleteRequest(
IrpContext->Irp,
(CCHAR)
(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
Ext2FreeIrpContext(IrpContext);
}
}
else
{
Ext2FreeIrpContext(IrpContext);
}
}
}
return Status;
}
NTSTATUS
Ext2WriteInode (
IN PEXT2_IRP_CONTEXT IrpContext,
IN PEXT2_VCB Vcb,
IN PEXT2_INODE ext2_inode,
IN ULONG offset,
IN PVOID Buffer,
IN ULONG size,
IN BOOLEAN bWriteToDisk,
OUT PULONG dwReturn)
{
PEXT2_BDL ext2_bdl = NULL;
ULONG blocks, i;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
blocks = Ext2BuildBDL(IrpContext, Vcb, ext2_inode, offset, size, &ext2_bdl);
if (blocks <= 0)
return Status;
#if DBG
{
ULONG dwTotal = 0;
Ext2DbgPrint(D_WRITE, "Ext2WriteInode: BDLCount = %xh Size=%xh Off=%xh\n", blocks, size, offset);
for(i=0;i<blocks;i++)
{
Ext2DbgPrint(D_WRITE, "Ext2WriteInode: Lba=%I64xh Len=%xh Off=%xh\n", ext2_bdl[i].Lba, ext2_bdl[i].Length, ext2_bdl[i].Offset);
dwTotal += ext2_bdl[i].Length;
}
if (dwTotal != size)
{
Ext2DbgBreakPoint();
}
Ext2DbgPrint(D_WRITE, "Ext2WriteInode: Total = %xh (WriteToDisk=%x)\n", dwTotal, bWriteToDisk);
}
#endif
if (bWriteToDisk)
{
#if 0
for(i=0; i<blocks; i++)
{
{
CcFlushCache( &(Vcb->SectionObject),
(PLARGE_INTEGER)&(ext2_bdl[i].Lba),
ext2_bdl[i].Length,
NULL);
if (Vcb->SectionObject.DataSectionObject != NULL)
{
ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE);
ExReleaseResource(&Vcb->PagingIoResource);
CcPurgeCacheSection( &(Vcb->SectionObject),
(PLARGE_INTEGER)&(ext2_bdl[i].Lba),
ext2_bdl[i].Length,
FALSE );
}
}
}
#endif
// assume offset is aligned.
Status = Ext2ReadWriteBlocks(IrpContext, Vcb, ext2_bdl, size, blocks, FALSE);
}
else
{
for(i = 0; i < blocks; i++)
{
if(!Ext2SaveBuffer(IrpContext, Vcb, ext2_bdl[i].Lba, ext2_bdl[i].Length, (PVOID)((PUCHAR)Buffer + ext2_bdl[i].Offset)))
goto errorout;
}
Status = STATUS_SUCCESS;
}
errorout:
if (ext2_bdl)
ExFreePool(ext2_bdl);
return Status;
}
NTSTATUS
Ext2WriteFile(IN PEXT2_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PEXT2_VCB Vcb;
PEXT2_FCB Fcb;
PEXT2_CCB Ccb;
PFILE_OBJECT FileObject;
PFILE_OBJECT CacheObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
ULONG Length;
ULONG ReturnedLength;
LARGE_INTEGER ByteOffset;
BOOLEAN PagingIo;
BOOLEAN Nocache;
BOOLEAN SynchronousIo;
BOOLEAN MainResourceAcquired = FALSE;
BOOLEAN PagingIoResourceAcquired = FALSE;
BOOLEAN bNeedExtending = FALSE;
BOOLEAN bAppendFile = FALSE;
PUCHAR Buffer;
__try
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
(IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
(Vcb->Identifier.Size == sizeof(EXT2_VCB)));
FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext;
ASSERT(Fcb);
ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
(Fcb->Identifier.Size == sizeof(EXT2_FCB)));
Ccb = (PEXT2_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);
Ext2DbgPrint(D_WRITE, "Ext2WriteFile: Len=%xh Off=%I64x Paging=%xh Nocache=%xh\n", Length, ByteOffset.QuadPart, PagingIo, Nocache);
if (Length == 0)
{
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
__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 (IsEndOfFile(ByteOffset))
{
bAppendFile = TRUE;
ByteOffset.QuadPart = Fcb->CommonFCBHeader.FileSize.QuadPart;
}
if ( FlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) && !PagingIo)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
//
// Do flushing for such cases
//
if (Nocache && !PagingIo && (Fcb->SectionObject.DataSectionObject != NULL))
{
ExAcquireResourceExclusive(&Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
MainResourceAcquired = TRUE;
ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
ExReleaseResource(&Fcb->PagingIoResource);
CcFlushCache( &(Fcb->SectionObject),
&ByteOffset,
Length,
&(Irp->IoStatus));
ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED);
if (!NT_SUCCESS(Irp->IoStatus.Status))
{
Status = Irp->IoStatus.Status;
__leave;
}
ExAcquireSharedStarveExclusive( &Fcb->PagingIoResource, TRUE);
ExReleaseResource(&Fcb->PagingIoResource);
CcPurgeCacheSection( &(Fcb->SectionObject),
(PLARGE_INTEGER)&(ByteOffset),
Length,
FALSE );
ExReleaseResource(&Fcb->MainResource);
MainResourceAcquired = FALSE;
}
if (!PagingIo)
{
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
IrpContext->IsSynchronous ))
{
Status = STATUS_PENDING;
__leave;
}
MainResourceAcquired = TRUE;
}
else
{
if (!ExAcquireResourceSharedLite(
&Fcb->PagingIoResource,
IrpContext->IsSynchronous ))
{
Status = STATUS_PENDING;
__leave;
}
PagingIoResourceAcquired = TRUE;
}
if (!PagingIo)
{
if (!FsRtlCheckLockForWriteAccess(
&Fcb->FileLockAnchor,
Irp ))
{
Status = STATUS_FILE_LOCK_CONFLICT;
__leave;
}
}
if (Nocache)
{
if (ByteOffset.QuadPart + Length > Fcb->CommonFCBHeader.AllocationSize.QuadPart)
{
if (ByteOffset.QuadPart >= Fcb->CommonFCBHeader.AllocationSize.QuadPart)
{
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
__leave;
}
else
{
if (Length > (ULONG)(Fcb->CommonFCBHeader.AllocationSize.QuadPart - ByteOffset.QuadPart))
Length = (ULONG)(Fcb->CommonFCBHeader.AllocationSize.QuadPart - ByteOffset.QuadPart);
}
}
}
if (!Nocache)
{
if (FlagOn(Fcb->Ext2Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
__leave;
}
{
if (FileObject->PrivateCacheMap == NULL)
{
CcInitializeCacheMap(
FileObject,
(PCC_FILE_SIZES)(&Fcb->CommonFCBHeader.AllocationSize),
FALSE,
&gExt2Global->CacheManagerCallbacks,
Fcb );
CcSetReadAheadGranularity( FileObject, READ_AHEAD_GRANULARITY);
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->CommonFCBHeader.AllocationSize)));
}
CacheObject = FileObject;
}
//
// Need extending the size of inode ?
//
if (bAppendFile || ((ULONG)(ByteOffset.QuadPart + Length) >
(ULONG)(Fcb->CommonFCBHeader.FileSize.QuadPart)))
{
LARGE_INTEGER ExtendSize;
LARGE_INTEGER FileSize;
bNeedExtending = TRUE;
FileSize = Fcb->CommonFCBHeader.FileSize;
ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
if (ExtendSize.QuadPart > Fcb->CommonFCBHeader.AllocationSize.QuadPart)
{
if (!Ext2ExpandFileAllocation(IrpContext, Vcb, Fcb, &ExtendSize))
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
}
{
Fcb->CommonFCBHeader.FileSize.QuadPart = ExtendSize.QuadPart;
Fcb->ext2_inode->i_size = (ULONG) ExtendSize.QuadPart;
}
if (FileObject->PrivateCacheMap)
{
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->CommonFCBHeader.AllocationSize)));
if (ByteOffset.QuadPart > FileSize.QuadPart)
{
Ext2ZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart, ByteOffset.QuadPart - FileSize.QuadPart);
}
if (Fcb->CommonFCBHeader.AllocationSize.QuadPart > ExtendSize.QuadPart)
{
Ext2ZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart, Fcb->CommonFCBHeader.AllocationSize.QuadPart - ExtendSize.QuadPart);
}
}
if (Ext2SaveInode(IrpContext, Vcb, Fcb->Ext2Mcb->Inode, Fcb->ext2_inode))
Status = STATUS_SUCCESS;
}
if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
{
CcPrepareMdlWrite(
CacheObject,
(&ByteOffset),
Length,
&Irp->MdlAddress,
&Irp->IoStatus );
Status = Irp->IoStatus.Status;
}
else
{
Buffer = Ext2GetUserBuffer(Irp);
if (Buffer == NULL)
{
Status = STATUS_INVALID_USER_BUFFER;
__leave;
}
if (!CcCopyWrite(
CacheObject,
(PLARGE_INTEGER)&ByteOffset,
Length,
IrpContext->IsSynchronous,
Buffer ))
{
Status = STATUS_PENDING;
__leave;
}
Status = Irp->IoStatus.Status;
}
if (NT_SUCCESS(Status))
Irp->IoStatus.Information = Length;
}
else
{
ReturnedLength = Length;
Status = Ext2LockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess );
if (!NT_SUCCESS(Status))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -