diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index dc880aeb..f159a3c0 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -300,6 +300,10 @@ typedef struct FSP_FSCTL_FILE_INFO FileInfo; } Overwrite; struct + { + FSP_FSCTL_FILE_INFO FileInfo; + } Read; + struct { FSP_FSCTL_FILE_INFO FileInfo; } Write; diff --git a/src/sys/read.c b/src/sys/read.c index fd772a2b..0fd08851 100644 --- a/src/sys/read.c +++ b/src/sys/read.c @@ -35,6 +35,9 @@ enum RequestSafeMdl = 1, RequestAddress = 2, RequestProcess = 3, + + /* ReadNonCachedComplete retry */ + RequestInfoChangeNumber = 0, }; static NTSTATUS FspFsvolRead( @@ -277,13 +280,6 @@ NTSTATUS FspFsvolReadComplete( { FSP_ENTER_IOC(PAGED_CODE()); - FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); - PFILE_OBJECT FileObject = IrpSp->FileObject; - FSP_FILE_NODE *FileNode = FileObject->FsContext; - LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset; - BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO); - BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); - if (!NT_SUCCESS(Response->IoStatus.Status)) { Irp->IoStatus.Information = 0; @@ -291,16 +287,47 @@ NTSTATUS FspFsvolReadComplete( FSP_RETURN(); } + FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); + PFILE_OBJECT FileObject = IrpSp->FileObject; + FSP_FILE_NODE *FileNode = FileObject->FsContext; + LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset; + BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO); + BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); + ULONG InfoChangeNumber; + BOOLEAN Success; + if (!PagingIo) { + if (FspFsctlTransactReadKind == Request->Kind) + { + InfoChangeNumber = FileNode->InfoChangeNumber; + FspIopResetRequest(Request, 0); + + Request->Kind = FspFsctlTransactReservedKind; + FspIopRequestContext(Request, RequestInfoChangeNumber) = (PVOID)InfoChangeNumber; + } + else + InfoChangeNumber = (ULONG)(UINT_PTR)FspIopRequestContext(Request, RequestInfoChangeNumber); + + Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireExclusive(FileNode, Main); + if (!Success) + { + FspIopRetryCompleteIrp(Irp, Response, &Result); + FSP_RETURN(); + } + + FspFileNodeTrySetFileInfo(FileNode, FileObject, &Response->Rsp.Read.FileInfo, + InfoChangeNumber); + /* update the current file offset if synchronous I/O (and not paging I/O) */ if (SynchronousIo) FileObject->CurrentByteOffset.QuadPart = ReadOffset.QuadPart + Response->IoStatus.Information; - } - FspFileNodeReleaseOwner(FileNode, Full, Request); - /* will also clear FspIrpFlags() */ + FspFileNodeRelease(FileNode, Main); + } + else + FspIopResetRequest(Request, 0); Irp->IoStatus.Information = Response->IoStatus.Information; Result = STATUS_SUCCESS; @@ -343,7 +370,7 @@ static VOID FspFsvolReadNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV if (0 != SafeMdl) FspSafeMdlDelete(SafeMdl); - if (0 != Irp && 0 != FspIrpFlags(Irp)) + if (0 != Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); FSP_FILE_NODE *FileNode = IrpSp->FileObject->FsContext; diff --git a/src/sys/write.c b/src/sys/write.c index e3eba3a8..599374db 100644 --- a/src/sys/write.c +++ b/src/sys/write.c @@ -368,6 +368,13 @@ NTSTATUS FspFsvolWriteComplete( { FSP_ENTER_IOC(PAGED_CODE()); + if (!NT_SUCCESS(Response->IoStatus.Status)) + { + Irp->IoStatus.Information = 0; + Result = Response->IoStatus.Status; + FSP_RETURN(); + } + FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; @@ -377,13 +384,6 @@ NTSTATUS FspFsvolWriteComplete( BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO); BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); - if (!NT_SUCCESS(Response->IoStatus.Status)) - { - Irp->IoStatus.Information = 0; - Result = Response->IoStatus.Status; - FSP_RETURN(); - } - if (!PagingIo) { /* update file info */ @@ -396,8 +396,7 @@ NTSTATUS FspFsvolWriteComplete( WriteOffset.QuadPart + Response->IoStatus.Information; } - FspFileNodeReleaseOwner(FileNode, Full, Request); - /* will also clear FspIrpFlags() */ + FspIopResetRequest(Request, 0); Irp->IoStatus.Information = Response->IoStatus.Information; Result = STATUS_SUCCESS; @@ -440,7 +439,7 @@ static VOID FspFsvolWriteNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, P if (0 != SafeMdl) FspSafeMdlDelete(SafeMdl); - if (0 != Irp && 0 != FspIrpFlags(Irp)) + if (0 != Irp) { PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); FSP_FILE_NODE *FileNode = IrpSp->FileObject->FsContext;