diff --git a/src/sys/driver.h b/src/sys/driver.h index fd4db509..355d82d1 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -796,6 +796,8 @@ NTSTATUS FspWqCreateAndPostIrpWorkItem(PIRP Irp, FSP_IOP_REQUEST_WORK *WorkRoutine, FSP_IOP_REQUEST_FINI *RequestFini, BOOLEAN CreateAndPost); VOID FspWqPostIrpWorkItem(PIRP Irp); +VOID FspWqOplockPrepare(PVOID Context, PIRP Irp); +VOID FspWqOplockComplete(PVOID Context, PIRP Irp); #define FspWqCreateIrpWorkItem(I, RW, RF)\ FspWqCreateAndPostIrpWorkItem(I, RW, RF, FALSE) #define FspWqRepostIrpWorkItem(I, RW, RF)\ diff --git a/src/sys/wq.c b/src/sys/wq.c index 5d3fc242..eb2bd85f 100644 --- a/src/sys/wq.c +++ b/src/sys/wq.c @@ -17,31 +17,59 @@ #include +NTSTATUS FspWqCreateAndPostIrpWorkItem(PIRP Irp, + FSP_IOP_REQUEST_WORK *WorkRoutine, FSP_IOP_REQUEST_FINI *RequestFini, + BOOLEAN CreateAndPost); +VOID FspWqPostIrpWorkItem(PIRP Irp); static VOID FspWqWorkRoutine(PVOID Context); +VOID FspWqOplockPrepare(PVOID Context, PIRP Irp); +VOID FspWqOplockComplete(PVOID Context, PIRP Irp); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FspWqCreateAndPostIrpWorkItem) +#pragma alloc_text(PAGE, FspWqPostIrpWorkItem) +#pragma alloc_text(PAGE, FspWqWorkRoutine) +#pragma alloc_text(PAGE, FspWqOplockPrepare) +#pragma alloc_text(PAGE, FspWqOplockComplete) +#endif + +static inline +NTSTATUS FspWqPrepareIrpWorkItem(PIRP Irp) +{ + NTSTATUS Result; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + + /* lock/buffer the user buffer */ + if ((IRP_MJ_READ == IrpSp->MajorFunction || IRP_MJ_WRITE == IrpSp->MajorFunction) && + !FlagOn(IrpSp->MinorFunction, IRP_MN_MDL)) + { + if (IRP_MJ_READ == IrpSp->MajorFunction) + Result = FspLockUserBuffer(Irp, IrpSp->Parameters.Read.Length, IoWriteAccess); + else + Result = FspLockUserBuffer(Irp, IrpSp->Parameters.Write.Length, IoReadAccess); + if (!NT_SUCCESS(Result)) + return Result; + } + + return STATUS_SUCCESS; +} NTSTATUS FspWqCreateAndPostIrpWorkItem(PIRP Irp, FSP_IOP_REQUEST_WORK *WorkRoutine, FSP_IOP_REQUEST_FINI *RequestFini, BOOLEAN CreateAndPost) { + PAGED_CODE(); + FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); FSP_FSCTL_TRANSACT_REQ_WORK_ITEM *RequestWorkItem; if (0 == Request) { NTSTATUS Result; - PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); - /* lock/buffer the user buffer */ - if ((IRP_MJ_READ == IrpSp->MajorFunction || IRP_MJ_WRITE == IrpSp->MajorFunction) && - !FlagOn(IrpSp->MinorFunction, IRP_MN_MDL)) - { - if (IRP_MJ_READ == IrpSp->MajorFunction) - Result = FspLockUserBuffer(Irp, IrpSp->Parameters.Read.Length, IoWriteAccess); - else - Result = FspLockUserBuffer(Irp, IrpSp->Parameters.Write.Length, IoReadAccess); - if (!NT_SUCCESS(Result)) - return Result; - } + Result = FspWqPrepareIrpWorkItem(Irp); + if (!NT_SUCCESS(Result)) + return Result; Result = FspIopCreateRequestAndWorkItem(Irp, 0, RequestFini, &Request); if (!NT_SUCCESS(Result)) @@ -77,9 +105,26 @@ NTSTATUS FspWqCreateAndPostIrpWorkItem(PIRP Irp, VOID FspWqPostIrpWorkItem(PIRP Irp) { + PAGED_CODE(); + FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); FSP_FSCTL_TRANSACT_REQ_WORK_ITEM *RequestWorkItem = FspIopRequestWorkItem(Request); +#if DBG + switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) + { + case IRP_MJ_CREATE: + ASSERT(0 != FspIopIrpResponse(Irp)); + break; + case IRP_MJ_READ: + case IRP_MJ_WRITE: + case IRP_MJ_DIRECTORY_CONTROL: + case IRP_MJ_LOCK_CONTROL: + default: + ASSERT(0); + break; + } +#endif ASSERT(Request->Hint == (UINT_PTR)Irp); ASSERT(0 != RequestWorkItem); ASSERT(0 != RequestWorkItem->WorkRoutine); @@ -90,6 +135,8 @@ VOID FspWqPostIrpWorkItem(PIRP Irp) static VOID FspWqWorkRoutine(PVOID Context) { + PAGED_CODE(); + PIRP Irp = Context; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject; @@ -125,3 +172,28 @@ static VOID FspWqWorkRoutine(PVOID Context) IoSetTopLevelIrp(0); } + +VOID FspWqOplockPrepare(PVOID Context, PIRP Irp) +{ + PAGED_CODE(); + + NTSTATUS Result; + + Result = FspWqPrepareIrpWorkItem(Irp); + if (!NT_SUCCESS(Result)) + /* + * Only way to communicate failure is through ExRaiseStatus. + * We will catch it in FspCheckOplock, etc. + */ + ExRaiseStatus(Result); +} + +VOID FspWqOplockComplete(PVOID Context, PIRP Irp) +{ + PAGED_CODE(); + + if (STATUS_SUCCESS == Irp->IoStatus.Status) + FspWqPostIrpWorkItem(Irp); + else + FspIopCompleteIrp(Irp, Irp->IoStatus.Status); +}