From e0c47750d9c6b969d2b9f522a4b3988498fbb99c Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 4 Dec 2015 10:05:36 -0800 Subject: [PATCH] sys: FspIopDispatchPrepare --- src/sys/create.c | 10 +++++++++ src/sys/driver.c | 3 +++ src/sys/driver.h | 7 ++++++ src/sys/fsctl.c | 55 +++++++++++++++++++++++++++++------------------- src/sys/iop.c | 16 ++++++++++++++ 5 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/sys/create.c b/src/sys/create.c index 3facbf13..fcbf2d47 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -13,6 +13,7 @@ static NTSTATUS FspFsvrtCreate( static NTSTATUS FspFsvolCreate( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_DRIVER_DISPATCH FspCreate; +FSP_IOPREP_DISPATCH FspCreatePrepare; FSP_IOCMPL_DISPATCH FspCreateComplete; #ifdef ALLOC_PRAGMA @@ -20,6 +21,7 @@ FSP_IOCMPL_DISPATCH FspCreateComplete; #pragma alloc_text(PAGE, FspFsvrtCreate) #pragma alloc_text(PAGE, FspFsvolCreate) #pragma alloc_text(PAGE, FspCreate) +#pragma alloc_text(PAGE, FspCreatePrepare) #pragma alloc_text(PAGE, FspCreateComplete) #endif @@ -347,6 +349,14 @@ NTSTATUS FspCreate( Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength); } +NTSTATUS FspCreatePrepare( + PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) +{ + PAGED_CODE(); + + return STATUS_SUCCESS; +} + VOID FspCreateComplete( PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) { diff --git a/src/sys/driver.c b/src/sys/driver.c index ccaf13d6..17785baa 100644 --- a/src/sys/driver.c +++ b/src/sys/driver.c @@ -62,6 +62,9 @@ NTSTATUS DriverEntry( DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = FspQuerySecurity; DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = FspSetSecurity; + /* setup the I/O preparation functions */ + FspIopPrepareFunction[IRP_MJ_CREATE] = FspCreatePrepare; + /* setup the I/O completion functions */ FspIopCompleteFunction[IRP_MJ_CREATE] = FspCreateComplete; FspIopCompleteFunction[IRP_MJ_CLOSE] = FspCloseComplete; diff --git a/src/sys/driver.h b/src/sys/driver.h index bb8e3bb5..3d8c6c0d 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -197,8 +197,13 @@ _Dispatch_type_(IRP_MJ_WRITE) FSP_DRIVER_DISPATCH FspWrite; /* I/O processing functions */ _IRQL_requires_max_(APC_LEVEL) _IRQL_requires_same_ +typedef NTSTATUS FSP_IOPREP_DISPATCH( + _Inout_ PIRP Irp, _Inout_ FSP_FSCTL_TRANSACT_REQ *Request); +_IRQL_requires_max_(APC_LEVEL) +_IRQL_requires_same_ typedef VOID FSP_IOCMPL_DISPATCH( _Inout_ PIRP Irp, _In_ const FSP_FSCTL_TRANSACT_RSP *Response); +FSP_IOPREP_DISPATCH FspCreatePrepare; FSP_IOCMPL_DISPATCH FspCleanupComplete; FSP_IOCMPL_DISPATCH FspCloseComplete; FSP_IOCMPL_DISPATCH FspCreateComplete; @@ -255,6 +260,7 @@ static inline VOID FspIopCompleteRequest(PIRP Irp, NTSTATUS Result) { FspIopCompleteRequestEx(Irp, Result, TRUE); } +NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); /* device management */ @@ -371,6 +377,7 @@ const char *IoctlCodeSym(ULONG ControlCode); extern PDRIVER_OBJECT FspDriverObject; extern PDEVICE_OBJECT FspFsctlDiskDeviceObject; extern PDEVICE_OBJECT FspFsctlNetDeviceObject; +extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[]; extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[]; #endif diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c index 3e41ab3a..e0e156fd 100644 --- a/src/sys/fsctl.c +++ b/src/sys/fsctl.c @@ -378,6 +378,7 @@ static NTSTATUS FspFsvrtTransact( } /* wait for an IRP to arrive */ +retry: while (0 == (PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, (ULONG)-1L))) { if (FspIoqStopped(&FsvrtDeviceExtension->Ioq)) @@ -392,36 +393,46 @@ static NTSTATUS FspFsvrtTransact( { PendingIrpRequest = PendingIrp->Tail.Overlay.DriverContext[0]; - NextRequest = FspFsctlTransactProduceRequest( - Request, PendingIrpRequest->Size, SystemBufferEnd); - /* this should not fail as we have already checked that we have enough space */ - ASSERT(0 != NextRequest); - - RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size); - Request = NextRequest; - - if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp)) + Result = FspIopDispatchPrepare(PendingIrp, PendingIrpRequest); + if (!NT_SUCCESS(Result)) + FspIopCompleteRequest(PendingIrp, Result); + else { - /* - * This can only happen if the Ioq was stopped. Abandon everything - * and return STATUS_CANCELLED. Any IRP's in the Pending and Process - * queues of the Ioq will be cancelled during FspIoqStop(). We must - * also cancel the PendingIrp we have in our hands. - */ - ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq)); - FspIopCompleteRequest(PendingIrp, STATUS_CANCELLED); - return STATUS_CANCELLED; - } + NextRequest = FspFsctlTransactProduceRequest( + Request, PendingIrpRequest->Size, SystemBufferEnd); + /* this should not fail as we have already checked that we have enough space */ + ASSERT(0 != NextRequest); - /* check that we have enough space before pulling the next pending IRP off the queue */ - if ((PUINT8)Request + FSP_FSCTL_TRANSACT_REQ_SIZEMAX > SystemBufferEnd) - break; + RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size); + Request = NextRequest; + + if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp)) + { + /* + * This can only happen if the Ioq was stopped. Abandon everything + * and return STATUS_CANCELLED. Any IRP's in the Pending and Process + * queues of the Ioq will be cancelled during FspIoqStop(). We must + * also cancel the PendingIrp we have in our hands. + */ + ASSERT(FspIoqStopped(&FsvrtDeviceExtension->Ioq)); + FspIopCompleteRequest(PendingIrp, STATUS_CANCELLED); + return STATUS_CANCELLED; + } + + /* check that we have enough space before pulling the next pending IRP off the queue */ + if ((PUINT8)Request + FSP_FSCTL_TRANSACT_REQ_SIZEMAX > SystemBufferEnd) + break; + } PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, 0); if (0 == PendingIrp) break; } + + if (Request == SystemBuffer) + goto retry; + RtlZeroMemory(Request, SystemBufferEnd - (PUINT8)Request); Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)SystemBuffer; diff --git a/src/sys/iop.c b/src/sys/iop.c index 50b91a04..3010962a 100644 --- a/src/sys/iop.c +++ b/src/sys/iop.c @@ -8,10 +8,12 @@ NTSTATUS FspIopCreateRequest( PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_FSCTL_TRANSACT_REQ **PRequest); +NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request); VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspIopCreateRequest) +#pragma alloc_text(PAGE, FspIopDispatchPrepare) #pragma alloc_text(PAGE, FspIopDispatchComplete) #endif @@ -74,6 +76,19 @@ VOID FspIopCompleteRequestEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceRelease) FspDeviceRelease(DeviceObject); } +NTSTATUS FspIopDispatchPrepare(PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) +{ + PAGED_CODE(); + + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + + ASSERT(IRP_MJ_MAXIMUM_FUNCTION >= IrpSp->MajorFunction); + if (0 != FspIopPrepareFunction[IrpSp->MajorFunction]) + return FspIopPrepareFunction[IrpSp->MajorFunction](Irp, Request); + else + return STATUS_SUCCESS; +} + VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) { PAGED_CODE(); @@ -86,4 +101,5 @@ VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) FspIopCompleteFunction[IrpSp->MajorFunction](Irp, Response); } +FSP_IOPREP_DISPATCH *FspIopPrepareFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];