[NTOS:PO]
[reactos.git] / reactos / ntoskrnl / po / power.c
index 598b60a..684a25e 100644 (file)
 
 /* 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
 {
     SYSTEM_POWER_STATE SystemPowerState;
@@ -45,21 +37,22 @@ PopRequestPowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject,
                              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);
+    PREQUEST_POWER_COMPLETE CompletionRoutine;
+    POWER_STATE PowerState;
 
-    IoFreeIrp(Irp);
+    Stack = IoGetCurrentIrpStackLocation(Irp);
+    CompletionRoutine = Context;
+
+    PowerState.DeviceState = (ULONG_PTR)Stack->Parameters.Others.Argument3;
+    CompletionRoutine(Stack->Parameters.Others.Argument1,
+                      (UCHAR)(ULONG_PTR)Stack->Parameters.Others.Argument2,
+                      PowerState,
+                      Stack->Parameters.Others.Argument4,
+                      &Irp->IoStatus);
 
-    ObDereferenceObject(RequestPowerItem->TopDeviceObject);
-    ExFreePool(Context);
+    IoSkipCurrentIrpStackLocation(Irp);
+    IoFreeIrp(Irp);
+    ObDereferenceObject(DeviceObject);
 
     return STATUS_MORE_PROCESSING_REQUIRED;
 }
@@ -161,12 +154,12 @@ PopQuerySystemPowerStateTraverse(PDEVICE_NODE DeviceNode,
 {
     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;
 
@@ -177,7 +170,7 @@ PopQuerySystemPowerStateTraverse(PDEVICE_NODE DeviceNode,
     {
         DPRINT1("Device '%wZ' failed IRP_MN_QUERY_POWER\n", &DeviceNode->InstancePath);
     }
-    
+
 #if 0
     return Status;
 #else
@@ -191,15 +184,15 @@ PopSetSystemPowerStateTraverse(PDEVICE_NODE DeviceNode,
 {
     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;
 
@@ -210,7 +203,7 @@ PopSetSystemPowerStateTraverse(PDEVICE_NODE DeviceNode,
     {
         DPRINT1("Device '%wZ' failed IRP_MN_SET_POWER\n", &DeviceNode->InstancePath);
     }
-    
+
 #if 0
     return Status;
 #else
@@ -227,7 +220,7 @@ PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState, POWER_ACTION PowerAction)
     NTSTATUS Status;
     DEVICETREE_TRAVERSE_CONTEXT Context;
     POWER_STATE_TRAVERSE_CONTEXT PowerContext;
-    
+
     Status = IopGetSystemPowerDeviceObject(&DeviceObject);
     if (!NT_SUCCESS(Status))
     {
@@ -243,34 +236,34 @@ PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState, POWER_ACTION PowerAction)
             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);
 
     if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED;
-    
+
     if (Fdo != NULL)
     {
         if (PowerAction != PowerActionShutdownReset)
@@ -303,7 +296,7 @@ PoInitSystem(IN ULONG BootPhase)
                                        PopAddRemoveSysCapsCallback,
                                        NULL,
                                        &NotificationEntry);
-        
+
         /* Register lid notification */
         IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
                                        PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
@@ -336,11 +329,11 @@ PoInitSystem(IN ULONG BootPhase)
         PopAcpiPresent = KeLoaderBlock->Extension->AcpiTable != NULL ? TRUE : FALSE;
     }
 
-    
+
     /* Initialize volume support */
     InitializeListHead(&PopVolumeDevices);
     KeInitializeGuardedMutex(&PopVolumeLock);
-    
+
     /* Initialize support for dope */
     KeInitializeSpinLock(&PopDopeGlobalLock);
 
@@ -521,59 +514,54 @@ PoRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject,
     PDEVICE_OBJECT TopDeviceObject;
     PIO_STACK_LOCATION Stack;
     PIRP Irp;
-    PREQUEST_POWER_ITEM RequestPowerItem;
-  
+
     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;
-  
+
     /* Always call the top of the device stack */
     TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
-  
-    Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_POWER,
-                                        TopDeviceObject,
-                                        NULL,
-                                        0,
-                                        NULL,
-                                        NULL);
+
+    Irp = IoAllocateIrp(TopDeviceObject->StackSize + 2, FALSE);
     if (!Irp)
     {
         ObDereferenceObject(TopDeviceObject);
-        ExFreePool(RequestPowerItem);
         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.Status = STATUS_NOT_SUPPORTED;
     Irp->IoStatus.Information = 0;
-  
+
+    IoSetNextIrpStackLocation(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;
     if (MinorFunction == IRP_MN_WAIT_WAKE)
+    {
         Stack->Parameters.WaitWake.PowerState = PowerState.SystemState;
+    }
     else
     {
         Stack->Parameters.Power.Type = DevicePowerState;
         Stack->Parameters.Power.State = PowerState;
     }
-  
-    RequestPowerItem->CompletionRoutine = CompletionFunction;
-    RequestPowerItem->PowerState = PowerState;
-    RequestPowerItem->Context = Context;
-    RequestPowerItem->TopDeviceObject = TopDeviceObject;
-  
+
     if (pIrp != NULL)
         *pIrp = Irp;
-  
-    IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, RequestPowerItem, TRUE, TRUE, TRUE);
+
+    IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, CompletionFunction, TRUE, TRUE, TRUE);
     PoCallDriver(TopDeviceObject, Irp);
-  
+
     /* Always return STATUS_PENDING. The completion routine
      * will call CompletionFunction and complete the Irp.
      */
@@ -663,7 +651,7 @@ NtPowerInformation(IN POWER_INFORMATION_LEVEL PowerInformationLevel,
            PowerInformationLevel,
            InputBuffer, InputBufferLength,
            OutputBuffer, OutputBufferLength);
-    
+
     switch (PowerInformationLevel)
     {
         case SystemBatteryState:
@@ -682,7 +670,8 @@ NtPowerInformation(IN POWER_INFORMATION_LEVEL PowerInformationLevel,
             Status = STATUS_SUCCESS;
             break;
         }
-               case SystemPowerCapabilities:
+
+        case SystemPowerCapabilities:
         {
             PSYSTEM_POWER_CAPABILITIES PowerCapabilities = (PSYSTEM_POWER_CAPABILITIES)OutputBuffer;
 
@@ -794,8 +783,8 @@ NtSetThreadExecutionState(IN EXECUTION_STATE esFlags,
 NTSTATUS
 NTAPI
 NtSetSystemPowerState(IN POWER_ACTION SystemAction,
-                             IN SYSTEM_POWER_STATE MinSystemState,
-                             IN ULONG Flags)
+                      IN SYSTEM_POWER_STATE MinSystemState,
+                      IN ULONG Flags)
 {
     KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
     POP_POWER_ACTION Action = {0};
@@ -830,18 +819,18 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction,
         {
             /* Not granted */
             DPRINT1("ERROR: Privilege not held for shutdown\n");
-            //return STATUS_PRIVILEGE_NOT_HELD; HACK!
+            return STATUS_PRIVILEGE_NOT_HELD;
         }
 
         /* Do it as a kernel-mode caller for consistency with system state */
-        return ZwSetSystemPowerState (SystemAction, MinSystemState, Flags);
+        return ZwSetSystemPowerState(SystemAction, MinSystemState, Flags);
     }
 
     /* Read policy settings (partial shutdown vs. full shutdown) */
     if (SystemAction == PowerActionShutdown) PopReadShutdownPolicy();
 
     /* Disable lazy flushing of registry */
-    DPRINT1("Stopping lazy flush\n");
+    DPRINT("Stopping lazy flush\n");
     CmSetLazyFlushState(FALSE);
 
     /* Setup the power action */
@@ -849,13 +838,13 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction,
     Action.Flags = Flags;
 
     /* Notify callbacks */
-    DPRINT1("Notifying callbacks\n");
+    DPRINT("Notifying callbacks\n");
     ExNotifyCallback(PowerStateCallback, (PVOID)3, NULL);
+
     /* Swap in any worker thread stacks */
-    DPRINT1("Swapping worker threads\n");
+    DPRINT("Swapping worker threads\n");
     ExSwapinWorkerThreads(FALSE);
-    
+
     /* Make our action global */
     PopAction = Action;
 
@@ -884,7 +873,7 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction,
 
         /* Check if we're still in an invalid status */
         if (!NT_SUCCESS(Status)) break;
-        
+
 #ifndef NEWCC
         /* Flush dirty cache pages */
         CcRosFlushDirtyPages(-1, &Dummy, FALSE); //HACK: We really should wait here!
@@ -893,14 +882,14 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction,
 #endif
 
         /* Flush all volumes and the registry */
-        DPRINT1("Flushing volumes, cache flushed %lu pages\n", Dummy);
+        DPRINT("Flushing volumes, cache flushed %lu pages\n", Dummy);
         PopFlushVolumes(PopAction.Shutdown);
 
         /* Set IRP for drivers */
         PopAction.IrpMinor = IRP_MN_SET_POWER;
         if (PopAction.Shutdown)
         {
-            DPRINT1("Queueing shutdown thread\n");
+            DPRINT("Queueing shutdown thread\n");
             /* Check if we are running in the system context */
             if (PsGetCurrentProcess() != PsInitialSystemProcess)
             {
@@ -910,7 +899,7 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction,
                                      NULL);
 
                 ExQueueWorkItem(&PopShutdownWorkItem, CriticalWorkQueue);
-                                
+
                 /* Spend us -- when we wake up, the system is good to go down */
                 KeSuspendThread(KeGetCurrentThread());
                 Status = STATUS_SYSTEM_SHUTDOWN;
@@ -923,9 +912,10 @@ NtSetSystemPowerState(IN POWER_ACTION SystemAction,
                 PopGracefulShutdown(NULL);
             }
         }
-        
+
         /* You should not have made it this far */
-        ASSERT(FALSE && "System is still up and running?!");
+        // ASSERTMSG("System is still up and running?!", FALSE);
+        DPRINT1("System is still up and running, you may not have chosen a yet supported power option: %u\n", PopAction.Action);
         break;
     }