📄 write.c
字号:
(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 (IsEndOfFile(ByteOffset))
{
bAppendFile = TRUE;
ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
}
if (FlagOn(Fcb->FFSMcb->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 (!ExAcquireResourceExclusiveLite(
&Fcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
__leave;
}
MainResourceAcquired = TRUE;
}
else
{
/*
ULONG ResShCnt, ResExCnt;
ResShCnt = ExIsResourceAcquiredSharedLite(&Fcb->PagingIoResource);
ResExCnt = ExIsResourceAcquiredExclusiveLite(&Fcb->PagingIoResource);
FFSPrint((DBG_USER, "FFSWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n",
Fcb->FFSMcb->Inode, Fcb->FFSMcb->ShortName.Buffer, ResShCnt, ResExCnt, IrpContext->IsSynchronous));
*/
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->Header.AllocationSize.QuadPart)
{
if (ByteOffset.QuadPart >=
Fcb->Header.AllocationSize.QuadPart)
{
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
__leave;
}
else
{
if (Length > (ULONG)(Fcb->Header.AllocationSize.QuadPart
- ByteOffset.QuadPart))
{
Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart
- ByteOffset.QuadPart);
}
}
}
}
if (!Nocache)
{
if (FlagOn(Fcb->FFSMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY))
{
__leave;
}
if (FileObject->PrivateCacheMap == NULL)
{
CcInitializeCacheMap(
FileObject,
(PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
FALSE,
&FFSGlobal->CacheManagerCallbacks,
Fcb);
CcSetReadAheadGranularity(
FileObject,
READ_AHEAD_GRANULARITY);
CcSetFileSizes(
FileObject,
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
}
CacheObject = FileObject;
//
// Need extending the size of inode ?
//
if ((bAppendFile) || ((ULONG)(ByteOffset.QuadPart + Length) >
(ULONG)(Fcb->Header.FileSize.QuadPart)))
{
LARGE_INTEGER ExtendSize;
LARGE_INTEGER FileSize;
bNeedExtending = TRUE;
FileSize = Fcb->Header.FileSize;
ExtendSize.QuadPart = (LONGLONG)(ByteOffset.QuadPart + Length);
if (ExtendSize.QuadPart > Fcb->Header.AllocationSize.QuadPart)
{
if (!FFSExpandFile(IrpContext, Vcb, Fcb, &ExtendSize))
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
}
{
Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart;
Fcb->dinode1->di_size = (ULONG)ExtendSize.QuadPart;
}
if (FileObject->PrivateCacheMap)
{
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
if (ByteOffset.QuadPart > FileSize.QuadPart)
{
FFSZeroHoles(IrpContext, Vcb, FileObject, FileSize.QuadPart,
ByteOffset.QuadPart - FileSize.QuadPart);
}
if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart)
{
FFSZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart,
Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart);
}
}
if (FFSv1SaveInode(IrpContext, Vcb, Fcb->FFSMcb->Inode, Fcb->dinode1))
{
Status = STATUS_SUCCESS;
}
FFSNotifyReportChange(
IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_SIZE,
FILE_ACTION_MODIFIED);
}
if (FlagOn(IrpContext->MinorFunction, IRP_MN_MDL))
{
CcPrepareMdlWrite(
CacheObject,
(&ByteOffset),
Length,
&Irp->MdlAddress,
&Irp->IoStatus);
Status = Irp->IoStatus.Status;
}
else
{
Buffer = FFSGetUserBuffer(Irp);
if (Buffer == NULL)
{
FFSBreakPoint();
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;
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK))
{
FFSPrint((DBG_USER, "FFSWriteFile is starting FlushingDpc...\n"));
FFSStartFloppyFlushDpc(Vcb, Fcb, FileObject);
}
}
}
else
{
ReturnedLength = Length;
Status = FFSLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess);
if (!NT_SUCCESS(Status))
{
__leave;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length;
Status =
FFSv1WriteInode(
IrpContext,
Vcb,
Fcb->dinode1,
(ULONGLONG)(ByteOffset.QuadPart),
NULL,
Length,
TRUE,
&ReturnedLength);
Irp = IrpContext->Irp;
}
}
__finally
{
if (PagingIoResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->PagingIoResource,
ExGetCurrentResourceThread());
}
if (MainResourceAcquired)
{
ExReleaseResourceForThreadLite(
&Fcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress)
{
if (Irp)
{
if (Status == STATUS_PENDING)
{
if (!bDeferred)
{
Status = FFSLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess);
if (NT_SUCCESS(Status))
{
Status = FFSQueueRequest(IrpContext);
}
else
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
}
else
{
if (NT_SUCCESS(Status))
{
if (SynchronousIo && !PagingIo)
{
FileObject->CurrentByteOffset.QuadPart =
ByteOffset.QuadPart + Irp->IoStatus.Information;
}
if (!PagingIo)
{
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
SetFlag(Fcb->Flags, FCB_FILE_MODIFIED);
}
}
FFSCompleteIrpContext(IrpContext, Status);
}
}
else
{
FFSFreeIrpContext(IrpContext);
}
}
}
return Status;
}
NTSTATUS
FFSWriteComplete(
IN PFFS_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFILE_OBJECT FileObject;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
__try
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
FileObject = IrpContext->FileObject;
Irp = IrpContext->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
CcMdlWriteComplete(FileObject, &(IrpSp->Parameters.Write.ByteOffset), Irp->MdlAddress);
Irp->MdlAddress = NULL;
Status = STATUS_SUCCESS;
}
__finally
{
if (!IrpContext->ExceptionInProgress)
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
NTSTATUS
FFSWrite(
IN PFFS_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
PFFS_FCBVCB FcbOrVcb;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PFFS_VCB Vcb;
BOOLEAN bCompleteRequest = TRUE;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
__try
{
if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE))
{
Status = FFSWriteComplete(IrpContext);
bCompleteRequest = FALSE;
}
else
{
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
if (Vcb->Identifier.Type != FFSVCB ||
Vcb->Identifier.Size != sizeof(FFS_VCB))
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
ASSERT(IsMounted(Vcb));
if (IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
{
Status = STATUS_TOO_LATE;
__leave;
}
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY))
{
Status = STATUS_MEDIA_WRITE_PROTECTED;
__leave;
}
FileObject = IrpContext->FileObject;
FcbOrVcb = (PFFS_FCBVCB)FileObject->FsContext;
if (FcbOrVcb->Identifier.Type == FFSVCB)
{
Status = FFSWriteVolume(IrpContext);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
}
bCompleteRequest = FALSE;
}
else if (FcbOrVcb->Identifier.Type == FFSFCB)
{
Status = FFSWriteFile(IrpContext);
if (!NT_SUCCESS(Status))
{
FFSBreakPoint();
}
bCompleteRequest = FALSE;
}
else
{
Status = STATUS_INVALID_PARAMETER;
}
}
}
__finally
{
if (bCompleteRequest)
{
FFSCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -