[NTOS:PO]

- Pass the correct DeviceObject to PoRequestPowerIrp's callback
- Use the IRP stack to store callback parameters instead of a pool allocation as shown by the test

svn path=/trunk/; revision=69503
This commit is contained in:
Thomas Faber 2015-10-11 19:57:06 +00:00
parent a7c1b9e740
commit c0cd33da02
2 changed files with 36 additions and 43 deletions

View file

@ -15,14 +15,6 @@
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
typedef struct _REQUEST_POWER_ITEM
{
PREQUEST_POWER_COMPLETE CompletionRoutine;
POWER_STATE PowerState;
PVOID Context;
PDEVICE_OBJECT TopDeviceObject;
} REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM;
typedef struct _POWER_STATE_TRAVERSE_CONTEXT typedef struct _POWER_STATE_TRAVERSE_CONTEXT
{ {
SYSTEM_POWER_STATE SystemPowerState; SYSTEM_POWER_STATE SystemPowerState;
@ -45,21 +37,22 @@ PopRequestPowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context) IN PVOID Context)
{ {
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
PREQUEST_POWER_ITEM RequestPowerItem; PREQUEST_POWER_COMPLETE CompletionRoutine;
POWER_STATE PowerState;
Stack = IoGetNextIrpStackLocation(Irp); Stack = IoGetCurrentIrpStackLocation(Irp);
RequestPowerItem = (PREQUEST_POWER_ITEM)Context; CompletionRoutine = Context;
RequestPowerItem->CompletionRoutine(DeviceObject, PowerState.DeviceState = (ULONG_PTR)Stack->Parameters.Others.Argument3;
Stack->MinorFunction, CompletionRoutine(Stack->Parameters.Others.Argument1,
RequestPowerItem->PowerState, (UCHAR)(ULONG_PTR)Stack->Parameters.Others.Argument2,
RequestPowerItem->Context, PowerState,
Stack->Parameters.Others.Argument4,
&Irp->IoStatus); &Irp->IoStatus);
IoSkipCurrentIrpStackLocation(Irp);
IoFreeIrp(Irp); IoFreeIrp(Irp);
ObDereferenceObject(DeviceObject);
ObDereferenceObject(RequestPowerItem->TopDeviceObject);
ExFreePoolWithTag(Context, 'IRoP');
return STATUS_MORE_PROCESSING_REQUIRED; return STATUS_MORE_PROCESSING_REQUIRED;
} }
@ -521,59 +514,52 @@ PoRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject,
PDEVICE_OBJECT TopDeviceObject; PDEVICE_OBJECT TopDeviceObject;
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
PIRP Irp; PIRP Irp;
PREQUEST_POWER_ITEM RequestPowerItem;
if (MinorFunction != IRP_MN_QUERY_POWER if (MinorFunction != IRP_MN_QUERY_POWER
&& MinorFunction != IRP_MN_SET_POWER && MinorFunction != IRP_MN_SET_POWER
&& MinorFunction != IRP_MN_WAIT_WAKE) && MinorFunction != IRP_MN_WAIT_WAKE)
return STATUS_INVALID_PARAMETER_2; return STATUS_INVALID_PARAMETER_2;
RequestPowerItem = ExAllocatePoolWithTag(NonPagedPool,
sizeof(REQUEST_POWER_ITEM),
'IRoP');
if (!RequestPowerItem)
return STATUS_INSUFFICIENT_RESOURCES;
/* Always call the top of the device stack */ /* Always call the top of the device stack */
TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_POWER, Irp = IoAllocateIrp(TopDeviceObject->StackSize + 2, FALSE);
TopDeviceObject,
NULL,
0,
NULL,
NULL);
if (!Irp) if (!Irp)
{ {
ObDereferenceObject(TopDeviceObject); ObDereferenceObject(TopDeviceObject);
ExFreePoolWithTag(RequestPowerItem, 'IRoP');
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
/* POWER IRPs are always initialized with a status code of Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
STATUS_NOT_IMPLEMENTED */
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
IoSetNextIrpStackLocation(Irp);
Stack = IoGetNextIrpStackLocation(Irp); Stack = IoGetNextIrpStackLocation(Irp);
Stack->Parameters.Others.Argument1 = DeviceObject;
Stack->Parameters.Others.Argument2 = (PVOID)(ULONG_PTR)MinorFunction;
Stack->Parameters.Others.Argument3 = (PVOID)(ULONG_PTR)PowerState.DeviceState;
Stack->Parameters.Others.Argument4 = Context;
Stack->DeviceObject = TopDeviceObject;
IoSetNextIrpStackLocation(Irp);
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MajorFunction = IRP_MJ_POWER;
Stack->MinorFunction = MinorFunction; Stack->MinorFunction = MinorFunction;
if (MinorFunction == IRP_MN_WAIT_WAKE) if (MinorFunction == IRP_MN_WAIT_WAKE)
{
Stack->Parameters.WaitWake.PowerState = PowerState.SystemState; Stack->Parameters.WaitWake.PowerState = PowerState.SystemState;
}
else else
{ {
Stack->Parameters.Power.Type = DevicePowerState; Stack->Parameters.Power.Type = DevicePowerState;
Stack->Parameters.Power.State = PowerState; Stack->Parameters.Power.State = PowerState;
} }
RequestPowerItem->CompletionRoutine = CompletionFunction;
RequestPowerItem->PowerState = PowerState;
RequestPowerItem->Context = Context;
RequestPowerItem->TopDeviceObject = TopDeviceObject;
if (pIrp != NULL) if (pIrp != NULL)
*pIrp = Irp; *pIrp = Irp;
IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, RequestPowerItem, TRUE, TRUE, TRUE); IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, CompletionFunction, TRUE, TRUE, TRUE);
PoCallDriver(TopDeviceObject, Irp); PoCallDriver(TopDeviceObject, Irp);
/* Always return STATUS_PENDING. The completion routine /* Always return STATUS_PENDING. The completion routine

View file

@ -136,10 +136,15 @@ RequestedPowerCompletion(
ok_eq_uint(Irp->StackCount, 5); ok_eq_uint(Irp->StackCount, 5);
ok_eq_uint(Irp->CurrentLocation, 4); ok_eq_uint(Irp->CurrentLocation, 4);
ok_eq_pointer(Irp->Tail.Overlay.Thread, NULL);
IoStackLocation = IoGetCurrentIrpStackLocation(Irp); IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
ok_eq_uint(IoStackLocation->MajorFunction, 0);
ok_eq_uint(IoStackLocation->MinorFunction, 0);
ok_eq_pointer(IoStackLocation->CompletionRoutine, NULL);
ok_eq_pointer(IoStackLocation->Context, NULL);
ok_eq_pointer(IoStackLocation->Parameters.Others.Argument1, DeviceObject); ok_eq_pointer(IoStackLocation->Parameters.Others.Argument1, DeviceObject);
ok_eq_pointer(IoStackLocation->Parameters.Others.Argument2, (PVOID)(ULONG_PTR)MinorFunction); ok_eq_pointer(IoStackLocation->Parameters.Others.Argument2, (PVOID)(ULONG_PTR)MinorFunction);
ok_eq_pointer(IoStackLocation->Parameters.Others.Argument3, (PVOID)PowerState.SystemState); ok_eq_pointer(IoStackLocation->Parameters.Others.Argument3, (PVOID)(ULONG_PTR)PowerState.SystemState);
ok_eq_pointer(IoStackLocation->Parameters.Others.Argument4, Context); ok_eq_pointer(IoStackLocation->Parameters.Others.Argument4, Context);
} }
@ -158,8 +163,10 @@ RequestedPowerIrpHandler(
ok_eq_uint(Irp->StackCount, 5); ok_eq_uint(Irp->StackCount, 5);
ok_eq_ulongptr(Irp->IoStatus.Information, 0); ok_eq_ulongptr(Irp->IoStatus.Information, 0);
ok_eq_hex(Irp->IoStatus.Status, STATUS_NOT_SUPPORTED); ok_eq_hex(Irp->IoStatus.Status, STATUS_NOT_SUPPORTED);
ok_eq_pointer(Irp->Tail.Overlay.Thread, NULL);
ok_eq_uint(IoStackLocation->MajorFunction, IRP_MJ_POWER); ok_eq_uint(IoStackLocation->MajorFunction, IRP_MJ_POWER);
ok_eq_uint(IoStackLocation->MinorFunction, IRP_MN_SET_POWER); ok_eq_uint(IoStackLocation->MinorFunction, IRP_MN_SET_POWER);
ok_eq_pointer(IoStackLocation->Context, RequestedPowerCompletion);
ok_eq_uint(IoStackLocation->Parameters.Power.Type, DevicePowerState); ok_eq_uint(IoStackLocation->Parameters.Power.Type, DevicePowerState);
ok_eq_uint(IoStackLocation->Parameters.Power.State.DeviceState, PowerDeviceD0); ok_eq_uint(IoStackLocation->Parameters.Power.State.DeviceState, PowerDeviceD0);