[3/5] user32: Make sure explorer.exe process is spawned for the correct desktop.

Sebastian Lackner sebastian at fds-team.de
Thu Dec 3 18:19:58 CST 2015


If an invalid combination of winstation/desktop is active for the current
process, the handle inheritance doesn't work, and no desktop is created.
To fix this problem, this patch explicitly passes the full desktop name
in the startup info structure.

Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---

We cannot use ObjectNameInformation (see previous patch).

 dlls/user32/win.c        |   19 +++++++++++++++++++
 dlls/user32/winstation.c |    2 +-
 server/protocol.def      |    5 +++--
 server/winstation.c      |   15 ++++++++-------
 4 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 360834e..1a3cd49 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -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;
diff --git a/dlls/user32/winstation.c b/dlls/user32/winstation.c
index d1353b4..ae1d6ad 100644
--- a/dlls/user32/winstation.c
+++ b/dlls/user32/winstation.c
@@ -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 );
     }
diff --git a/server/protocol.def b/server/protocol.def
index aa37c66..04814c9 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -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 */
diff --git a/server/winstation.c b/server/winstation.c
index 08389bb..5016184 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -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;
-- 
2.6.2



More information about the wine-patches mailing list