mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: FspIopRetryCompleteIrp() and related changes
This commit is contained in:
		| @@ -14,10 +14,9 @@ static NTSTATUS FspFsvolCreate( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; | ||||
| FSP_IORETR_DISPATCH FspFsvolCreateRetryComplete; | ||||
| static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, | ||||
| static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, | ||||
|     FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject, | ||||
|     BOOLEAN FlushImage, BOOLEAN Retrying); | ||||
|     BOOLEAN FlushImage); | ||||
| static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc); | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini; | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolCreateTryOpenRequestFini; | ||||
| @@ -30,7 +29,6 @@ FSP_DRIVER_DISPATCH FspCreate; | ||||
| #pragma alloc_text(PAGE, FspFsvolCreate) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreatePrepare) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateRetryComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateTryOpen) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreatePostClose) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateRequestFini) | ||||
| @@ -532,7 +530,6 @@ NTSTATUS FspFsvolCreateComplete( | ||||
|         FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes, | ||||
|             FILE_ATTRIBUTE_DIRECTORY); | ||||
|         FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2; | ||||
|         FileDesc->State.FileInfo = Response->Rsp.Create.Opened.FileInfo; | ||||
|  | ||||
|         DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE); | ||||
|  | ||||
| @@ -580,7 +577,7 @@ NTSTATUS FspFsvolCreateComplete( | ||||
|                 (FlagOn(Response->Rsp.Create.Opened.GrantedAccess, FILE_WRITE_DATA) || | ||||
|                 DeleteOnClose); | ||||
|  | ||||
|             Result = FspFsvolCreateTryOpen(Irp, FileNode, FileDesc, FileObject, FlushImage, FALSE); | ||||
|             Result = FspFsvolCreateTryOpen(Irp, Response, FileNode, FileDesc, FileObject, FlushImage); | ||||
|         } | ||||
|         else | ||||
|         if (FILE_SUPERSEDED == Response->IoStatus.Information || | ||||
| @@ -632,7 +629,7 @@ NTSTATUS FspFsvolCreateComplete( | ||||
|         else | ||||
|         { | ||||
|             /* SUCCESS! */ | ||||
|             FspFileNodeSetFileInfo(FileNode, &FileDesc->State.FileInfo); | ||||
|             FspFileNodeSetFileInfo(FileNode, &Response->Rsp.Create.Opened.FileInfo); | ||||
|             FspIopRequestContext(Request, RequestFileDesc) = 0; | ||||
|             Irp->IoStatus.Information = (ULONG_PTR)Response->IoStatus.Information; | ||||
|             Result = STATUS_SUCCESS; | ||||
| @@ -666,6 +663,16 @@ NTSTATUS FspFsvolCreateComplete( | ||||
|         Irp->IoStatus.Information = Request->Req.Overwrite.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN; | ||||
|         Result = STATUS_SUCCESS; | ||||
|     } | ||||
|     else if (FspFsctlTransactReservedKind == Request->Kind) | ||||
|     { | ||||
|         /* | ||||
|          * A Reserved request is a special request used when retrying a file open. | ||||
|          */ | ||||
|  | ||||
|         BOOLEAN FlushImage = 0 != FspIopRequestContext(Request, RequestState); | ||||
|  | ||||
|         Result = FspFsvolCreateTryOpen(Irp, Response, FileNode, FileDesc, FileObject, FlushImage); | ||||
|     } | ||||
|     else | ||||
|         ASSERT(0); | ||||
|  | ||||
| @@ -674,77 +681,43 @@ NTSTATUS FspFsvolCreateComplete( | ||||
|         IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspFsvolCreateRetryComplete( | ||||
|     PIRP Irp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); | ||||
|     FSP_FILE_NODE *FileNode; | ||||
|     FSP_FILE_DESC *FileDesc; | ||||
|     PFILE_OBJECT FileObject; | ||||
|     BOOLEAN FlushImage; | ||||
|  | ||||
|     ASSERT(FspFsctlTransactCreateKind == Request->Kind); | ||||
|  | ||||
|     FileDesc = FspIopRequestContext(Request, RequestFileDesc); | ||||
|     FileNode = FileDesc->FileNode; | ||||
|     FileObject = FspIopRequestContext(Request, RequestFileObject); | ||||
|     FlushImage = 0 != FspIopRequestContext(Request, RequestState); | ||||
|  | ||||
|     Result = FspFsvolCreateTryOpen(Irp, FileNode, FileDesc, FileObject, FlushImage, TRUE); | ||||
|     if (STATUS_PENDING == Result) | ||||
|         return Result; | ||||
|     else | ||||
|     { | ||||
|         DEBUGLOGIRP(Irp, Result); | ||||
|  | ||||
|         FspIopCompleteIrp(Irp, Result); | ||||
|         return STATUS_SUCCESS; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, | ||||
| static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, | ||||
|     FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject, | ||||
|     BOOLEAN FlushImage, BOOLEAN Retrying) | ||||
|     BOOLEAN FlushImage) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); | ||||
|     BOOLEAN Success; | ||||
|  | ||||
|     ASSERT(FspFsctlTransactCreateKind == Request->Kind); | ||||
|  | ||||
|     Success = FspFileNodeTryAcquireExclusive(FileNode, Both); | ||||
|     if (!Success) | ||||
|     { | ||||
|         /* repost the IRP to retry later */ | ||||
|         NTSTATUS Result; | ||||
|         PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||
|         FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = | ||||
|             FspFsvolDeviceExtension(IrpSp->DeviceObject); | ||||
|  | ||||
|         if (!Retrying) | ||||
|         if (FspFsctlTransactCreateKind == Request->Kind) | ||||
|         { | ||||
|             /* disassociate the FileDesc momentarily from the Request */ | ||||
|             Request = FspIrpRequest(Irp); | ||||
|             FspIopRequestContext(Request, RequestFileDesc) = 0; | ||||
|  | ||||
|             /* reset the Request and reassociate the FileDesc and FileObject with it */ | ||||
|             Request->Kind = FspFsctlTransactReservedKind; | ||||
|             FspIopResetRequest(Request, FspFsvolCreateTryOpenRequestFini); | ||||
|             FspIopRequestContext(Request, RequestFileDesc) = FileDesc; | ||||
|             FspIopRequestContext(Request, RequestFileObject) = FileObject; | ||||
|             FspIopRequestContext(Request, RequestState) = (PVOID)(UINT_PTR)FlushImage; | ||||
|         } | ||||
|  | ||||
|         FspIoqRetryCompleteIrp(FsvolDeviceExtension->Ioq, Irp, &Result); | ||||
|         FspIopRetryCompleteIrp(Irp, Response, &Result); | ||||
|  | ||||
|         return Result; | ||||
|     } | ||||
|  | ||||
|     FspFileObjectSetSizes(FileObject, | ||||
|         FileDesc->State.FileInfo.AllocationSize, FileDesc->State.FileInfo.FileSize); | ||||
|         Response->Rsp.Create.Opened.FileInfo.AllocationSize, | ||||
|         Response->Rsp.Create.Opened.FileInfo.FileSize); | ||||
|  | ||||
|     if (FlushImage) | ||||
|     { | ||||
| @@ -769,7 +742,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, | ||||
|         FspFileNodeRelease(FileNode, Both); | ||||
|  | ||||
|     /* SUCCESS! */ | ||||
|     FspFileNodeSetFileInfo(FileNode, &FileDesc->State.FileInfo); | ||||
|     FspFileNodeSetFileInfo(FileNode, &Response->Rsp.Create.Opened.FileInfo); | ||||
|     FspIopRequestContext(Request, RequestFileDesc) = 0; | ||||
|     Irp->IoStatus.Information = FILE_OPENED; | ||||
|     return STATUS_SUCCESS; | ||||
|   | ||||
| @@ -69,7 +69,6 @@ NTSTATUS DriverEntry( | ||||
|     /* setup the I/O prepare/complete functions */ | ||||
|     FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare; | ||||
|     FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete; | ||||
|     FspIopRetryCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateRetryComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete; | ||||
|     FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete; | ||||
|   | ||||
| @@ -225,15 +225,10 @@ _IRQL_requires_max_(APC_LEVEL) | ||||
| _IRQL_requires_same_ | ||||
| typedef NTSTATUS FSP_IOCMPL_DISPATCH( | ||||
|     _Inout_ PIRP Irp, _In_ const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| _IRQL_requires_max_(APC_LEVEL) | ||||
| _IRQL_requires_same_ | ||||
| typedef NTSTATUS FSP_IORETR_DISPATCH( | ||||
|     _Inout_ PIRP Irp); | ||||
| FSP_IOCMPL_DISPATCH FspFsvolCleanupComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolCloseComplete; | ||||
| FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; | ||||
| FSP_IORETR_DISPATCH FspFsvolCreateRetryComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolDeviceControlComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolDirectoryControlComplete; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolFileSystemControlComplete; | ||||
| @@ -422,9 +417,10 @@ NTSTATUS FspIopPostWorkRequestFunnel(PDEVICE_OBJECT DeviceObject, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, BOOLEAN BestEffort); | ||||
| VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference); | ||||
| VOID FspIopCompleteCanceledIrp(PIRP Irp); | ||||
| BOOLEAN FspIopRetryCompleteIrp(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, NTSTATUS *PResult); | ||||
| FSP_FSCTL_TRANSACT_RSP *FspIopIrpResponse(PIRP Irp); | ||||
| NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); | ||||
| NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| NTSTATUS FspIopDispatchRetryComplete(PIRP Irp); | ||||
|  | ||||
| /* device management */ | ||||
| #define FSP_DEVICE_VOLUME_NAME_LENMAX   (FSP_FSCTL_VOLUME_NAME_SIZEMAX - sizeof(WCHAR)) | ||||
| @@ -590,10 +586,6 @@ typedef struct | ||||
| { | ||||
|     FSP_FILE_NODE *FileNode; | ||||
|     UINT64 UserContext2; | ||||
|     union | ||||
|     { | ||||
|         FSP_FSCTL_FILE_INFO FileInfo;   /* create time only */ | ||||
|     } State; | ||||
| } FSP_FILE_DESC; | ||||
| NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, | ||||
|     ULONG ExtraSize, FSP_FILE_NODE **PFileNode); | ||||
| @@ -663,6 +655,5 @@ extern PDEVICE_OBJECT FspFsctlDiskDeviceObject; | ||||
| extern PDEVICE_OBJECT FspFsctlNetDeviceObject; | ||||
| extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[]; | ||||
| extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[]; | ||||
| extern FSP_IORETR_DISPATCH *FspIopRetryCompleteFunction[]; | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -18,9 +18,10 @@ NTSTATUS FspIopPostWorkRequestFunnel(PDEVICE_OBJECT DeviceObject, | ||||
| static IO_COMPLETION_ROUTINE FspIopPostWorkRequestCompletion; | ||||
| VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference); | ||||
| VOID FspIopCompleteCanceledIrp(PIRP Irp); | ||||
| BOOLEAN FspIopRetryCompleteIrp(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, NTSTATUS *PResult); | ||||
| FSP_FSCTL_TRANSACT_RSP *FspIopIrpResponse(PIRP Irp); | ||||
| NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); | ||||
| NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| NTSTATUS FspIopDispatchRetryComplete(PIRP Irp); | ||||
|  | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspIopCreateRequestFunnel) | ||||
| @@ -30,9 +31,10 @@ NTSTATUS FspIopDispatchRetryComplete(PIRP Irp); | ||||
| #pragma alloc_text(PAGE, FspIopPostWorkRequestFunnel) | ||||
| #pragma alloc_text(PAGE, FspIopCompleteIrpEx) | ||||
| #pragma alloc_text(PAGE, FspIopCompleteCanceledIrp) | ||||
| #pragma alloc_text(PAGE, FspIopRetryCompleteIrp) | ||||
| #pragma alloc_text(PAGE, FspIopIrpResponse) | ||||
| #pragma alloc_text(PAGE, FspIopDispatchPrepare) | ||||
| #pragma alloc_text(PAGE, FspIopDispatchComplete) | ||||
| #pragma alloc_text(PAGE, FspIopDispatchRetryComplete) | ||||
| #endif | ||||
|  | ||||
| static const LONG Delays[] = | ||||
| @@ -81,6 +83,7 @@ typedef struct | ||||
| { | ||||
|     FSP_IOP_REQUEST_FINI *RequestFini; | ||||
|     PVOID Context[3]; | ||||
|     FSP_FSCTL_TRANSACT_RSP *Response; | ||||
|     __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 RequestBuf[]; | ||||
| } FSP_FSCTL_TRANSACT_REQ_HEADER; | ||||
|  | ||||
| @@ -142,6 +145,9 @@ VOID FspIopDeleteRequest(FSP_FSCTL_TRANSACT_REQ *Request) | ||||
|     if (0 != RequestHeader->RequestFini) | ||||
|         RequestHeader->RequestFini(RequestHeader->Context); | ||||
|  | ||||
|     if (0 != RequestHeader->Response) | ||||
|         FspFree(RequestHeader->Response); | ||||
|  | ||||
|     FspFree(RequestHeader); | ||||
| } | ||||
|  | ||||
| @@ -260,6 +266,39 @@ VOID FspIopCompleteCanceledIrp(PIRP Irp) | ||||
|     FspIopCompleteIrpEx(Irp, STATUS_CANCELLED, TRUE); | ||||
| } | ||||
|  | ||||
| BOOLEAN FspIopRetryCompleteIrp(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, NTSTATUS *PResult) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PDEVICE_OBJECT DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); | ||||
|     FSP_FSCTL_TRANSACT_REQ_HEADER *RequestHeader = (PVOID)((PUINT8)Request - sizeof *RequestHeader); | ||||
|  | ||||
|     ASSERT(0 != Request); | ||||
|  | ||||
|     if (0 != Response && RequestHeader->Response != Response) | ||||
|     { | ||||
|         if (0 != RequestHeader->Response) | ||||
|             FspFree(RequestHeader->Response); | ||||
|         RequestHeader->Response = FspAllocMustSucceed(Response->Size); | ||||
|         RtlCopyMemory(RequestHeader->Response, Response, Response->Size); | ||||
|         Response = RequestHeader->Response; | ||||
|     } | ||||
|  | ||||
|     return FspIoqRetryCompleteIrp(FsvolDeviceExtension->Ioq, Irp, PResult); | ||||
| } | ||||
|  | ||||
| FSP_FSCTL_TRANSACT_RSP *FspIopIrpResponse(PIRP Irp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); | ||||
|     FSP_FSCTL_TRANSACT_REQ_HEADER *RequestHeader = (PVOID)((PUINT8)Request - sizeof *RequestHeader); | ||||
|  | ||||
|     return RequestHeader->Response; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
| @@ -285,18 +324,5 @@ NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response | ||||
|     return FspIopCompleteFunction[IrpSp->MajorFunction](Irp, Response); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspIopDispatchRetryComplete(PIRP Irp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||
|  | ||||
|     ASSERT(IRP_MJ_MAXIMUM_FUNCTION >= IrpSp->MajorFunction); | ||||
|     ASSERT(0 != FspIopRetryCompleteFunction[IrpSp->MajorFunction]); | ||||
|  | ||||
|     return FspIopRetryCompleteFunction[IrpSp->MajorFunction](Irp); | ||||
| } | ||||
|  | ||||
| FSP_IOPREP_DISPATCH *FspIopPrepareFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; | ||||
| FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; | ||||
| FSP_IORETR_DISPATCH *FspIopRetryCompleteFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; | ||||
|   | ||||
| @@ -329,7 +329,11 @@ static PIRP FspIoqRetriedPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext) | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (Irp == IrpHint) | ||||
|             return 0; | ||||
|         return Irp; | ||||
|     } | ||||
| } | ||||
|  | ||||
| _IRQL_raises_(DISPATCH_LEVEL) | ||||
|   | ||||
| @@ -548,7 +548,8 @@ NTSTATUS FspVolumeTransact( | ||||
|         if (0 == RetriedIrp) | ||||
|             break; | ||||
|  | ||||
|         Result = FspIopDispatchRetryComplete(RetriedIrp); | ||||
|         Response = FspIopIrpResponse(RetriedIrp); | ||||
|         Result = FspIopDispatchComplete(RetriedIrp, Response); | ||||
|         if (STATUS_PENDING == Result) | ||||
|         { | ||||
|             /* | ||||
|   | ||||
		Reference in New Issue
	
	Block a user