user32: Make sure explorer.exe process is spawned for the correct desktop.

If an invalid combination of winstation/desktop is active for the
current process, the handle inheritance doesn't work, and no desktop is
created.

Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Sebastian Lackner 2015-12-04 01:19:58 +01:00 committed by Alexandre Julliard
parent 8c4a785daf
commit 19a3f6b5cb
5 changed files with 34 additions and 12 deletions

View File

@ -25,6 +25,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winver.h"
@ -2040,10 +2041,28 @@ HWND WINAPI GetDesktopWindow(void)
WCHAR windir[MAX_PATH];
WCHAR app[MAX_PATH + sizeof(explorer)/sizeof(WCHAR)];
WCHAR cmdline[MAX_PATH + (sizeof(explorer) + sizeof(args))/sizeof(WCHAR)];
WCHAR desktop[MAX_PATH];
void *redir;
SERVER_START_REQ( set_user_object_info )
{
req->handle = wine_server_obj_handle( GetThreadDesktop(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;

View File

@ -632,7 +632,7 @@ BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DW
SERVER_START_REQ( set_user_object_info )
{
req->handle = wine_server_obj_handle( handle );
req->flags = SET_USER_OBJECT_FLAGS;
req->flags = SET_USER_OBJECT_SET_FLAGS;
req->obj_flags = obj_flags->dwFlags;
ret = !wine_server_call_err( req );
}

View File

@ -4009,7 +4009,8 @@ struct set_user_object_info_reply
unsigned int old_obj_flags;
/* VARARG(name,unicode_str); */
};
#define SET_USER_OBJECT_FLAGS 1
#define SET_USER_OBJECT_SET_FLAGS 1
#define SET_USER_OBJECT_GET_FULL_NAME 2
@ -6152,6 +6153,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 489
#define SERVER_PROTOCOL_VERSION 490
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -2840,14 +2840,15 @@ enum coords_relative
/* Get/set information about a user object (window station or desktop) */
@REQ(set_user_object_info)
obj_handle_t handle; /* handle to the object */
unsigned int flags; /* information to set */
unsigned int flags; /* information to set/get */
unsigned int obj_flags; /* new object flags */
@REPLY
int is_desktop; /* is object a desktop? */
unsigned int old_obj_flags; /* old object flags */
VARARG(name,unicode_str); /* object name */
@END
#define SET_USER_OBJECT_FLAGS 1
#define SET_USER_OBJECT_SET_FLAGS 1
#define SET_USER_OBJECT_GET_FULL_NAME 2
/* Register a hotkey */

View File

@ -424,13 +424,13 @@ void close_thread_desktop( struct thread *thread )
}
/* set the reply data from the object name */
static void set_reply_data_obj_name( struct object *obj )
static void set_reply_data_obj_name( struct object *obj, int full_name )
{
data_size_t len;
const WCHAR *ptr, *name = get_object_name( obj, &len );
/* if there is a backslash return the part of the name after it */
if (name && (ptr = memchrW( name, '\\', len/sizeof(WCHAR) )))
if (name && !full_name && (ptr = memchrW( name, '\\', len/sizeof(WCHAR) )))
{
len -= (ptr + 1 - name) * sizeof(WCHAR);
name = ptr + 1;
@ -657,14 +657,14 @@ DECL_HANDLER(set_user_object_info)
struct desktop *desktop = (struct desktop *)obj;
reply->is_desktop = 1;
reply->old_obj_flags = desktop->flags;
if (req->flags & SET_USER_OBJECT_FLAGS) desktop->flags = req->obj_flags;
if (req->flags & SET_USER_OBJECT_SET_FLAGS) desktop->flags = req->obj_flags;
}
else if (obj->ops == &winstation_ops)
{
struct winstation *winstation = (struct winstation *)obj;
reply->is_desktop = 0;
reply->old_obj_flags = winstation->flags;
if (req->flags & SET_USER_OBJECT_FLAGS) winstation->flags = req->obj_flags;
if (req->flags & SET_USER_OBJECT_SET_FLAGS) winstation->flags = req->obj_flags;
}
else
{
@ -672,7 +672,8 @@ DECL_HANDLER(set_user_object_info)
release_object( obj );
return;
}
if (get_reply_max_size()) set_reply_data_obj_name( obj );
if (get_reply_max_size())
set_reply_data_obj_name( obj, (req->flags & SET_USER_OBJECT_GET_FULL_NAME) != 0 );
release_object( obj );
}
@ -688,7 +689,7 @@ DECL_HANDLER(enum_winstation)
unsigned int access = WINSTA_ENUMERATE;
if (req->index > index++) continue;
if (!check_object_access( &winsta->obj, &access )) continue;
set_reply_data_obj_name( &winsta->obj );
set_reply_data_obj_name( &winsta->obj, 0 );
clear_error();
reply->next = index;
return;
@ -714,7 +715,7 @@ DECL_HANDLER(enum_desktop)
if (req->index > index++) continue;
if (!desktop->obj.name) continue;
if (!check_object_access( &desktop->obj, &access )) continue;
set_reply_data_obj_name( &desktop->obj );
set_reply_data_obj_name( &desktop->obj, 0 );
release_object( winstation );
clear_error();
reply->next = index;