[PATCH v2 resend 1/4] powrprof/tests: Test NtPowerInformation() with SystemExecutionState.

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


Test interaction between SetThreadExecutionState(), PowerSetRequest(),
and this parameter.

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

Notes:
    v2: Test that, when a thread terminates, its execution state is cleaned up.

 configure.ac                    |   1 +
 dlls/powrprof/tests/Makefile.in |   4 +
 dlls/powrprof/tests/powrprof.c  | 219 ++++++++++++++++++++++++++++++++
 include/powrprof.h              |   5 +
 4 files changed, 229 insertions(+)
 create mode 100644 dlls/powrprof/tests/Makefile.in
 create mode 100644 dlls/powrprof/tests/powrprof.c

diff --git a/configure.ac b/configure.ac
index f45c078674c2..b277642e316f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3616,6 +3616,7 @@ WINE_CONFIG_MAKEFILE(dlls/pdh/tests)
 WINE_CONFIG_MAKEFILE(dlls/photometadatahandler)
 WINE_CONFIG_MAKEFILE(dlls/pidgen)
 WINE_CONFIG_MAKEFILE(dlls/powrprof)
+WINE_CONFIG_MAKEFILE(dlls/powrprof/tests)
 WINE_CONFIG_MAKEFILE(dlls/printui)
 WINE_CONFIG_MAKEFILE(dlls/prntvpt)
 WINE_CONFIG_MAKEFILE(dlls/propsys)
