From 2c1d00f142382f79fc70fde85a5eb110a50f7a3f Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 14 Oct 2021 15:22:40 +0200 Subject: [PATCH] win32u: Move winstation initialization from user32. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/user32/user_main.c | 105 +------------------------- dlls/win32u/font.c | 16 +--- dlls/win32u/syscall.c | 4 +- dlls/win32u/win32u_private.h | 17 +++++ dlls/win32u/winstation.c | 138 ++++++++++++++++++++++++++++++++++- 5 files changed, 160 insertions(+), 120 deletions(-) diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 0046d475fbc..a28253100be 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -33,8 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(graphics); -#define DESKTOP_ALL_ACCESS 0x01ff - HMODULE user32_module = 0; static CRITICAL_SECTION user_section; @@ -161,53 +159,6 @@ static void palette_init(void) } -/*********************************************************************** - * get_default_desktop - * - * Get the name of the desktop to use for this app if not specified explicitly. - */ -static const WCHAR *get_default_desktop(void) -{ - static WCHAR buffer[MAX_PATH + ARRAY_SIZE(L"\\Explorer")]; - WCHAR *p, *appname = buffer; - const WCHAR *ret = NULL; - DWORD len; - HKEY tmpkey, appkey; - - len = (GetModuleFileNameW( 0, buffer, MAX_PATH )); - if (!len || len >= MAX_PATH) return L"Default"; - if ((p = wcsrchr( appname, '/' ))) appname = p + 1; - if ((p = wcsrchr( appname, '\\' ))) appname = p + 1; - p = appname + lstrlenW(appname); - lstrcpyW( p, L"\\Explorer" ); - - /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Explorer */ - if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\AppDefaults", &tmpkey )) - { - if (RegOpenKeyW( tmpkey, appname, &appkey )) appkey = 0; - RegCloseKey( tmpkey ); - if (appkey) - { - len = sizeof(buffer); - if (!RegQueryValueExW( appkey, L"Desktop", 0, NULL, (LPBYTE)buffer, &len )) ret = buffer; - RegCloseKey( appkey ); - if (ret && *ret) return ret; - ret = NULL; - } - } - - /* @@ Wine registry key: HKCU\Software\Wine\Explorer */ - if (!RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Explorer", &appkey )) - { - len = sizeof(buffer); - if (!RegQueryValueExW( appkey, L"Desktop", 0, NULL, (LPBYTE)buffer, &len )) ret = buffer; - RegCloseKey( appkey ); - if (ret && *ret) return ret; - } - return L"Default"; -} - - /*********************************************************************** * dpiaware_init * @@ -265,67 +216,13 @@ static void dpiaware_init(void) } -/*********************************************************************** - * winstation_init - * - * Connect to the process window station and desktop. - */ -static void winstation_init(void) -{ - STARTUPINFOW info; - WCHAR *winstation = NULL, *desktop = NULL, *buffer = NULL; - HANDLE handle; - - GetStartupInfoW( &info ); - if (info.lpDesktop && *info.lpDesktop) - { - buffer = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(info.lpDesktop) + 1) * sizeof(WCHAR) ); - lstrcpyW( buffer, info.lpDesktop ); - if ((desktop = wcschr( buffer, '\\' ))) - { - *desktop++ = 0; - winstation = buffer; - } - else desktop = buffer; - } - - /* set winstation if explicitly specified, or if we don't have one yet */ - if (buffer || !NtUserGetProcessWindowStation()) - { - handle = CreateWindowStationW( winstation ? winstation : L"WinSta0", 0, WINSTA_ALL_ACCESS, NULL ); - if (handle) - { - NtUserSetProcessWindowStation( handle ); - /* only WinSta0 is visible */ - if (!winstation || !wcsicmp( winstation, L"WinSta0" )) - { - USEROBJECTFLAGS flags; - flags.fInherit = FALSE; - flags.fReserved = FALSE; - flags.dwFlags = WSF_VISIBLE; - NtUserSetObjectInformation( handle, UOI_FLAGS, &flags, sizeof(flags) ); - } - } - } - if (buffer || !NtUserGetThreadDesktop( GetCurrentThreadId() )) - { - handle = CreateDesktopW( desktop ? desktop : get_default_desktop(), - NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); - if (handle) NtUserSetThreadDesktop( handle ); - } - HeapFree( GetProcessHeap(), 0, buffer ); - - register_desktop_class(); -} - - /*********************************************************************** * USER initialisation routine */ static BOOL process_attach(void) { dpiaware_init(); - winstation_init(); + register_desktop_class(); /* Initialize system colors and metrics */ SYSPARAMS_Init(); diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 1f9c2adc21c..e1603b3698a 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -199,18 +199,6 @@ static struct font_gamma_ramp font_gamma_ramp; static void add_face_to_cache( struct gdi_font_face *face ); static void remove_face_from_cache( struct gdi_font_face *face ); -static void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) -{ - while (len--) *dst++ = (unsigned char)*src++; -} - -static UINT asciiz_to_unicode( WCHAR *dst, const char *src ) -{ - WCHAR *p = dst; - while ((*p++ = *src++)); - return (p - dst) * sizeof(WCHAR); -} - UINT get_acp(void) { return ((const WORD *)NtCurrentTeb()->Peb->AnsiCodePageData)[1]; @@ -553,7 +541,7 @@ static void get_fonts_win_dir_path( const WCHAR *file, WCHAR *path ) if (file) lstrcatW( path, file ); } -static HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len ) +HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len ) { UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name }; OBJECT_ATTRIBUTES attr; @@ -617,7 +605,7 @@ static HKEY reg_create_key( HKEY root, const WCHAR *name, ULONG name_len, return ret; } -static HKEY reg_open_hkcu_key( const char *name ) +HKEY reg_open_hkcu_key( const char *name ) { WCHAR nameW[128]; return reg_open_key( hkcu_key, nameW, asciiz_to_unicode( nameW, name ) - sizeof(WCHAR) ); diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index 12b895eff9a..28b7b177ba8 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -123,7 +123,9 @@ static NTSTATUS init( void *dispatcher ) { NTSTATUS status; if ((status = ntdll_init_syscalls( 1, &syscall_table, dispatcher ))) return status; - return gdi_init(); + if ((status = gdi_init())) return status; + winstation_init(); + return STATUS_SUCCESS; } unixlib_entry_t __wine_unix_call_funcs[] = diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 3b2623e1ed9..d187354cfcc 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -224,7 +224,12 @@ HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg ); extern void wrappers_init( unixlib_handle_t handle ) DECLSPEC_HIDDEN; extern NTSTATUS gdi_init(void) DECLSPEC_HIDDEN; extern NTSTATUS callbacks_init( void *args ) DECLSPEC_HIDDEN; +extern void winstation_init(void) DECLSPEC_HIDDEN; +extern HKEY reg_open_hkcu_key( const char *name ) DECLSPEC_HIDDEN; +extern HKEY reg_open_key( HKEY root, const WCHAR *name, ULONG name_len ) DECLSPEC_HIDDEN; +extern ULONG query_reg_ascii_value( HKEY hkey, const char *name, + KEY_VALUE_PARTIAL_INFORMATION *info, ULONG size ) DECLSPEC_HIDDEN; static inline WCHAR *win32u_wcsrchr( const WCHAR *str, WCHAR ch ) { @@ -316,6 +321,18 @@ static inline LONG win32u_wcstol( LPCWSTR s, LPWSTR *end, INT base ) #define wcsrchr(s,c) win32u_wcsrchr(s,c) #define wcstol(s,e,b) win32u_wcstol(s,e,b) +static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len ) +{ + while (len--) *dst++ = (unsigned char)*src++; +} + +static inline UINT asciiz_to_unicode( WCHAR *dst, const char *src ) +{ + WCHAR *p = dst; + while ((*p++ = *src++)); + return (p - dst) * sizeof(WCHAR); +} + DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *src, DWORD srclen ) DECLSPEC_HIDDEN; DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src, diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index aff16e2a873..c0fb0155f24 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -22,17 +22,22 @@ #pragma makedep unix #endif +#include "ntstatus.h" +#define WIN32_NO_STATUS #include #include "windef.h" #include "winbase.h" #include "ntuser.h" -#include "winternl.h" +#include "ddk/wdm.h" +#include "ntgdi_private.h" #include "wine/server.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(winstation); +#define DESKTOP_ALL_ACCESS 0x01ff + /*********************************************************************** * NtUserCreateWindowStation (win32u.@) */ @@ -374,3 +379,134 @@ BOOL WINAPI NtUserSetObjectInformation( HANDLE handle, INT index, void *info, DW SERVER_END_REQ; return ret; } + +static HANDLE get_winstations_dir_handle(void) +{ + char bufferA[64]; + WCHAR buffer[64]; + UNICODE_STRING str; + OBJECT_ATTRIBUTES attr; + NTSTATUS status; + HANDLE dir; + + sprintf( bufferA, "\\Sessions\\%u\\Windows\\WindowStations", NtCurrentTeb()->Peb->SessionId ); + str.Buffer = buffer; + str.Length = str.MaximumLength = asciiz_to_unicode( buffer, bufferA ) - sizeof(WCHAR); + InitializeObjectAttributes( &attr, &str, 0, 0, NULL ); + status = NtOpenDirectoryObject( &dir, DIRECTORY_CREATE_OBJECT | DIRECTORY_TRAVERSE, &attr ); + return status ? 0 : dir; +} + +/*********************************************************************** + * get_default_desktop + * + * Get the name of the desktop to use for this app if not specified explicitly. + */ +static const WCHAR *get_default_desktop( void *buf, size_t buf_size ) +{ + const WCHAR *p, *appname = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; + KEY_VALUE_PARTIAL_INFORMATION *info = buf; + WCHAR *buffer = buf; + HKEY tmpkey, appkey; + DWORD len; + + static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',0}; + + if ((p = wcsrchr( appname, '/' ))) appname = p + 1; + if ((p = wcsrchr( appname, '\\' ))) appname = p + 1; + len = lstrlenW(appname); + if (len > MAX_PATH) return defaultW; + memcpy( buffer, appname, len * sizeof(WCHAR) ); + asciiz_to_unicode( buffer + len, "\\Explorer" ); + + /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Explorer */ + if ((tmpkey = reg_open_hkcu_key( "Software\\Wine\\AppDefaults" ))) + { + appkey = reg_open_key( tmpkey, buffer, lstrlenW(buffer) * sizeof(WCHAR) ); + NtClose( tmpkey ); + if (appkey) + { + len = query_reg_ascii_value( appkey, "Desktop", info, buf_size ); + NtClose( appkey ); + if (len) return (const WCHAR *)info->Data; + } + } + + /* @@ Wine registry key: HKCU\Software\Wine\Explorer */ + if ((appkey = reg_open_hkcu_key( "Software\\Wine\\Explorer" ))) + { + len = query_reg_ascii_value( appkey, "Desktop", info, buf_size ); + NtClose( appkey ); + if (len) return (const WCHAR *)info->Data; + } + + return defaultW; +} + +/*********************************************************************** + * winstation_init + * + * Connect to the process window station and desktop. + */ +void winstation_init(void) +{ + RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters; + WCHAR *winstation = NULL, *desktop = NULL, *buffer = NULL; + HANDLE handle, dir = NULL; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING str; + + static const WCHAR winsta0[] = {'W','i','n','S','t','a','0',0}; + + if (params->Desktop.Length) + { + buffer = malloc( params->Desktop.Length + sizeof(WCHAR) ); + memcpy( buffer, params->Desktop.Buffer, params->Desktop.Length ); + buffer[params->Desktop.Length / sizeof(WCHAR)] = 0; + if ((desktop = wcschr( buffer, '\\' ))) + { + *desktop++ = 0; + winstation = buffer; + } + else desktop = buffer; + } + + /* set winstation if explicitly specified, or if we don't have one yet */ + if (buffer || !NtUserGetProcessWindowStation()) + { + str.Buffer = (WCHAR *)(winstation ? winstation : winsta0); + str.Length = str.MaximumLength = lstrlenW( str.Buffer ) * sizeof(WCHAR); + dir = get_winstations_dir_handle(); + InitializeObjectAttributes( &attr, &str, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + dir, NULL ); + + handle = NtUserCreateWindowStation( &attr, WINSTA_ALL_ACCESS, 0, 0, 0, 0, 0 ); + if (handle) + { + NtUserSetProcessWindowStation( handle ); + /* only WinSta0 is visible */ + if (!winstation || !wcsicmp( winstation, winsta0 )) + { + USEROBJECTFLAGS flags; + flags.fInherit = FALSE; + flags.fReserved = FALSE; + flags.dwFlags = WSF_VISIBLE; + NtUserSetObjectInformation( handle, UOI_FLAGS, &flags, sizeof(flags) ); + } + } + } + if (buffer || !NtUserGetThreadDesktop( GetCurrentThreadId() )) + { + char buffer[4096]; + str.Buffer = (WCHAR *)(desktop ? desktop : get_default_desktop( buffer, sizeof(buffer) )); + str.Length = str.MaximumLength = lstrlenW( str.Buffer ) * sizeof(WCHAR); + if (!dir) dir = get_winstations_dir_handle(); + InitializeObjectAttributes( &attr, &str, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + dir, NULL ); + + handle = NtUserCreateDesktopEx( &attr, NULL, NULL, 0, DESKTOP_ALL_ACCESS, 0 ); + if (handle) NtUserSetThreadDesktop( handle ); + } + NtClose( dir ); + free( buffer ); +}