In service processes, `get_desktop_window` only creates a fake window owned by the first calling thread, with only a handle and no client-side object.
Before 9d6455f91cb7a7d166d5c4708d528b43a63eb4d7 `get_window_thread` was returning an error (called from `send_message` > `process_message`) in that case, as client-side object is missing.
After the commit, we only check handle existence and we now return success and then try to send/process the desktop window message, waiting for explorer startup which never happens.
Fixes: 9d6455f91cb7a7d166d5c4708d528b43a63eb4d7
From: Rémi Bernon rbernon@codeweavers.com
In service processes, `get_desktop_window` only creates a fake window owned by the first calling thread, with only a handle and no client-side object.
Before 9d6455f91cb7a7d166d5c4708d528b43a63eb4d7 `get_window_thread` was returning an error (called from `send_message` > `process_message`) in that case, as client-side object is missing.
After the commit, we only check handle existence and we now return success and then try to send/process the desktop window message, waiting for explorer startup which never happens.
Fixes: 9d6455f91cb7a7d166d5c4708d528b43a63eb4d7 --- dlls/win32u/driver.c | 2 +- dlls/win32u/win32u_private.h | 1 + dlls/win32u/winstation.c | 18 ++++++++++-------- 3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 180f1187593..5e32e714b24 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1011,7 +1011,7 @@ static void load_display_driver(void) USEROBJECTFLAGS flags; HWINSTA winstation;
- if (!load_desktop_driver( get_desktop_window() ) || user_driver == &lazy_load_driver) + if (is_service_process() || !load_desktop_driver( get_desktop_window() ) || user_driver == &lazy_load_driver) { winstation = NtUserGetProcessWindowStation(); if (!NtUserGetObjectInformation( winstation, UOI_FLAGS, &flags, sizeof(flags), NULL ) diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index a7bee5bd93a..2e3dbdd20fb 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -231,6 +231,7 @@ extern NTSTATUS get_shared_queue( struct object_lock *lock, const queue_shm_t ** extern NTSTATUS get_shared_input( UINT tid, struct object_lock *lock, const input_shm_t **input_shm );
extern BOOL is_virtual_desktop(void); +extern BOOL is_service_process(void);
/* window.c */ struct tagWND; diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 766043ce282..2311c7a7cf0 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -347,6 +347,15 @@ BOOL is_virtual_desktop(void) return ret; }
+BOOL is_service_process(void) +{ + static const WCHAR wine_service_station_name[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n',0}; + WCHAR name[MAX_PATH]; + + return NtUserGetObjectInformation( NtUserGetProcessWindowStation(), UOI_NAME, name, sizeof(name), NULL ) && + !wcscmp( name, wine_service_station_name ); +} + /*********************************************************************** * NtUserCreateWindowStation (win32u.@) */ @@ -779,20 +788,13 @@ static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiB
HWND get_desktop_window(void) { - static const WCHAR wine_service_station_name[] = - {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n',0}; struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); - WCHAR name[MAX_PATH]; BOOL is_service;
if (thread_info->top_window) return UlongToHandle( thread_info->top_window );
/* don't create an actual explorer desktop window for services */ - if (NtUserGetObjectInformation( NtUserGetProcessWindowStation(), UOI_NAME, name, sizeof(name), NULL ) - && !wcscmp( name, wine_service_station_name )) - is_service = TRUE; - else - is_service = FALSE; + is_service = is_service_process();
SERVER_START_REQ( get_desktop_window ) {
This merge request was approved by Huw Davies.