win32u: Move winstation initialization from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2021-10-14 15:22:40 +02:00 committed by Alexandre Julliard
parent d841b31aee
commit 2c1d00f142
5 changed files with 160 additions and 120 deletions

View File

@ -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();

View File

@ -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) );

View File

@ -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[] =

View File

@ -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,

View File

@ -22,17 +22,22 @@
#pragma makedep unix
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include <stdarg.h>
#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 );
}