Commit 257206e0 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

win32u: Move GetDesktopWindow implementation from user32.

parent ca0f64f9
......@@ -136,13 +136,14 @@ static void dpiaware_init(void)
static const struct user_callbacks user_funcs =
{
CopyImage,
GetDesktopWindow,
GetWindowRect,
RedrawWindow,
SendMessageTimeoutW,
SendMessageW,
WaitForInputIdle,
WindowFromDC,
free_dce,
register_builtin_classes,
MSG_SendInternalMessageTimeout,
(void *)__wine_set_user_driver,
};
......
......@@ -2022,87 +2022,7 @@ HWND WINAPI GetDesktopWindow(void)
struct user_thread_info *thread_info = get_user_thread_info();
if (thread_info->top_window) return thread_info->top_window;
SERVER_START_REQ( get_desktop_window )
{
req->force = 0;
if (!wine_server_call( req ))
{
thread_info->top_window = wine_server_ptr_handle( reply->top_window );
thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
}
}
SERVER_END_REQ;
if (!thread_info->top_window)
{
STARTUPINFOW si;
PROCESS_INFORMATION pi;
WCHAR windir[MAX_PATH];
WCHAR app[MAX_PATH + ARRAY_SIZE( L"\\explorer.exe" )];
WCHAR cmdline[MAX_PATH + ARRAY_SIZE( L"\\explorer.exe /desktop" )];
WCHAR desktop[MAX_PATH];
void *redir;
SERVER_START_REQ( set_user_object_info )
{
req->handle = wine_server_obj_handle( NtUserGetThreadDesktop(GetCurrentThreadId()) );
req->flags = SET_USER_OBJECT_GET_FULL_NAME;
wine_server_set_reply( req, desktop, sizeof(desktop) - sizeof(WCHAR) );
if (!wine_server_call( req ))
{
size_t size = wine_server_reply_size( reply );
desktop[size / sizeof(WCHAR)] = 0;
TRACE( "starting explorer for desktop %s\n", debugstr_w(desktop) );
}
else
desktop[0] = 0;
}
SERVER_END_REQ;
memset( &si, 0, sizeof(si) );
si.cb = sizeof(si);
si.lpDesktop = *desktop ? desktop : NULL;
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = 0;
si.hStdOutput = 0;
si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
GetSystemDirectoryW( windir, MAX_PATH );
lstrcpyW( app, windir );
lstrcatW( app, L"\\explorer.exe" );
lstrcpyW( cmdline, app );
lstrcatW( cmdline, L" /desktop" );
Wow64DisableWow64FsRedirection( &redir );
if (CreateProcessW( app, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
NULL, windir, &si, &pi ))
{
TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
WaitForInputIdle( pi.hProcess, 10000 );
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
else WARN( "failed to start explorer, err %d\n", GetLastError() );
Wow64RevertWow64FsRedirection( redir );
SERVER_START_REQ( get_desktop_window )
{
req->force = 1;
if (!wine_server_call( req ))
{
thread_info->top_window = wine_server_ptr_handle( reply->top_window );
thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
}
}
SERVER_END_REQ;
}
if (!thread_info->top_window || !NtUserCallHwnd( thread_info->top_window, NtUserCreateDesktopWindow ))
ERR( "failed to create desktop window\n" );
register_builtin_classes();
return thread_info->top_window;
return UlongToHandle( NtUserCallNoParam( NtUserGetDesktopWindow ));
}
......
......@@ -64,6 +64,15 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
}
}
/***********************************************************************
* NtUserWaitForInputIdle (win32u.@)
*/
DWORD WINAPI NtUserWaitForInputIdle( HANDLE process, DWORD timeout, BOOL wow )
{
if (!user_callbacks) return 0;
return user_callbacks->pWaitForInputIdle( process, timeout );
}
/**********************************************************************
* NtUserGetGUIThreadInfo (win32u.@)
*/
......
......@@ -30,13 +30,14 @@ struct dce;
struct user_callbacks
{
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
HWND (WINAPI *pGetDesktopWindow)(void);
BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect );
BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT );
LRESULT (WINAPI *pSendMessageTimeoutW)( HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM );
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
HWND (WINAPI *pWindowFromDC)( HDC );
void (WINAPI *free_dce)( struct dce *dce, HWND hwnd );
void (CDECL *register_builtin_classes)(void);
LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
void (CDECL *set_user_driver)( void *, UINT );
};
......
......@@ -35,6 +35,7 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(winstation);
WINE_DECLARE_DEBUG_CHANNEL(win);
#define DESKTOP_ALL_ACCESS 0x01ff
......@@ -388,13 +389,118 @@ BOOL WINAPI NtUserSetObjectInformation( HANDLE handle, INT index, void *info, DW
return ret;
}
#ifdef _WIN64
static inline TEB64 *NtCurrentTeb64(void) { return NULL; }
#else
static inline TEB64 *NtCurrentTeb64(void) { return (TEB64 *)NtCurrentTeb()->GdiBatchCount; }
#endif
HWND get_desktop_window(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
if (thread_info->top_window) return thread_info->top_window;
if (!user_callbacks) return 0;
return user_callbacks->pGetDesktopWindow();
SERVER_START_REQ( get_desktop_window )
{
req->force = 0;
if (!wine_server_call( req ))
{
thread_info->top_window = wine_server_ptr_handle( reply->top_window );
thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
}
}
SERVER_END_REQ;
if (!thread_info->top_window)
{
static const WCHAR appnameW[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s',
'\\','s','y','s','t','e','m','3','2','\\','e','x','p','l','o','r','e','r','.','e','x','e',0};
static const WCHAR cmdlineW[] = {'"','C',':','\\','w','i','n','d','o','w','s','\\',
's','y','s','t','e','m','3','2','\\','e','x','p','l','o','r','e','r','.','e','x','e','"',
' ','/','d','e','s','k','t','o','p',0};
static const WCHAR system_dir[] = {'C',':','\\','w','i','n','d','o','w','s','\\',
's','y','s','t','e','m','3','2','\\',0};
RTL_USER_PROCESS_PARAMETERS params = { sizeof(params), sizeof(params) };
PS_ATTRIBUTE_LIST ps_attr;
PS_CREATE_INFO create_info;
WCHAR desktop[MAX_PATH];
PEB *peb = NtCurrentTeb()->Peb;
HANDLE process, thread;
NTSTATUS status;
SERVER_START_REQ( set_user_object_info )
{
req->handle = wine_server_obj_handle( NtUserGetThreadDesktop(GetCurrentThreadId()) );
req->flags = SET_USER_OBJECT_GET_FULL_NAME;
wine_server_set_reply( req, desktop, sizeof(desktop) - sizeof(WCHAR) );
if (!wine_server_call( req ))
{
size_t size = wine_server_reply_size( reply );
desktop[size / sizeof(WCHAR)] = 0;
TRACE( "starting explorer for desktop %s\n", debugstr_w(desktop) );
}
else
desktop[0] = 0;
}
SERVER_END_REQ;
params.Flags = PROCESS_PARAMS_FLAG_NORMALIZED;
params.Environment = peb->ProcessParameters->Environment;
params.EnvironmentSize = peb->ProcessParameters->EnvironmentSize;
params.hStdError = peb->ProcessParameters->hStdError;
init_unicode_string( &params.CurrentDirectory.DosPath, system_dir );
init_unicode_string( &params.ImagePathName, appnameW + 4 );
init_unicode_string( &params.CommandLine, cmdlineW );
init_unicode_string( &params.WindowTitle, appnameW + 4 );
init_unicode_string( &params.Desktop, desktop );
ps_attr.TotalLength = sizeof(ps_attr);
ps_attr.Attributes[0].Attribute = PS_ATTRIBUTE_IMAGE_NAME;
ps_attr.Attributes[0].Size = sizeof(appnameW) - sizeof(WCHAR);
ps_attr.Attributes[0].ValuePtr = (WCHAR *)appnameW;
ps_attr.Attributes[0].ReturnLength = NULL;
if (NtCurrentTeb64() && !NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR])
{
NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = TRUE;
status = NtCreateUserProcess( &process, &thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, &params,
&create_info, &ps_attr );
NtCurrentTeb64()->TlsSlots[WOW64_TLS_FILESYSREDIR] = FALSE;
}
else
status = NtCreateUserProcess( &process, &thread, PROCESS_ALL_ACCESS, THREAD_ALL_ACCESS,
NULL, NULL, 0, THREAD_CREATE_FLAGS_CREATE_SUSPENDED, &params,
&create_info, &ps_attr );
if (!status)
{
NtResumeThread( thread, NULL );
TRACE_(win)( "started explorer\n" );
NtUserWaitForInputIdle( process, 10000, FALSE );
NtClose( thread );
NtClose( process );
}
else ERR_(win)( "failed to start explorer %x\n", status );
SERVER_START_REQ( get_desktop_window )
{
req->force = 1;
if (!wine_server_call( req ))
{
thread_info->top_window = wine_server_ptr_handle( reply->top_window );
thread_info->msg_window = wine_server_ptr_handle( reply->msg_window );
}
}
SERVER_END_REQ;
}
if (!thread_info->top_window || !user_driver->pCreateDesktopWindow( thread_info->top_window ))
ERR_(win)( "failed to create desktop window\n" );
if (user_callbacks) user_callbacks->register_builtin_classes();
return thread_info->top_window;
}
static HANDLE get_winstations_dir_handle(void)
......
......@@ -376,5 +376,6 @@ BOOL WINAPI NtUserUnregisterClass( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name );
BOOL WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id );
WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout );
DWORD WINAPI NtUserWaitForInputIdle( HANDLE process, DWORD timeout, BOOL wow );
#endif /* _NTUSER_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment