[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] Improve Xenfilt power and default IRP handling.
On 14/03/2022 18:01, Martin Harvey wrote:This is a very large patch given absolutely no explanation. It really needs a *much* more comprehensive commit comment... even be broken down into multiple incremental patches, e.g. maybe doing FDO and PDO separately. Signed-off-by: Martin Harvey <martin.harvey@xxxxxxxxxx> --- src/common/util.h | 8 + src/xenfilt/fdo.c | 785 ++++++++++++--------------------------------- src/xenfilt/pdo.c | 790 ++++++++++++---------------------------------- 3 files changed, 411 insertions(+), 1172 deletions(-) diff --git a/src/common/util.h b/src/common/util.h index 36a36dd..fb9b9b7 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -36,6 +36,14 @@#include "assert.h" +typedef enum _XEN_IRP_STRATEGY {+ XEN_IRP_PASSDOWN_TRANSPARENT, + XEN_IRP_HANDLE_INDISPATCH_AND_COMPLETE, + XEN_IRP_HANDLE_INDISPATCH_PASSDOWN, + XEN_IRP_HANDLE_INCOMPLETION, I'm not keen on these names. What is 'incompletion'? I.e. your use of '_' or lack thereof seems rather arbitrary. + XEN_IRP_STRATEGY_MAX +} XEN_IRP_STRATEGY, *PXEN_IRP_STRATEGY; + #define P2ROUNDUP(_x, _a) \ (-(-(_x) & -(_a)))diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.cindex 63fa7b3..5d43d01 100644 --- a/src/xenfilt/fdo.c +++ b/src/xenfilt/fdo.c @@ -59,11 +59,6 @@ struct _XENFILT_FDO { PDEVICE_OBJECT PhysicalDeviceObject; CHAR Name[MAXNAMELEN];- PXENFILT_THREAD SystemPowerThread;- PIRP SystemPowerIrp; - PXENFILT_THREAD DevicePowerThread; - PIRP DevicePowerIrp; - MUTEX Mutex; LIST_ENTRY List; ULONG References; @@ -1004,6 +999,26 @@ fail1: return status; }+static NTSTATUS+FdoDispatchDefault( + IN PXENFILT_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + return status; + +fail1: + Error("fail1 (%08x)\n", status); + return status; +} + + static NTSTATUS FdoDispatchPnp( IN PXENFILT_FDO Fdo, @@ -1055,524 +1070,135 @@ FdoDispatchPnp( break;default:- status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); - if (!NT_SUCCESS(status)) - goto fail1; - - IoSkipCurrentIrpStackLocation(Irp); - - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); + status = FdoDispatchDefault(Fdo, Irp); break; }- return status;- -fail1: - Error("fail1 (%08x)\n", status); - - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -FdoSetDevicePowerUp( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_STATE PowerState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - - ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo)); - - status = FdoForwardIrpSynchronously(Fdo, Irp); - if (!NT_SUCCESS(status)) - goto done; - - Trace("%s: %s -> %s\n", - __FdoGetName(Fdo), - DevicePowerStateName(__FdoGetDevicePowerState(Fdo)), - DevicePowerStateName(DeviceState)); - - PowerState.DeviceState = DeviceState; - PoSetPowerState(Fdo->Dx->DeviceObject, - DevicePowerState, - PowerState); - - __FdoSetDevicePowerState(Fdo, DeviceState); - -done: - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -FdoSetDevicePowerDown( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_STATE PowerState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - - ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo)); - - Trace("%s: %s -> %s\n", - __FdoGetName(Fdo), - DevicePowerStateName(__FdoGetDevicePowerState(Fdo)), - DevicePowerStateName(DeviceState)); - - PowerState.DeviceState = DeviceState; - PoSetPowerState(Fdo->Dx->DeviceObject, - DevicePowerState, - PowerState); - - __FdoSetDevicePowerState(Fdo, DeviceState); - - status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -FdoSetDevicePower( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_ACTION PowerAction; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; - - Trace("%s: ====> (%s:%s)\n", - __FdoGetName(Fdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction)); - - if (DeviceState == __FdoGetDevicePowerState(Fdo)) { - status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - goto done; - } - - status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ? - FdoSetDevicePowerUp(Fdo, Irp) : - FdoSetDevicePowerDown(Fdo, Irp); - -done: - Trace("%s: <==== (%s:%s)(%08x)\n", - __FdoGetName(Fdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction), - status); - return status; -} - -static NTSTATUS -FdoSetSystemPowerUp( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo)); - - status = FdoForwardIrpSynchronously(Fdo, Irp); - if (!NT_SUCCESS(status)) - goto done; - - Trace("%s: %s -> %s\n", - __FdoGetName(Fdo), - SystemPowerStateName(__FdoGetSystemPowerState(Fdo)), - SystemPowerStateName(SystemState)); - - __FdoSetSystemPowerState(Fdo, SystemState); - -done: - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -FdoSetSystemPowerDown( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); - - Trace("%s: %s -> %s\n", - __FdoGetName(Fdo), - SystemPowerStateName(__FdoGetSystemPowerState(Fdo)), - SystemPowerStateName(SystemState)); - - __FdoSetSystemPowerState(Fdo, SystemState); - - status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -FdoSetSystemPower( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - POWER_ACTION PowerAction; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; - - Trace("%s: ====> (%s:%s)\n", - __FdoGetName(Fdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction)); - - if (SystemState == __FdoGetSystemPowerState(Fdo)) { - status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - goto done; - } - - status = (SystemState < __FdoGetSystemPowerState(Fdo)) ? - FdoSetSystemPowerUp(Fdo, Irp) : - FdoSetSystemPowerDown(Fdo, Irp); - -done: - Trace("%s: <==== (%s:%s)(%08x)\n", - __FdoGetName(Fdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction), - status); - return status; -} - -static NTSTATUS -FdoQueryDevicePowerUp( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - - ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo)); - - status = FdoForwardIrpSynchronously(Fdo, Irp); - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; }static NTSTATUS-FdoQueryDevicePowerDown( +FdoDispatchPowerImmediate( Is there a non-immediate variant? I can't see it. IN PXENFILT_FDO Fdo, IN PIRP Irp ) { - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; + NTSTATUS status = STATUS_INTERNAL_ERROR; + PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp); + UCHAR MinorFunction = StackLocation->MinorFunction;- ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo));- - status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -FdoQueryDevicePower( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_ACTION PowerAction; - NTSTATUS status; + if (MinorFunction != IRP_MN_SET_POWER) + goto fail1;- StackLocation = IoGetCurrentIrpStackLocation(Irp);- DeviceState = StackLocation->Parameters.Power.State.DeviceState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; + POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;- Trace("%s: ====> (%s:%s)\n",- __FdoGetName(Fdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction)); + switch (PowerType) { + case DevicePowerState: + POWER_STATE PowerState; + DEVICE_POWER_STATE DeviceState = StackLocation->Parameters.Power.State.DeviceState; + if (DeviceState >= __FdoGetDevicePowerState(Fdo)) + goto fail3;- if (DeviceState == __FdoGetDevicePowerState(Fdo)) {- status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); + __FdoSetDevicePowerState(Fdo, DeviceState); + PowerState.DeviceState = DeviceState; + PoSetPowerState(__FdoGetDeviceObject(Fdo), + DevicePowerState, + PowerState); + break; + case SystemPowerState: + SYSTEM_POWER_STATE SystemState = StackLocation->Parameters.Power.State.SystemState; + if (SystemState >= __FdoGetSystemPowerState(Fdo)) + goto fail3;- goto done;+ __FdoSetSystemPowerState(Fdo, SystemState); + break; + default: + goto fail2; }- status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ?- FdoQueryDevicePowerUp(Fdo, Irp) : - FdoQueryDevicePowerDown(Fdo, Irp); - -done: - Trace("%s: <==== (%s:%s)(%08x)\n", - __FdoGetName(Fdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction), - status); - return status; -} - -static NTSTATUS -FdoQuerySystemPowerUp( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo)); - - status = FdoForwardIrpSynchronously(Fdo, Irp); - - IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS;+fail3:+ Error("fail3 (%08x)\n", status); We don't need to spit status out at every fail level. +fail2: + Error("fail2 (%08x)\n", status); +fail1: + Error("fail1 (%08x)\n", status); return status; }-static NTSTATUS-FdoQuerySystemPowerDown( +static VOID +FdoCompletionPower( IN PXENFILT_FDO Fdo, IN PIRP Irp - ) +) { - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; + PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp); + UCHAR MinorFunction = StackLocation->MinorFunction;- StackLocation = IoGetCurrentIrpStackLocation(Irp);- SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); - - status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} + if (MinorFunction != IRP_MN_SET_POWER) + goto fail1;-static NTSTATUS-FdoQuerySystemPower( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - POWER_ACTION PowerAction; - NTSTATUS status; + POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;- StackLocation = IoGetCurrentIrpStackLocation(Irp);- SystemState = StackLocation->Parameters.Power.State.SystemState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; + switch (PowerType) { + case DevicePowerState: + POWER_STATE PowerState; + DEVICE_POWER_STATE DeviceState = StackLocation->Parameters.Power.State.DeviceState; + if (DeviceState <= __FdoGetDevicePowerState(Fdo)) + goto fail3;- Trace("%s: ====> (%s:%s)\n",- __FdoGetName(Fdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction)); + PowerState.DeviceState = DeviceState; + PoSetPowerState(__FdoGetDeviceObject(Fdo), + DevicePowerState, + PowerState); + __FdoSetDevicePowerState(Fdo, DeviceState);- if (SystemState == __FdoGetSystemPowerState(Fdo)) {- status = FdoForwardIrpSynchronously(Fdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + case SystemPowerState: + SYSTEM_POWER_STATE SystemState = StackLocation->Parameters.Power.State.SystemState; + if (SystemState <= __FdoGetSystemPowerState(Fdo)) + goto fail3;- goto done;+ __FdoSetSystemPowerState(Fdo, SystemState); + break; + default: + goto fail2; }- status = (SystemState < __FdoGetSystemPowerState(Fdo)) ?- FdoQuerySystemPowerUp(Fdo, Irp) : - FdoQuerySystemPowerDown(Fdo, Irp); - -done: - Trace("%s: <==== (%s:%s)(%08x)\n", - __FdoGetName(Fdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction), - status); + return;- return status;+fail3: + Error("fail3\n"); +fail2: + Error("fail2\n"); +fail1: + Error("fail1"); }+__drv_functionClass(IO_COMPLETION_ROUTINE)+__drv_sameIRQL static NTSTATUS -FdoDevicePower( - IN PXENFILT_THREAD Self, +FdoDispatchPowerCompletionV2( Ick. 'V2'? Really? What is V2 about it? + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PVOID Context ) { PXENFILT_FDO Fdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; - - if (Fdo->DevicePowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } - - if (ThreadIsAlerted(Self)) - break; - - Irp = Fdo->DevicePowerIrp; - - if (Irp == NULL) - continue;- Fdo->DevicePowerIrp = NULL;- KeMemoryBarrier(); - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = StackLocation->MinorFunction; - - switch (StackLocation->MinorFunction) { - case IRP_MN_SET_POWER: - (VOID) FdoSetDevicePower(Fdo, Irp); - break; - - case IRP_MN_QUERY_POWER: - (VOID) FdoQueryDevicePower(Fdo, Irp); - break; + UNREFERENCED_PARAMETER(DeviceObject);- default:- ASSERT(FALSE); - break; - } + if (Irp->PendingReturned) + IoMarkIrpPending(Irp);- IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);- } + //Assumption don't need STATUS_MORE_PROCESSING_REQUIRED. + FdoCompletionPower(Fdo, Irp);+ IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);return STATUS_SUCCESS; }-static NTSTATUS-FdoSystemPower( - IN PXENFILT_THREAD Self, - IN PVOID Context - ) -{ - PXENFILT_FDO Fdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; - - if (Fdo->SystemPowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } - - if (ThreadIsAlerted(Self)) - break; - - Irp = Fdo->SystemPowerIrp; - - if (Irp == NULL) - continue; - - Fdo->SystemPowerIrp = NULL; - KeMemoryBarrier(); - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = StackLocation->MinorFunction; - - switch (StackLocation->MinorFunction) { - case IRP_MN_SET_POWER: - (VOID) FdoSetSystemPower(Fdo, Irp); - break; - - case IRP_MN_QUERY_POWER: - (VOID) FdoQuerySystemPower(Fdo, Irp); - break; - - default: - ASSERT(FALSE); - break; - } - - IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); - } - - return STATUS_SUCCESS; -}static NTSTATUSFdoDispatchPower( @@ -1582,104 +1208,125 @@ FdoDispatchPower( { PIO_STACK_LOCATION StackLocation; UCHAR MinorFunction; - POWER_STATE_TYPE PowerType; NTSTATUS status; - - status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); - if (!NT_SUCCESS(status)) - goto fail1; + XEN_IRP_STRATEGY strategy; + BOOLEAN HaveRemoveLock = FALSE;StackLocation = IoGetCurrentIrpStackLocation(Irp);MinorFunction = StackLocation->MinorFunction;- if (MinorFunction != IRP_MN_QUERY_POWER &&- MinorFunction != IRP_MN_SET_POWER) { - IoSkipCurrentIrpStackLocation(Irp); - - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); - - goto done; - } - - PowerType = StackLocation->Parameters.Power.Type; - - Trace("%s: ====> (%02x:%s)\n", - __FdoGetName(Fdo), - MinorFunction, - PowerMinorFunctionName(MinorFunction)); - - switch (PowerType) { - case DevicePowerState: - IoMarkIrpPending(Irp); - - ASSERT3P(Fdo->DevicePowerIrp, ==, NULL); - Fdo->DevicePowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Fdo->DevicePowerThread); - - status = STATUS_PENDING; + //Decide how we're going to handle this IRP. + switch(MinorFunction) { + case IRP_MN_QUERY_POWER: + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; //Dont fail, don't need to check queries. break; - - case SystemPowerState: - IoMarkIrpPending(Irp); - - ASSERT3P(Fdo->SystemPowerIrp, ==, NULL); - Fdo->SystemPowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Fdo->SystemPowerThread); - - status = STATUS_PENDING; + case IRP_MN_SET_POWER: + POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type; + + switch (PowerType) { + case DevicePowerState: + DEVICE_POWER_STATE DeviceState = StackLocation->Parameters.Power.State.DeviceState; + + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + //If fails, then pending removal or already removed, + //freshly initialized (or not). Consider status to return... Can we have more complete english in comments so they are clear? Also a space after the '//' please. + HaveRemoveLock = TRUE; + + if (DeviceState == __FdoGetDevicePowerState(Fdo)) { + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; No need for braces in this sequence (and similar elsewhere). + } else if (DeviceState < __FdoGetDevicePowerState(Fdo)) { + strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN; + } else { + strategy = XEN_IRP_HANDLE_INCOMPLETION; + } + case SystemPowerState: + SYSTEM_POWER_STATE SystemState = StackLocation->Parameters.Power.State.SystemState; + + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + //If fails, then pending removal or already removed, + //freshly initialized (or not). Consider status to return... + HaveRemoveLock = TRUE; + + if (SystemState == __FdoGetSystemPowerState(Fdo)) { + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; + } else if (SystemState < __FdoGetSystemPowerState(Fdo)) { + strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN; + } else { + strategy = XEN_IRP_HANDLE_INCOMPLETION; + } break; - + default: + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; + break; + } default: - IoSkipCurrentIrpStackLocation(Irp); - - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; break; }- Trace("%s: <==== (%02x:%s) (%08x)\n",- __FdoGetName(Fdo), - MinorFunction, - PowerMinorFunctionName(MinorFunction), - status); - -done: - return status; - -fail1: - Error("fail1 (%08x)\n", status); + switch(strategy) { + case XEN_IRP_HANDLE_INDISPATCH_PASSDOWN: + status = FdoDispatchPowerImmediate(Fdo, Irp); + if (!NT_SUCCESS(status)) + goto fail2; + //Fallthru. Is that a valid annotation format? + case XEN_IRP_PASSDOWN_TRANSPARENT: + default: + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + if (!NT_SUCCESS(status)) + goto fail3;- Irp->IoStatus.Status = status;- IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (HaveRemoveLock) + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); + break; + case XEN_IRP_HANDLE_INCOMPLETION: + IoMarkIrpPending(Irp); + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + FdoDispatchPowerCompletionV2, + Fdo, + TRUE, + TRUE, + TRUE); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + if (!NT_SUCCESS(status)) + goto fail4; + status = STATUS_PENDING; //Must return STATUS_PENDING after IoMarkIrpPending, whatever happens next. + break; + }return status;-} - -static NTSTATUS -FdoDispatchDefault( - IN PXENFILT_FDO Fdo, - IN PIRP Irp - ) -{ - NTSTATUS status; - - status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); - if (!NT_SUCCESS(status)) - goto fail1;- IoSkipCurrentIrpStackLocation(Irp);- - status = IoCallDriver(Fdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); +fail4: + //Error from lower driver, have remove lock, and completion routine. + //Comp routine shd be called on error to drop remove lock. + Error("fail4 (%08x)\n", status); + status = STATUS_PENDING; //Must return STATUS_PENDING after IoMarkIrpPending, whatever happens next. + return status; The whole point of fail labels is that they undo things in sequence and *only* fail1 returns. +fail3:+ //Error from lower driver, have remove lock, called down. + Error("fail3 (%08x)\n", status); + if (HaveRemoveLock) + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); return status;+fail2:+ //Immediate error, have remove lock, not called down. + Error("fail2 (%08x)\n", status); + if (HaveRemoveLock) + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); + //Fallthru. + fail1: + //Immediate error, no remove lock, not called down. Error("fail1 (%08x)\n", status);Irp->IoStatus.Status = status;@@ -1775,14 +1422,6 @@ FdoCreate( Fdo->LowerDeviceObject = LowerDeviceObject; Fdo->Type = Type;- status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);- if (!NT_SUCCESS(status)) - goto fail4; - - status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread); - if (!NT_SUCCESS(status)) - goto fail5; - status = __FdoSetDeviceID(Fdo); if (!NT_SUCCESS(status)) goto fail6; @@ -1822,20 +1461,6 @@ fail7: fail6: Error("fail6\n");- ThreadAlert(Fdo->DevicePowerThread);- ThreadJoin(Fdo->DevicePowerThread); - Fdo->DevicePowerThread = NULL; - -fail5: - Error("fail5\n"); - - ThreadAlert(Fdo->SystemPowerThread); - ThreadJoin(Fdo->SystemPowerThread); - Fdo->SystemPowerThread = NULL; - -fail4: - Error("fail4\n"); - Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN; Fdo->PhysicalDeviceObject = NULL; Fdo->LowerDeviceObject = NULL; @@ -1891,14 +1516,6 @@ FdoDestroy( __FdoClearInstanceID(Fdo); __FdoClearDeviceID(Fdo);- ThreadAlert(Fdo->DevicePowerThread);- ThreadJoin(Fdo->DevicePowerThread); - Fdo->DevicePowerThread = NULL; - - ThreadAlert(Fdo->SystemPowerThread); - ThreadJoin(Fdo->SystemPowerThread); - Fdo->SystemPowerThread = NULL; - Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN; Fdo->LowerDeviceObject = NULL; Fdo->PhysicalDeviceObject = NULL; diff --git a/src/xenfilt/pdo.c b/src/xenfilt/pdo.c index 741c2f3..ee2a049 100644 --- a/src/xenfilt/pdo.c +++ b/src/xenfilt/pdo.c @@ -56,11 +56,6 @@ struct _XENFILT_PDO { PDEVICE_OBJECT PhysicalDeviceObject; CHAR Name[MAXNAMELEN];- PXENFILT_THREAD SystemPowerThread;- PIRP SystemPowerIrp; - PXENFILT_THREAD DevicePowerThread; - PIRP DevicePowerIrp; - PXENFILT_FDO Fdo; BOOLEAN Missing; const CHAR *Reason; @@ -1101,6 +1096,26 @@ PdoEject( return status; }+static NTSTATUS+PdoDispatchDefault( + IN PXENFILT_PDO Pdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + return status; + +fail1: + Error("fail1 (%08x)\n", status); + return status; +} + + static NTSTATUS PdoDispatchPnp( IN PXENFILT_PDO Pdo, @@ -1164,528 +1179,136 @@ PdoDispatchPnp( break;default:- status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); - if (!NT_SUCCESS(status)) - goto fail1; - - IoSkipCurrentIrpStackLocation(Irp); - - status = IoCallDriver(Pdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); + status = PdoDispatchDefault(Pdo, Irp); break; }- return status;- -fail1: - Error("fail1 (%08x)\n", status); - - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -PdoSetDevicePowerUp( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_STATE PowerState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - - ASSERT3U(DeviceState, <, __PdoGetDevicePowerState(Pdo)); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - if (!NT_SUCCESS(status)) - goto done; - - Trace("%s: %s -> %s\n", - __PdoGetName(Pdo), - DevicePowerStateName(__PdoGetDevicePowerState(Pdo)), - DevicePowerStateName(DeviceState)); - - PowerState.DeviceState = DeviceState; - PoSetPowerState(__PdoGetDeviceObject(Pdo), - DevicePowerState, - PowerState); - - __PdoSetDevicePowerState(Pdo, DeviceState); - -done: - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; }-static NTSTATUS-PdoSetDevicePowerDown( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_STATE PowerState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - - ASSERT3U(DeviceState, >, __PdoGetDevicePowerState(Pdo)); - - Trace("%s: %s -> %s\n", - __PdoGetName(Pdo), - DevicePowerStateName(__PdoGetDevicePowerState(Pdo)), - DevicePowerStateName(DeviceState)); - - PowerState.DeviceState = DeviceState; - PoSetPowerState(__PdoGetDeviceObject(Pdo), - DevicePowerState, - PowerState); - - __PdoSetDevicePowerState(Pdo, DeviceState); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -}static NTSTATUS-PdoSetDevicePower( +PdoDispatchPowerImmediate( IN PXENFILT_PDO Pdo, IN PIRP Irp ) { - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_ACTION PowerAction; - NTSTATUS status; + NTSTATUS status = STATUS_INTERNAL_ERROR; + PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp); + UCHAR MinorFunction = StackLocation->MinorFunction;- StackLocation = IoGetCurrentIrpStackLocation(Irp);- DeviceState = StackLocation->Parameters.Power.State.DeviceState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; - - Trace("%s: ====> (%s:%s)\n", - __PdoGetName(Pdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction)); - - if (DeviceState == __PdoGetDevicePowerState(Pdo)) { - status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - goto done; - } - - status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ? - PdoSetDevicePowerUp(Pdo, Irp) : - PdoSetDevicePowerDown(Pdo, Irp); - -done: - Trace("%s: <==== (%s:%s)(%08x)\n", - __PdoGetName(Pdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction), - status); - return status; -} - -static NTSTATUS -PdoSetSystemPowerUp( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, <, __PdoGetSystemPowerState(Pdo)); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - if (!NT_SUCCESS(status)) - goto done; - - Trace("%s: %s -> %s\n", - __PdoGetName(Pdo), - SystemPowerStateName(__PdoGetSystemPowerState(Pdo)), - SystemPowerStateName(SystemState)); - - __PdoSetSystemPowerState(Pdo, SystemState); - -done: - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -PdoSetSystemPowerDown( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, >, __PdoGetSystemPowerState(Pdo)); - - Trace("%s: %s -> %s\n", - __PdoGetName(Pdo), - SystemPowerStateName(__PdoGetSystemPowerState(Pdo)), - SystemPowerStateName(SystemState)); - - __PdoSetSystemPowerState(Pdo, SystemState); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -PdoSetSystemPower( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - POWER_ACTION PowerAction; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; - - Trace("%s: ====> (%s:%s)\n", - __PdoGetName(Pdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction)); - - if (SystemState == __PdoGetSystemPowerState(Pdo)) { - status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - goto done; - } - - status = (SystemState < __PdoGetSystemPowerState(Pdo)) ? - PdoSetSystemPowerUp(Pdo, Irp) : - PdoSetSystemPowerDown(Pdo, Irp); - -done: - Trace("%s: <==== (%s:%s)(%08x)\n", - __PdoGetName(Pdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction), - status); - return status; -} - -static NTSTATUS -PdoQueryDevicePowerUp( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - - ASSERT3U(DeviceState, <, __PdoGetDevicePowerState(Pdo)); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -PdoQueryDevicePowerDown( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - - ASSERT3U(DeviceState, >, __PdoGetDevicePowerState(Pdo)); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -PdoQueryDevicePower( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - DEVICE_POWER_STATE DeviceState; - POWER_ACTION PowerAction; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - DeviceState = StackLocation->Parameters.Power.State.DeviceState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; + if (MinorFunction != IRP_MN_SET_POWER) + goto fail1;- Trace("%s: ====> (%s:%s)\n",- __PdoGetName(Pdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction)); + POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;- if (DeviceState == __PdoGetDevicePowerState(Pdo)) {- status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); + switch (PowerType) { + case DevicePowerState: + POWER_STATE PowerState; + DEVICE_POWER_STATE DeviceState = StackLocation->Parameters.Power.State.DeviceState; + if (DeviceState >= __PdoGetDevicePowerState(Pdo)) + goto fail3; + + __PdoSetDevicePowerState(Pdo, DeviceState); + PowerState.DeviceState = DeviceState; + PoSetPowerState(__PdoGetDeviceObject(Pdo), + DevicePowerState, + PowerState); + break; + case SystemPowerState: + SYSTEM_POWER_STATE SystemState = StackLocation->Parameters.Power.State.SystemState; + if (SystemState >= __PdoGetSystemPowerState(Pdo)) + goto fail3;- goto done;+ __PdoSetSystemPowerState(Pdo, SystemState); + break; + default: + goto fail2; }- status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ?- PdoQueryDevicePowerUp(Pdo, Irp) : - PdoQueryDevicePowerDown(Pdo, Irp); - -done: - Trace("%s: <==== (%s:%s)(%08x)\n", - __PdoGetName(Pdo), - DevicePowerStateName(DeviceState), - PowerActionName(PowerAction), - status); - return status; -} - -static NTSTATUS -PdoQuerySystemPowerUp( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, <, __PdoGetSystemPowerState(Pdo)); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return status; -} - -static NTSTATUS -PdoQuerySystemPowerDown( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - NTSTATUS status; - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - SystemState = StackLocation->Parameters.Power.State.SystemState; - - ASSERT3U(SystemState, >, __PdoGetSystemPowerState(Pdo)); - - status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS;+fail3:+ Error("fail3 (%08x)\n", status); +fail2: + Error("fail2 (%08x)\n", status); +fail1: + Error("fail1 (%08x)\n", status); return status; }-static NTSTATUS-PdoQuerySystemPower( +static VOID +PdoCompletionPower( IN PXENFILT_PDO Pdo, IN PIRP Irp - ) +) { - PIO_STACK_LOCATION StackLocation; - SYSTEM_POWER_STATE SystemState; - POWER_ACTION PowerAction; - NTSTATUS status; + PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp); + UCHAR MinorFunction = StackLocation->MinorFunction;- StackLocation = IoGetCurrentIrpStackLocation(Irp);- SystemState = StackLocation->Parameters.Power.State.SystemState; - PowerAction = StackLocation->Parameters.Power.ShutdownType; + if (MinorFunction != IRP_MN_SET_POWER) + goto fail1;- Trace("%s: ====> (%s:%s)\n",- __PdoGetName(Pdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction)); + POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;- if (SystemState == __PdoGetSystemPowerState(Pdo)) {- status = PdoForwardIrpSynchronously(Pdo, Irp); - IoCompleteRequest(Irp, IO_NO_INCREMENT); + switch (PowerType) { + case DevicePowerState: + POWER_STATE PowerState; + DEVICE_POWER_STATE DeviceState = StackLocation->Parameters.Power.State.DeviceState; + if (DeviceState <= __PdoGetDevicePowerState(Pdo)) + goto fail3; + + PowerState.DeviceState = DeviceState; + PoSetPowerState(__PdoGetDeviceObject(Pdo), + DevicePowerState, + PowerState); + __PdoSetDevicePowerState(Pdo, DeviceState); + + break; + case SystemPowerState: + SYSTEM_POWER_STATE SystemState = StackLocation->Parameters.Power.State.SystemState; + if (SystemState <= __PdoGetSystemPowerState(Pdo)) + goto fail3;- goto done;+ __PdoSetSystemPowerState(Pdo, SystemState); + break; + default: + goto fail2; }- status = (SystemState < __PdoGetSystemPowerState(Pdo)) ?- PdoQuerySystemPowerUp(Pdo, Irp) : - PdoQuerySystemPowerDown(Pdo, Irp); + return;-done:- Trace("%s: <==== (%s:%s)(%08x)\n", - __PdoGetName(Pdo), - SystemPowerStateName(SystemState), - PowerActionName(PowerAction), - status); - - return status; +fail3: + Error("fail3\n"); +fail2: + Error("fail2\n"); +fail1: + Error("fail1"); }+__drv_functionClass(IO_COMPLETION_ROUTINE)+__drv_sameIRQL static NTSTATUS -PdoDevicePower( - IN PXENFILT_THREAD Self, +PdoDispatchPowerCompletionV2( I assume this means that you largely duped the FDO code. Please please find some better names. + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PVOID Context ) { PXENFILT_PDO Pdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; - - if (Pdo->DevicePowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } - - if (ThreadIsAlerted(Self)) - break; - - Irp = Pdo->DevicePowerIrp; - - if (Irp == NULL) - continue; - - Pdo->DevicePowerIrp = NULL; - KeMemoryBarrier(); - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = StackLocation->MinorFunction;- switch (StackLocation->MinorFunction) {- case IRP_MN_SET_POWER: - (VOID) PdoSetDevicePower(Pdo, Irp); - break; - - case IRP_MN_QUERY_POWER: - (VOID) PdoQueryDevicePower(Pdo, Irp); - break; + UNREFERENCED_PARAMETER(DeviceObject);- default:- ASSERT(FALSE); - break; - } + if (Irp->PendingReturned) + IoMarkIrpPending(Irp);- IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);- } + //Assumption don't need STATUS_MORE_PROCESSING_REQUIRED. + PdoCompletionPower(Pdo, Irp);+ IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);return STATUS_SUCCESS; }-static NTSTATUS-PdoSystemPower( - IN PXENFILT_THREAD Self, - IN PVOID Context - ) -{ - PXENFILT_PDO Pdo = Context; - PKEVENT Event; - - Event = ThreadGetEvent(Self); - - for (;;) { - PIRP Irp; - PIO_STACK_LOCATION StackLocation; - UCHAR MinorFunction; - - if (Pdo->SystemPowerIrp == NULL) { - (VOID) KeWaitForSingleObject(Event, - Executive, - KernelMode, - FALSE, - NULL); - KeClearEvent(Event); - } - - if (ThreadIsAlerted(Self)) - break; - - Irp = Pdo->SystemPowerIrp; - - if (Irp == NULL) - continue; - - Pdo->SystemPowerIrp = NULL; - KeMemoryBarrier(); - - StackLocation = IoGetCurrentIrpStackLocation(Irp); - MinorFunction = StackLocation->MinorFunction; - - switch (StackLocation->MinorFunction) { - case IRP_MN_SET_POWER: - (VOID) PdoSetSystemPower(Pdo, Irp); - break; - - case IRP_MN_QUERY_POWER: - (VOID) PdoQuerySystemPower(Pdo, Irp); - break; - - default: - ASSERT(FALSE); - break; - } - - IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); - } - - return STATUS_SUCCESS; -}static NTSTATUSPdoDispatchPower( @@ -1695,104 +1318,125 @@ PdoDispatchPower( { PIO_STACK_LOCATION StackLocation; UCHAR MinorFunction; - POWER_STATE_TYPE PowerType; NTSTATUS status; - - status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); - if (!NT_SUCCESS(status)) - goto fail1; + XEN_IRP_STRATEGY strategy; + BOOLEAN HaveRemoveLock = FALSE; Here an elsewhere... can we keep the declarations vertically aligned and at a tabstop? StackLocation = IoGetCurrentIrpStackLocation(Irp);MinorFunction = StackLocation->MinorFunction;- if (MinorFunction != IRP_MN_QUERY_POWER &&- MinorFunction != IRP_MN_SET_POWER) { - IoSkipCurrentIrpStackLocation(Irp); - - status = IoCallDriver(Pdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); - - goto done; - } - - PowerType = StackLocation->Parameters.Power.Type; - - Trace("%s: ====> (%02x:%s)\n", - __PdoGetName(Pdo), - MinorFunction, - PowerMinorFunctionName(MinorFunction)); - - switch (PowerType) { - case DevicePowerState: - IoMarkIrpPending(Irp); - - ASSERT3P(Pdo->DevicePowerIrp, ==, NULL); - Pdo->DevicePowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Pdo->DevicePowerThread); - - status = STATUS_PENDING; + //Decide how we're going to handle this IRP. + switch(MinorFunction) { + case IRP_MN_QUERY_POWER: + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; //Dont fail, don't need to check queries. break; + case IRP_MN_SET_POWER: + POWER_STATE_TYPE PowerType = StackLocation->Parameters.Power.Type;- case SystemPowerState:- IoMarkIrpPending(Irp); + switch (PowerType) { + case DevicePowerState: + DEVICE_POWER_STATE DeviceState = StackLocation->Parameters.Power.State.DeviceState;- ASSERT3P(Pdo->SystemPowerIrp, ==, NULL);- Pdo->SystemPowerIrp = Irp; - KeMemoryBarrier(); - - ThreadWake(Pdo->SystemPowerThread); - - status = STATUS_PENDING; + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + //If fails, then pending removal or already removed, + //freshly initialized (or not). Consider status to return... + HaveRemoveLock = TRUE; + + if (DeviceState == __PdoGetDevicePowerState(Pdo)) { + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; + } else if (DeviceState < __PdoGetDevicePowerState(Pdo)) { + strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN; + } else { + strategy = XEN_IRP_HANDLE_INCOMPLETION; + } + case SystemPowerState: + SYSTEM_POWER_STATE SystemState = StackLocation->Parameters.Power.State.SystemState; + + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + //If fails, then pending removal or already removed, + //freshly initialized (or not). Consider status to return... + HaveRemoveLock = TRUE; + + if (SystemState == __PdoGetSystemPowerState(Pdo)) { + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; + } else if (SystemState < __PdoGetSystemPowerState(Pdo)) { + strategy = XEN_IRP_HANDLE_INDISPATCH_PASSDOWN; + } else { + strategy = XEN_IRP_HANDLE_INCOMPLETION; + } break; - + default: + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; + break; + } default: - IoSkipCurrentIrpStackLocation(Irp); - - status = IoCallDriver(Pdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); + strategy = XEN_IRP_PASSDOWN_TRANSPARENT; break; }- Trace("%s: <==== (%02x:%s) (%08x)\n",- __PdoGetName(Pdo), - MinorFunction, - PowerMinorFunctionName(MinorFunction), - status); - -done: - return status; - -fail1: - Error("fail1 (%08x)\n", status); + switch(strategy) { + case XEN_IRP_HANDLE_INDISPATCH_PASSDOWN: + status = PdoDispatchPowerImmediate(Pdo, Irp); + if (!NT_SUCCESS(status)) + goto fail2; + //Fallthru. + case XEN_IRP_PASSDOWN_TRANSPARENT: + default: + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); + if (!NT_SUCCESS(status)) + goto fail3;- Irp->IoStatus.Status = status;- IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (HaveRemoveLock) + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); + break; + case XEN_IRP_HANDLE_INCOMPLETION: + IoMarkIrpPending(Irp); + IoCopyCurrentIrpStackLocationToNext(Irp); + IoSetCompletionRoutine(Irp, + PdoDispatchPowerCompletionV2, + Pdo, + TRUE, + TRUE, + TRUE); + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); + if (!NT_SUCCESS(status)) + goto fail4; + status = STATUS_PENDING; //Must return STATUS_PENDING after IoMarkIrpPending, whatever happens next. + break; + }return status;-} - -static NTSTATUS -PdoDispatchDefault( - IN PXENFILT_PDO Pdo, - IN PIRP Irp - ) -{ - NTSTATUS status;- status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);- if (!NT_SUCCESS(status)) - goto fail1; - - IoSkipCurrentIrpStackLocation(Irp); - - status = IoCallDriver(Pdo->LowerDeviceObject, Irp); - IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); +fail4: + //Error from lower driver, have remove lock, and completion routine. + //Comp routine shd be called on error to drop remove lock. + Error("fail4 (%08x)\n", status); + status = STATUS_PENDING; //Must return STATUS_PENDING after IoMarkIrpPending, whatever happens next. + return status;+fail3:+ //Error from lower driver, have remove lock, called down. + Error("fail3 (%08x)\n", status); + if (HaveRemoveLock) + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); return status;+fail2:+ //Immediate error, have remove lock, not called down. + Error("fail2 (%08x)\n", status); + if (HaveRemoveLock) + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); + //Fallthru. + fail1: + //Immediate error, no remove lock, not called down. Error("fail1 (%08x)\n", status);Irp->IoStatus.Status = status;@@ -1907,14 +1551,6 @@ PdoCreate( Pdo->LowerDeviceObject = LowerDeviceObject; Pdo->Type = Type;- status = ThreadCreate(PdoSystemPower, Pdo, &Pdo->SystemPowerThread);- if (!NT_SUCCESS(status)) - goto fail4; - - status = ThreadCreate(PdoDevicePower, Pdo, &Pdo->DevicePowerThread); - if (!NT_SUCCESS(status)) - goto fail5; - status = PdoSetDeviceInformation(Pdo); if (!NT_SUCCESS(status)) goto fail6; @@ -1968,20 +1604,6 @@ fail7: fail6: Error("fail6\n");- ThreadAlert(Pdo->DevicePowerThread);- ThreadJoin(Pdo->DevicePowerThread); - Pdo->DevicePowerThread = NULL; - -fail5: - Error("fail5\n"); - - ThreadAlert(Pdo->SystemPowerThread); - ThreadJoin(Pdo->SystemPowerThread); - Pdo->SystemPowerThread = NULL; - -fail4: - Error("fail4\n"); - Pdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN; Pdo->PhysicalDeviceObject = NULL; Pdo->LowerDeviceObject = NULL; @@ -2040,14 +1662,6 @@ PdoDestroy(PdoClearDeviceInformation(Pdo); - ThreadAlert(Pdo->DevicePowerThread);- ThreadJoin(Pdo->DevicePowerThread); - Pdo->DevicePowerThread = NULL; - - ThreadAlert(Pdo->SystemPowerThread); - ThreadJoin(Pdo->SystemPowerThread); - Pdo->SystemPowerThread = NULL; - Pdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN; Pdo->PhysicalDeviceObject = NULL; Pdo->LowerDeviceObject = NULL; Paul
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |