[PATCH 5/5] ntdll: Semi-implement power request functions.

Chip Davis cdavis at codeweavers.com
Tue Aug 13 11:50:11 CDT 2019


These create the object and alter the system execution state, but don't
actually force the computer to stay awake. It should be simple enough to
implement that on Mac OS. Linux might be a problem--in this instance,
we'll probably need to call out to some daemon over DBus.

Signed-off-by: Chip Davis <cdavis at codeweavers.com>
---
 dlls/ntdll/nt.c                | 90 +++++++++++++++++++++++++++++++---
 dlls/powrprof/tests/powrprof.c | 14 +++---
 2 files changed, 91 insertions(+), 13 deletions(-)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index a62c321883e..e534e6e0bec 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -51,6 +51,7 @@
 #include <time.h>
 
 #define NONAMELESSUNION
+#define NONAMELESSSTRUCT
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
 #include "wine/debug.h"
@@ -3084,15 +3085,72 @@ NTSTATUS WINAPI NtSetThreadExecutionState( EXECUTION_STATE new_state, EXECUTION_
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS do_format_string( const UNICODE_STRING *file, unsigned int id, unsigned int count,
+    UNICODE_STRING *params, UNICODE_STRING *dest )
+{
+    NTSTATUS status;
+    HMODULE mod;
+    LDR_RESOURCE_INFO info;
+    const IMAGE_RESOURCE_DATA_ENTRY *entry;
+    void *rsrc;
+    LANGID lang_id;
+    const WCHAR *str;
+    int i;
+
+    FIXME( "Detailed reason string formatting is not implemented\n" );
+
+    if ((status = LdrLoadDll( NULL, LDR_DONT_RESOLVE_REFS | LDR_NO_DLL_CALLS, file, &mod )))
+        return status;
+    info.Type = 6;  /* RT_STRING */
+    info.Name = (id >> 4) + 1;
+    NtQueryDefaultUILanguage( &lang_id );
+    info.Language = lang_id;
+    if ((status = LdrFindResource_U( mod, &info, 3, &entry )))
+        goto done;
+    if ((status = LdrAccessResource( mod, entry, &rsrc, NULL )))
+        goto done;
+    str = rsrc;
+    for (i = 0; i < (id & 0xf); i++)
+        str += *str + 1;
+    ++str;
+    if (!RtlCreateUnicodeString( dest, str ))
+        status = STATUS_NO_MEMORY;
+
+done:
+    LdrUnloadDll( mod );
+    return status;
+}
+
 /******************************************************************************
  *  NtCreatePowerRequest                        [NTDLL.@]
  *
  */
 NTSTATUS WINAPI NtCreatePowerRequest( HANDLE *handle, COUNTED_REASON_CONTEXT *context )
 {
-    FIXME( "(%p, %p): stub\n", handle, context );
+    UNICODE_STRING reason;
+    NTSTATUS status;
 
-    return STATUS_NOT_IMPLEMENTED;
+    WARN( "(%p, %p): semi-stub\n", handle, context );
+
+    if (context->Flags & POWER_REQUEST_CONTEXT_SIMPLE_STRING)
+        reason = context->u.SimpleString;
+    else if (context->Flags & POWER_REQUEST_CONTEXT_DETAILED_STRING)
+    {
+        if ((status = do_format_string( &context->u.s.ResourceFileName, context->u.s.ResourceReasonId,
+                                        context->u.s.StringCount, context->u.s.ReasonStrings, &reason )))
+            return status;
+    }
+
+    SERVER_START_REQ( create_power_request )
+    {
+        wine_server_add_data( req, reason.Buffer, reason.Length * sizeof(WCHAR) );
+        status = wine_server_call( req );
+        if (!status)
+            *handle = wine_server_ptr_handle( reply->handle );
+    }
+    SERVER_END_REQ;
+
+    return status;
 }
 
 /******************************************************************************
@@ -3101,9 +3159,19 @@ NTSTATUS WINAPI NtCreatePowerRequest( HANDLE *handle, COUNTED_REASON_CONTEXT *co
  */
 NTSTATUS WINAPI NtSetPowerRequest( HANDLE handle, POWER_REQUEST_TYPE type )
 {
-    FIXME( "(%p, %u): stub\n", handle, type );
+    NTSTATUS status;
 
-    return STATUS_NOT_IMPLEMENTED;
+    WARN( "(%p, %u): semi-stub\n", handle, type );
+
+    SERVER_START_REQ( set_power_request )
+    {
+        req->handle = wine_server_obj_handle( handle );
+        req->request = type;
+        status = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    return status;
 }
 
 /******************************************************************************
@@ -3112,9 +3180,19 @@ NTSTATUS WINAPI NtSetPowerRequest( HANDLE handle, POWER_REQUEST_TYPE type )
  */
 NTSTATUS WINAPI NtClearPowerRequest( HANDLE handle, POWER_REQUEST_TYPE type )
 {
-    FIXME( "(%p, %u): stub\n", handle, type );
+    NTSTATUS status;
 
-    return STATUS_NOT_IMPLEMENTED;
+    WARN( "(%p, %u): semi-stub\n", handle, type );
+
+    SERVER_START_REQ( clear_power_request )
+    {
+        req->handle = wine_server_obj_handle( handle );
+        req->request = type;
+        status = wine_server_call( req );
+    }
+    SERVER_END_REQ;
+
+    return status;
 }
 
 #ifdef linux
diff --git a/dlls/powrprof/tests/powrprof.c b/dlls/powrprof/tests/powrprof.c
index 5a1ebfa813e..2b1d1069b6a 100644
--- a/dlls/powrprof/tests/powrprof.c
+++ b/dlls/powrprof/tests/powrprof.c
@@ -170,31 +170,31 @@ static void test_system_execution_state_power_request()
     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());
+    ok(req != INVALID_HANDLE_VALUE, "err %u\n", GetLastError());
 
     ret = pPowerSetRequest(req, PowerRequestSystemRequired);
-    todo_wine ok(ret, "err %u\n", GetLastError());
+    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);
+    ok(es & ES_SYSTEM_REQUIRED, "unexpected execution state 0x%08x\n", es);
 
     ret = pPowerClearRequest(req, PowerRequestSystemRequired);
-    todo_wine ok(ret, "err %u\n", GetLastError());
+    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());
+    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);
+    ok(es & ES_DISPLAY_REQUIRED, "unexpected execution state 0x%08x\n", es);
 
     ret = CloseHandle(req);
-    todo_wine ok(ret, "err %u\n", GetLastError());
+    ok(ret, "err %u\n", GetLastError());
 
     status = CallNtPowerInformation(SystemExecutionState, NULL, 0, &es, sizeof(es));
     ok(status == STATUS_SUCCESS, "status %08x\n", status);
-- 
2.21.0




More information about the wine-devel mailing list