diff --git a/dlls/powrprof/tests/Makefile.in b/dlls/powrprof/tests/Makefile.in
new file mode 100644
index 000000000000..87aa06be5026
--- /dev/null
+++ b/dlls/powrprof/tests/Makefile.in
@@ -0,0 +1,4 @@
+TESTDLL   = powrprof.dll
+IMPORTS   = powrprof
+
+C_SRCS    = powrprof.c
diff --git a/dlls/powrprof/tests/powrprof.c b/dlls/powrprof/tests/powrprof.c
new file mode 100644
index 000000000000..d744895cc484
--- /dev/null
+++ b/dlls/powrprof/tests/powrprof.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2019 Chip Davis for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winternl.h"
+#include "powrprof.h"
+
+#include "wine/test.h"
+
+HANDLE (WINAPI *pPowerCreateRequest)(REASON_CONTEXT *);
+BOOL (WINAPI *pPowerSetRequest)(HANDLE, POWER_REQUEST_TYPE);
+BOOL (WINAPI *pPowerClearRequest)(HANDLE, POWER_REQUEST_TYPE);
+
+static void test_system_execution_state(void)
+{
+    EXECUTION_STATE es, old_es;
+    NTSTATUS status;
+
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+    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);
+
+    old_es = es;
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+    ok(status == STATUS_SUCCESS, "status %08x\n", status);
+    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);
+
+    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);
+
+    old_es = SetThreadExecutionState(ES_CONTINUOUS);
+    ok(old_es == (ES_CONTINUOUS|ES_DISPLAY_REQUIRED), "unexpected execution state 0x%08x\n", old_es);
+
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+    ok(status == STATUS_SUCCESS, "status %08x\n", status);
+
+    old_es = SetThreadExecutionState(ES_DISPLAY_REQUIRED);
+    ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+
+    old_es = es;
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+    ok(status == STATUS_SUCCESS, "status %08x\n", status);
+    ok(es == old_es, "unexpected execution state 0x%08x vs 0x%08x\n", es, old_es);
+}
+
+static HANDLE events[2];
+
+static DWORD CALLBACK execution_state_thread(LPVOID param)
+{
+    EXECUTION_STATE old_es;
+
+    SetThreadExecutionState(ES_SYSTEM_REQUIRED);
+    SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+    old_es = SetThreadExecutionState(ES_DISPLAY_REQUIRED);
+    ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+    SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+    old_es = SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED);
+    ok(old_es == ES_CONTINUOUS, "unexpected execution state 0x%08x\n", old_es);
+    SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+    old_es = SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
+    ok(old_es == (ES_CONTINUOUS|ES_SYSTEM_REQUIRED), "unexpected execution state 0x%08x\n", old_es);
+    SignalObjectAndWait(events[0], events[1], INFINITE, FALSE);
+
+    return 0;
+}
+
+static void test_system_execution_state_other_thread(void)
+{
+    HANDLE thread;
+    EXECUTION_STATE base_es, es;
+    NTSTATUS status;
+
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &base_es, sizeof(base_es));
+    ok(status == STATUS_SUCCESS, "status %08x\n", status);
+    trace("base execution state = 0x%08x\n", base_es);
+
+    events[0] = CreateEventW(NULL, FALSE, FALSE, NULL);
+    events[1] = CreateEventW(NULL, FALSE, FALSE, NULL);
+    thread = CreateThread(NULL, 0, execution_state_thread, NULL, 0, NULL);
+    ok(thread != NULL, "Failed to create thread, err %u\n", GetLastError());
+
+    WaitForSingleObject(events[0], INFINITE);
+    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);
+    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);
+    ok(es == base_es, "unexpected execution state 0x%08x\n", es);
+    es = SetThreadExecutionState(0);
+    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_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);
+    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);
+    es = SetThreadExecutionState(0);
+    todo_wine 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);
+
+    CloseHandle(thread);
+    CloseHandle(events[0]);
+    CloseHandle(events[1]);
+}
+
+static void test_system_execution_state_power_request()
+{
+    HANDLE req;
+    REASON_CONTEXT reason;
+    BOOL ret;
+    NTSTATUS status;
+    EXECUTION_STATE base_es, es;
+    static const WCHAR reasonW[] = {'W', 'i', 'n', 'e', ' ', 't', 'e', 's', 't', 0};
+
+    if (!pPowerCreateRequest)
+    {
+        win_skip("Power request objects unavailable\n");
+        return;
+    }
+
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &base_es, sizeof(base_es));
+    ok(status == STATUS_SUCCESS, "status %08x\n", status);
+    trace("base execution state = 0x%08x\n", base_es);
+
+    reason.Version = 0;
+    reason.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
+    reason.Reason.SimpleReasonString = reasonW;
+    req = pPowerCreateRequest(&reason);
+    todo_wine ok(req != INVALID_HANDLE_VALUE, "err %u\n", GetLastError());
+
+    ret = pPowerSetRequest(req, PowerRequestSystemRequired);
+    todo_wine ok(ret, "err %u\n", GetLastError());
+
+    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);
+
+    ret = pPowerClearRequest(req, PowerRequestSystemRequired);
+    todo_wine ok(ret, "err %u\n", GetLastError());
+
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+    ok(status == STATUS_SUCCESS, "status %08x\n", status);
+    ok(!(es & ES_SYSTEM_REQUIRED) || (base_es & ES_SYSTEM_REQUIRED), "unexpected execution state 0x%08x\n", es);
+
+    ret = pPowerSetRequest(req, PowerRequestDisplayRequired);
+    todo_wine ok(ret, "err %u\n", GetLastError());
+
+    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);
+
+    ret = CloseHandle(req);
+    todo_wine ok(ret, "err %u\n", GetLastError());
+
+    status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
+    ok(status == STATUS_SUCCESS, "status %08x\n", status);
+    ok(!(es & ES_DISPLAY_REQUIRED) || (base_es & ES_DISPLAY_REQUIRED), "unexpected execution state 0x%08x\n", es);
+}
+
+START_TEST(powrprof)
+{
+    HMODULE hkernel32;
+
+    hkernel32 = GetModuleHandleA("kernel32.dll");
+    pPowerCreateRequest = (void *)GetProcAddress(hkernel32, "PowerCreateRequest");
+    pPowerSetRequest = (void *)GetProcAddress(hkernel32, "PowerSetRequest");
+    pPowerClearRequest = (void *)GetProcAddress(hkernel32, "PowerClearRequest");
+
+    test_system_execution_state();
+    test_system_execution_state_other_thread();
+    test_system_execution_state_power_request();
+}
diff --git a/include/powrprof.h b/include/powrprof.h
index 318188e465e5..421d9d4fc763 100644
--- a/include/powrprof.h
+++ b/include/powrprof.h
@@ -146,6 +146,11 @@ extern "C" {
 
 typedef BOOLEAN (CALLBACK* PWRSCHEMESENUMPROC)(UINT, DWORD, LPWSTR, DWORD, LPWSTR, PPOWER_POLICY, LPARAM);
 
+#ifndef WINE_NTSTATUS_DECLARED
+#define WINE_NTSTATUS_DECLARED
+typedef LONG NTSTATUS;
+#endif
+
 NTSTATUS WINAPI CallNtPowerInformation(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
 BOOLEAN WINAPI CanUserWritePwrScheme(VOID);
 BOOLEAN WINAPI DeletePwrScheme(UINT);
-- 
2.21.0




More information about the wine-devel mailing list