Implement PoRequestPowerIrp
Modified: trunk/reactos/ntoskrnl/po/power.c
_____
Modified: trunk/reactos/ntoskrnl/po/power.c
--- trunk/reactos/ntoskrnl/po/power.c 2005-07-02 14:05:38 UTC (rev
16379)
+++ trunk/reactos/ntoskrnl/po/power.c 2005-07-02 14:50:22 UTC (rev
16380)
@@ -6,12 +6,20 @@
* PURPOSE: Power Manager
*
* PROGRAMMERS: Casper S. Hornstrup (chorns(a)users.sourceforge.net)
+ * HervÚ Poussineau (hpoussin(a)reactos.com)
*/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
+typedef struct _REQUEST_POWER_ITEM
+{
+ PREQUEST_POWER_COMPLETE CompletionRoutine;
+ POWER_STATE PowerState;
+ PVOID Context;
+} REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM;
+
PDEVICE_NODE PopSystemPowerDeviceNode = NULL;
BOOLEAN PopAcpiPresent = FALSE;
@@ -57,8 +65,33 @@
return NULL;
}
+static
+NTSTATUS STDCALL
+PopRequestPowerIrpCompletion(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID Context)
+{
+ PIO_STACK_LOCATION Stack;
+ PREQUEST_POWER_ITEM RequestPowerItem;
+
+ Stack = IoGetNextIrpStackLocation(Irp);
+ RequestPowerItem = (PREQUEST_POWER_ITEM)Context;
+
+ RequestPowerItem->CompletionRoutine(
+ DeviceObject,
+ Stack->MinorFunction,
+ RequestPowerItem->PowerState,
+ RequestPowerItem->Context,
+ &Irp->IoStatus);
+
+ ExFreePool(&Irp->IoStatus);
+ ExFreePool(Context);
+ return STATUS_SUCCESS;
+}
+
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
STDCALL
@@ -68,9 +101,74 @@
IN POWER_STATE PowerState,
IN PREQUEST_POWER_COMPLETE CompletionFunction,
IN PVOID Context,
- OUT PIRP *Irp OPTIONAL)
+ OUT PIRP *pIrp OPTIONAL)
{
- return STATUS_NOT_IMPLEMENTED;
+ PDEVICE_OBJECT TopDeviceObject;
+ PIO_STACK_LOCATION Stack;
+ PIRP Irp;
+ PIO_STATUS_BLOCK IoStatusBlock;
+ PREQUEST_POWER_ITEM RequestPowerItem;
+ NTSTATUS Status;
+
+ if (MinorFunction != IRP_MN_QUERY_POWER
+ && MinorFunction != IRP_MN_SET_POWER
+ && MinorFunction != IRP_MN_WAIT_WAKE)
+ return STATUS_INVALID_PARAMETER_2;
+
+ RequestPowerItem = ExAllocatePool(NonPagedPool,
sizeof(REQUEST_POWER_ITEM));
+ if (!RequestPowerItem)
+ return STATUS_INSUFFICIENT_RESOURCES;
+ IoStatusBlock = ExAllocatePool(NonPagedPool,
sizeof(IO_STATUS_BLOCK));
+ if (!IoStatusBlock)
+ {
+ ExFreePool(RequestPowerItem);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Always call the top of the device stack */
+ TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
+
+ Irp = IoBuildSynchronousFsdRequest(
+ IRP_MJ_PNP,
+ TopDeviceObject,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ IoStatusBlock);
+ if (!Irp)
+ {
+ ExFreePool(RequestPowerItem);
+ ExFreePool(IoStatusBlock);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* POWER IRPs are always initialized with a status code of
+ STATUS_NOT_IMPLEMENTED */
+ Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+ Irp->IoStatus.Information = 0;
+
+ Stack = IoGetNextIrpStackLocation(Irp);
+ Stack->MinorFunction = MinorFunction;
+ if (MinorFunction == IRP_MN_WAIT_WAKE)
+ Stack->Parameters.WaitWake.PowerState = PowerState.SystemState;
+ else
+ Stack->Parameters.WaitWake.PowerState = PowerState.DeviceState;
+
+ RequestPowerItem->CompletionRoutine = CompletionFunction;
+ RequestPowerItem->PowerState = PowerState;
+ RequestPowerItem->Context = Context;
+
+ if (pIrp != NULL)
+ *pIrp = Irp;
+
+ IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion,
RequestPowerItem, TRUE, TRUE, TRUE);
+ Status = IoCallDriver(TopDeviceObject, Irp);
+
+ /* Always return STATUS_PENDING. The completion routine
+ * will call CompletionFunction and complete the Irp.
+ */
+ return STATUS_PENDING;
}
VOID