PREQUEST_POWER_COMPLETE CompletionRoutine;
POWER_STATE PowerState;
PVOID Context;
+ PDEVICE_OBJECT TopDeviceObject;
} REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM;
+typedef struct _POWER_STATE_TRAVERSE_CONTEXT
+{
+ SYSTEM_POWER_STATE SystemPowerState;
+ POWER_ACTION PowerAction;
+ PDEVICE_OBJECT PowerDevice;
+} POWER_STATE_TRAVERSE_CONTEXT, *PPOWER_STATE_TRAVERSE_CONTEXT;
+
PDEVICE_NODE PopSystemPowerDeviceNode = NULL;
BOOLEAN PopAcpiPresent = FALSE;
POP_POWER_ACTION PopAction;
RequestPowerItem->Context,
&Irp->IoStatus);
- ExFreePool(Context);
-
IoFreeIrp(Irp);
+ ObDereferenceObject(RequestPowerItem->TopDeviceObject);
+ ExFreePool(Context);
+
return STATUS_MORE_PROCESSING_REQUIRED;
}
}
NTSTATUS
-NTAPI
-PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState)
+PopSendQuerySystemPowerState(PDEVICE_OBJECT DeviceObject, SYSTEM_POWER_STATE SystemState, POWER_ACTION PowerAction)
{
+ KEVENT Event;
IO_STATUS_BLOCK IoStatusBlock;
- PDEVICE_OBJECT DeviceObject;
PIO_STACK_LOCATION IrpSp;
- PDEVICE_OBJECT Fdo;
- NTSTATUS Status;
- KEVENT Event;
PIRP Irp;
+ NTSTATUS Status;
- if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED;
+ KeInitializeEvent(&Event,
+ NotificationEvent,
+ FALSE);
- Status = IopGetSystemPowerDeviceObject(&DeviceObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("No system power driver available\n");
- return STATUS_UNSUCCESSFUL;
- }
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER,
+ DeviceObject,
+ NULL,
+ 0,
+ NULL,
+ &Event,
+ &IoStatusBlock);
+ if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
- Fdo = IoGetAttachedDeviceReference(DeviceObject);
+ IrpSp = IoGetNextIrpStackLocation(Irp);
+ IrpSp->MinorFunction = IRP_MN_QUERY_POWER;
+ IrpSp->Parameters.Power.Type = SystemPowerState;
+ IrpSp->Parameters.Power.State.SystemState = SystemState;
+ IrpSp->Parameters.Power.ShutdownType = PowerAction;
- if (Fdo == DeviceObject)
+ Status = PoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
{
- DPRINT("An FDO was not attached\n");
- return STATUS_UNSUCCESSFUL;
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = IoStatusBlock.Status;
}
+ return Status;
+}
+
+NTSTATUS
+PopSendSetSystemPowerState(PDEVICE_OBJECT DeviceObject, SYSTEM_POWER_STATE SystemState, POWER_ACTION PowerAction)
+{
+ KEVENT Event;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PIO_STACK_LOCATION IrpSp;
+ PIRP Irp;
+ NTSTATUS Status;
+
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER,
- Fdo,
+ DeviceObject,
NULL,
0,
NULL,
&Event,
&IoStatusBlock);
+ if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
IrpSp = IoGetNextIrpStackLocation(Irp);
IrpSp->MinorFunction = IRP_MN_SET_POWER;
IrpSp->Parameters.Power.Type = SystemPowerState;
- IrpSp->Parameters.Power.State.SystemState = PowerState;
+ IrpSp->Parameters.Power.State.SystemState = SystemState;
+ IrpSp->Parameters.Power.ShutdownType = PowerAction;
- DPRINT("Calling ACPI driver");
- Status = PoCallDriver(Fdo, Irp);
+ Status = PoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event,
KernelMode,
FALSE,
NULL);
- Status = IoStatusBlock.Status;
+ Status = IoStatusBlock.Status;
+ }
+
+ return Status;
+}
+
+NTSTATUS
+PopQuerySystemPowerStateTraverse(PDEVICE_NODE DeviceNode,
+ PVOID Context)
+{
+ PPOWER_STATE_TRAVERSE_CONTEXT PowerStateContext = Context;
+ NTSTATUS Status;
+
+ DPRINT("PopQuerySystemPowerStateTraverse(%p, %p)\n", DeviceNode, Context);
+
+ if (DeviceNode == IopRootDeviceNode)
+ return STATUS_SUCCESS;
+
+ if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
+ return STATUS_SUCCESS;
+
+ Status = PopSendQuerySystemPowerState(DeviceNode->PhysicalDeviceObject,
+ PowerStateContext->SystemPowerState,
+ PowerStateContext->PowerAction);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Device '%wZ' failed IRP_MN_QUERY_POWER\n", &DeviceNode->InstancePath);
+ }
+
+#if 0
+ return Status;
+#else
+ return STATUS_SUCCESS;
+#endif
+}
+
+NTSTATUS
+PopSetSystemPowerStateTraverse(PDEVICE_NODE DeviceNode,
+ PVOID Context)
+{
+ PPOWER_STATE_TRAVERSE_CONTEXT PowerStateContext = Context;
+ NTSTATUS Status;
+
+ DPRINT("PopSetSystemPowerStateTraverse(%p, %p)\n", DeviceNode, Context);
+
+ if (DeviceNode == IopRootDeviceNode)
+ return STATUS_SUCCESS;
+
+ if (DeviceNode->PhysicalDeviceObject == PowerStateContext->PowerDevice)
+ return STATUS_SUCCESS;
+
+ if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
+ return STATUS_SUCCESS;
+
+ Status = PopSendSetSystemPowerState(DeviceNode->PhysicalDeviceObject,
+ PowerStateContext->SystemPowerState,
+ PowerStateContext->PowerAction);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Device '%wZ' failed IRP_MN_SET_POWER\n", &DeviceNode->InstancePath);
+ }
+
+#if 0
+ return Status;
+#else
+ return STATUS_SUCCESS;
+#endif
+}
+
+NTSTATUS
+NTAPI
+PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState, POWER_ACTION PowerAction)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PDEVICE_OBJECT Fdo;
+ NTSTATUS Status;
+ DEVICETREE_TRAVERSE_CONTEXT Context;
+ POWER_STATE_TRAVERSE_CONTEXT PowerContext;
+
+ Status = IopGetSystemPowerDeviceObject(&DeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("No system power driver available\n");
+ Fdo = NULL;
+ }
+ else
+ {
+ Fdo = IoGetAttachedDeviceReference(DeviceObject);
+ if (Fdo == DeviceObject)
+ {
+ DPRINT("An FDO was not attached\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ /* Set up context */
+ PowerContext.PowerAction = PowerAction;
+ PowerContext.SystemPowerState = PowerState;
+ PowerContext.PowerDevice = Fdo;
+
+ /* Query for system power change */
+ IopInitDeviceTreeTraverseContext(&Context,
+ IopRootDeviceNode,
+ PopQuerySystemPowerStateTraverse,
+ &PowerContext);
+
+ Status = IopTraverseDeviceTree(&Context);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Query system power state failed; changing state anyway\n");
}
+
+ /* Set system power change */
+ IopInitDeviceTreeTraverseContext(&Context,
+ IopRootDeviceNode,
+ PopSetSystemPowerStateTraverse,
+ &PowerContext);
+
+ IopTraverseDeviceTree(&Context);
- ObDereferenceObject(Fdo);
+ if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED;
+
+ if (Fdo != NULL)
+ {
+ if (PowerAction != PowerActionShutdownReset)
+ PopSendSetSystemPowerState(Fdo, PowerState, PowerAction);
+
+ ObDereferenceObject(Fdo);
+ }
return Status;
}
NULL);
if (!Irp)
{
+ ObDereferenceObject(TopDeviceObject);
ExFreePool(RequestPowerItem);
return STATUS_INSUFFICIENT_RESOURCES;
}
RequestPowerItem->CompletionRoutine = CompletionFunction;
RequestPowerItem->PowerState = PowerState;
RequestPowerItem->Context = Context;
+ RequestPowerItem->TopDeviceObject = TopDeviceObject;
if (pIrp != NULL)
*pIrp = Irp;
IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, RequestPowerItem, TRUE, TRUE, TRUE);
- IoCallDriver(TopDeviceObject, Irp);
+ PoCallDriver(TopDeviceObject, Irp);
/* Always return STATUS_PENDING. The completion routine
* will call CompletionFunction and complete the Irp.
PAGED_CODE();
- DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
- "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
+ DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%p, "
+ "InputBufferLength 0x%x, OutputBuffer 0x%p, OutputBufferLength 0x%x)\n",
PowerInformationLevel,
InputBuffer, InputBufferLength,
OutputBuffer, OutputBufferLength);
PreviousState = Thread->PowerState | ES_CONTINUOUS;
/* Check if we need to update the power state */
- if (esFlags & ES_CONTINUOUS) Thread->PowerState = esFlags;
+ if (esFlags & ES_CONTINUOUS) Thread->PowerState = (UCHAR)esFlags;
/* Protect the write back to user mode */
_SEH2_TRY
(MinSystemState <= PowerSystemUnspecified) ||
(SystemAction > PowerActionWarmEject) ||
(SystemAction < PowerActionReserved) ||
- (Flags & ~(POWER_ACTION_QUERY_ALLOWED |
- POWER_ACTION_UI_ALLOWED |
- POWER_ACTION_OVERRIDE_APPS |
- POWER_ACTION_LIGHTEST_FIRST |
- POWER_ACTION_LOCK_CONSOLE |
- POWER_ACTION_DISABLE_WAKES |
+ (Flags & ~(POWER_ACTION_QUERY_ALLOWED |
+ POWER_ACTION_UI_ALLOWED |
+ POWER_ACTION_OVERRIDE_APPS |
+ POWER_ACTION_LIGHTEST_FIRST |
+ POWER_ACTION_LOCK_CONSOLE |
+ POWER_ACTION_DISABLE_WAKES |
POWER_ACTION_CRITICAL)))
{
DPRINT1("NtSetSystemPowerState: Bad parameters!\n");
#ifndef NEWCC
/* Flush dirty cache pages */
- CcRosFlushDirtyPages(-1, &Dummy);
+ CcRosFlushDirtyPages(-1, &Dummy, FALSE); //HACK: We really should wait here!
#else
Dummy = 0;
#endif
/* Flush all volumes and the registry */
- DPRINT1("Flushing volumes, cache flushed %d pages\n", Dummy);
+ DPRINT1("Flushing volumes, cache flushed %lu pages\n", Dummy);
PopFlushVolumes(PopAction.Shutdown);
/* Set IRP for drivers */