From: Chip Davis Subject: [PATCH v4 resend 3/4] ntdll: Implement SystemExecutionState handling. Message-Id: <20191125021249.50751-3-cdavis@codeweavers.com> Date: Sun, 24 Nov 2019 20:12:48 -0600 In-Reply-To: <20191125021249.50751-2-cdavis@codeweavers.com> References: <20191125021249.50751-1-cdavis@codeweavers.com> <20191125021249.50751-2-cdavis@codeweavers.com> Get it from the server in NtPowerInformation(), and change it when NtSetThreadExecutionState() is called. Signed-off-by: Chip Davis --- Notes: v2: Handle thread termination. v3: Put server changes back in their own patch. v4: Update for test changes. dlls/ntdll/nt.c | 33 ++++++++++++++++++++------------- dlls/ntdll/tests/info.c | 16 ++++++++-------- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index c9b278d3fc9..a0dfec0632a 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -3161,15 +3161,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; } /****************************************************************************** @@ -3361,13 +3364,17 @@ NTSTATUS WINAPI NtPowerInformation( return fill_battery_state(lpOutputBuffer); } case SystemExecutionState: { - PULONG ExecutionState = lpOutputBuffer; - WARN("semi-stub: SystemExecutionState\n"); /* Needed for .NET Framework, but using a FIXME is really noisy. */ - 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; + EXECUTION_STATE *exec_state = lpOutputBuffer; + NTSTATUS status; + if (nOutputBufferSize < sizeof(EXECUTION_STATE)) + return STATUS_BUFFER_TOO_SMALL; + 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/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 8e743320c65..f37b1a68cd0 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -1019,7 +1019,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 = pNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es)); @@ -1027,11 +1027,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 = pNtPowerInformation(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); @@ -1104,23 +1104,23 @@ static void test_system_execution_state_other_thread(void) status = pNtPowerInformation(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 = pNtPowerInformation(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 = pNtPowerInformation(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