📄 write.c
字号:
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)RfsdDeferWrite,
IrpContext,
Irp,
Length,
bAgain );
bDeferred = TRUE;
DbgBreak();
Status = STATUS_PENDING;
__leave;
}
}
#endif
if (IsEndOfFile(ByteOffset)) {
bAppendFile = TRUE;
ByteOffset.QuadPart = Fcb->Header.FileSize.QuadPart;
}
if ( FlagOn(Fcb->RfsdMcb->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);
RfsdPrint((DBG_USER, "RfsdWriteFile: Inode=%xh %S PagingIo: %xh:%xh Synchronous=%xh\n",
Fcb->RfsdMcb->Inode, Fcb->RfsdMcb->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->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
__leave;
}
if (FileObject->PrivateCacheMap == NULL) {
CcInitializeCacheMap(
FileObject,
(PCC_FILE_SIZES)(&Fcb->Header.AllocationSize),
FALSE,
&RfsdGlobal->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) || ((ByteOffset.QuadPart + Length) >
(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) {
Status = RfsdExpandFile(IrpContext, Vcb, Fcb, &ExtendSize);
if (!NT_SUCCESS(Status)) {
__leave;
}
}
{
Fcb->Header.FileSize.QuadPart = ExtendSize.QuadPart;
Fcb->Inode->i_size = ExtendSize.LowPart;
Fcb->Inode->i_size_high = (ULONG) ExtendSize.HighPart;
}
if (FileObject->PrivateCacheMap) {
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
if (ByteOffset.QuadPart > FileSize.QuadPart) {
RfsdZeroHoles( IrpContext, Vcb, FileObject, FileSize.QuadPart,
ByteOffset.QuadPart - FileSize.QuadPart);
}
if (Fcb->Header.AllocationSize.QuadPart > ExtendSize.QuadPart) {
RfsdZeroHoles(IrpContext, Vcb, FileObject, ExtendSize.QuadPart,
Fcb->Header.AllocationSize.QuadPart - ExtendSize.QuadPart);
}
}
if (RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode)) {
Status = STATUS_SUCCESS;
}
RfsdNotifyReportChange(
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 = RfsdGetUserBuffer(Irp);
if (Buffer == NULL) {
DbgBreak();
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)) {
RfsdPrint((DBG_USER, "RfsdWriteFile is starting FlushingDpc...\n"));
RfsdStartFloppyFlushDpc(Vcb, Fcb, FileObject);
}
}
} else {
ReturnedLength = Length;
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess );
if (!NT_SUCCESS(Status)) {
__leave;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Length;
Status = RfsdWriteInode(
IrpContext,
Vcb,
Fcb->RfsdMcb->Inode,
Fcb->Inode,
(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 = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess );
if (NT_SUCCESS(Status)) {
Status = RfsdQueueRequest(IrpContext);
} else {
RfsdCompleteIrpContext(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);
}
}
RfsdCompleteIrpContext(IrpContext, Status);
}
} else {
RfsdFreeIrpContext(IrpContext);
}
}
}
return Status;
}
NTSTATUS
RfsdWriteComplete (IN PRFSD_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFILE_OBJECT FileObject;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
__try {
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_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) {
RfsdCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
NTSTATUS
RfsdWrite (IN PRFSD_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
PRFSD_FCBVCB FcbOrVcb;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PRFSD_VCB Vcb;
BOOLEAN bCompleteRequest = TRUE;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
__try {
if (FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE)) {
Status = RfsdWriteComplete(IrpContext);
bCompleteRequest = FALSE;
} else {
DeviceObject = IrpContext->DeviceObject;
if (DeviceObject == RfsdGlobal->DeviceObject) {
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
if (Vcb->Identifier.Type != RFSDVCB ||
Vcb->Identifier.Size != sizeof(RFSD_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 = (PRFSD_FCBVCB) FileObject->FsContext;
if (FcbOrVcb->Identifier.Type == RFSDVCB) {
Status = RfsdWriteVolume(IrpContext);
if (!NT_SUCCESS(Status)) {
DbgBreak();
}
bCompleteRequest = FALSE;
} else if (FcbOrVcb->Identifier.Type == RFSDFCB) {
Status = RfsdWriteFile(IrpContext);
if (!NT_SUCCESS(Status)) {
DbgBreak();
}
bCompleteRequest = FALSE;
} else {
Status = STATUS_INVALID_PARAMETER;
}
}
} __finally {
if (bCompleteRequest) {
RfsdCompleteIrpContext(IrpContext, Status);
}
}
return Status;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -