[PATCH v3 3/4] ntdll: Implement SystemExecutionState handling.

Chip Davis cdavis at codeweavers.com
Sun Sep 1 22:43:12 CDT 2019


Get it from the server in NtPowerInformation(), and change it when
NtSetThreadExecutionState() is called.

Signed-off-by: Chip Davis <cdavis at codeweavers.com>
---

Notes:
    v2: Handle thread termination.
    v3: Put server changes back in their own patch.

 dlls/ntdll/nt.c                | 29 ++++++++++++++++++-----------
 dlls/powrprof/tests/powrprof.c | 16 ++++++++--------
 2 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 06f8f39b169d..a6843c929895 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -3064,15 +3064,18 @@ NTSTATUS WINAPI NtInitiatePowerAction(
  */
 NTSTATUS WINAPI NtSetThreadExecutionState( EXECUTION_STATE new_state, EXECUTION_STATE *old_state )
 {
-    static EXECUTION_STATE current =
-        ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_USER_PRESENT;
-    *old_state = current;
+    NTSTATUS status;
 
     WARN( "(0x%x, %p): stub, harmless.\n", new_state, old_state );
 
-    if (!(current & ES_CONTINUOUS) || (new_state & ES_CONTINUOUS))
-        current = new_state;
-    return STATUS_SUCCESS;
+    SERVER_START_REQ( set_thread_execution_state )
+    {
+        req->new_state = new_state;
+        status = wine_server_call( req );
+        *old_state = reply->old_state;
+    }
+    SERVER_END_REQ;
+    return status;
 }
 
 /******************************************************************************
@@ -3191,13 +3194,17 @@ NTSTATUS WINAPI NtPowerInformation(
 			return STATUS_SUCCESS;
 		}
 		case SystemExecutionState: {
-			PULONG ExecutionState = lpOutputBuffer;
-			WARN("semi-stub: SystemExecutionState\n"); /* Needed for .NET Framework, but using a FIXME is really noisy. */
+			EXECUTION_STATE *exec_state = lpOutputBuffer;
+			NTSTATUS status;
 			if (lpInputBuffer != NULL)
 				return STATUS_INVALID_PARAMETER;
-			/* FIXME: The actual state should be the value set by SetThreadExecutionState which is not currently implemented. */
-			*ExecutionState = ES_USER_PRESENT;
-			return STATUS_SUCCESS;
+			SERVER_START_REQ( get_system_execution_state )
+			{
+				status = wine_server_call( req );
+				if (!status) *exec_state = reply->exec_state;
+			}
+			SERVER_END_REQ;
+			return status;
 		}
 		case ProcessorInformation: {
 			const int cannedMHz = 1000; /* We fake a 1GHz processor if we can't conjure up real values */
diff --git a/dlls/powrprof/tests/powrprof.c b/dlls/powrprof/tests/powrprof.c
index d744895cc484..ce9f96bfd90d 100644
--- a/dlls/powrprof/tests/powrprof.c
+++ b/dlls/powrprof/tests/powrprof.c
@@ -42,7 +42,7 @@ static void test_system_execution_state(void)
     ok(status == STATUS_SUCCESS, "status %08x\n", status);
 
     old_es = SetThreadExecutionState(ES_SYSTEM_REQUIRED);
-    todo_wine ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+    ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
 
     old_es = es;
     status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
@@ -50,11 +50,11 @@ static void test_system_execution_state(void)
     ok(es == old_es, "unexpected execution state 0x%08x vs 0x%08x\n", es, old_es);
 
     old_es = SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
-    todo_wine ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+    ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
 
     status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
     ok(status == STATUS_SUCCESS, "status %08x\n", status);
-    todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+    ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
 
     old_es = SetThreadExecutionState(ES_CONTINUOUS);
     ok(old_es == (ES_CONTINUOUS|ES_DISPLAY_REQUIRED), "unexpected execution state 0x%08x\n", old_es);
@@ -127,23 +127,23 @@ static void test_system_execution_state_other_thread(void)
 
     status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
     ok(status == STATUS_SUCCESS, "status %08x\n", status);
-    todo_wine ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
+    ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
     es = SetThreadExecutionState(0);
-    todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+    ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
     SignalObjectAndWait(events[1], events[0], INFINITE, FALSE);
 
     status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
     ok(status == STATUS_SUCCESS, "status %08x\n", status);
-    todo_wine ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
+    ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
     es = SetThreadExecutionState(0);
-    todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+    ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
     SignalObjectAndWait(events[1], thread, INFINITE, FALSE);
 
     status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
     ok(status == STATUS_SUCCESS, "status %08x\n", status);
     ok(es == base_es, "unexpected execution state 0x%08x\n", es);
     es = SetThreadExecutionState(0);
-    todo_wine ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
+    ok(es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", es);
 
     CloseHandle(thread);
     CloseHandle(events[0]);
-- 
2.21.0




More information about the wine-devel mailing list