> > +/* globally stored shell window handles */
> > +
> > +static HWND hwndShellWindow = 0;
> > +static HWND hwndShellListView = 0;
> > +
> > +/* id of the process, which currently owns the shell window */
> > +static DWORD pidShellWindow = 0;
>
> You must not store handles or pids in the server, you should store
> pointers to the server objects, and properly handle the case where the
> corresponding window or process gets destroyed.
OK, I moved the server implementation to window.c and replaced the handles and
IDs by object pointers.
If you want, you can remove those two calls to grab_object() and
release_object() from the patch. They are not really necessary, since the
process pointer is allways automatically reset to 0 the time its windows are
destroyed. And the windows are always destroyed before a process is killed.
But maybe you want to play safe, and leave the calls in.
Changelog:
* Implement SetShellWindow(), SetShellWindowEx() and GetShellWindow()
--
Martin Fuchs
martin-fuchs@gmx.net
Index: dlls/user/focus.c
===================================================================
RCS file: /home/wine/wine/dlls/user/focus.c,v
retrieving revision 1.4
diff -u -r1.4 focus.c
--- dlls/user/focus.c 22 Nov 2002 21:22:16 -0000 1.4
+++ dlls/user/focus.c 27 Aug 2003 12:08:44 -0000
@@ -81,6 +81,12 @@
return TRUE;
}
+ if (hwnd == GetShellWindow())
+ {
+ TRACE("set_active_window(%p): ignored for desktop window\n", hwnd);
+ return TRUE;
+ }
+
/* call CBT hook chain */
cbt.fMouse = mouse;
cbt.hWndActive = previous;
@@ -341,3 +347,57 @@
SERVER_END_REQ;
return ret;
}
+
+
+/***********************************************************************
+* SetShellWindowEx (USER32.@)
+* hwndShell = Progman[Program Manager]
+* |-> SHELLDLL_DefView
+* hwndListView = | |-> SysListView32
+* | | |-> tooltips_class32
+* | |
+* | |-> SysHeader32
+* |
+* |-> ProxyTarget
+*/
+BOOL WINAPI SetShellWindowEx(HWND hwndShell, HWND hwndListView)
+{
+ BOOL ret;
+
+ SERVER_START_REQ(set_shell_windows)
+ {
+ req->shell_window = hwndShell;
+ req->shell_listview = hwndListView;
+
+ ret = !wine_server_call_err(req);
+ }
+ SERVER_END_REQ;
+
+ return ret;
+}
+
+/*******************************************************************
+* SetShellWindow (USER32.@)
+*/
+BOOL WINAPI SetShellWindow(HWND hwndShell)
+{
+ return SetShellWindowEx(hwndShell, hwndShell);
+}
+
+/*******************************************************************
+* GetShellWindow (USER32.@)
+*/
+HWND WINAPI GetShellWindow()
+{
+ HWND hwndShell = 0;
+
+ SERVER_START_REQ(get_shell_windows)
+ {
+ if (!wine_server_call_err(req))
+ hwndShell = reply->shell_window;
+ }
+ SERVER_END_REQ;
+
+ return hwndShell;
+}
+
Index: include/wine/server_protocol.h
===================================================================
RCS file: /home/wine/wine/include/wine/server_protocol.h,v
retrieving revision 1.80
diff -u -r1.80 server_protocol.h
--- include/wine/server_protocol.h 19 Aug 2003 03:08:18 -0000 1.80
+++ include/wine/server_protocol.h 27 Aug 2003 12:08:47 -0000
@@ -3111,6 +3111,32 @@
#define OPEN_TOKEN_AS_SELF 2
+
+struct set_shell_windows_request
+{
+ struct request_header __header;
+ user_handle_t shell_window;
+ user_handle_t shell_listview;
+};
+struct set_shell_windows_reply
+{
+ struct reply_header __header;
+};
+
+
+struct get_shell_windows_request
+{
+ struct request_header __header;
+};
+struct get_shell_windows_reply
+{
+ struct reply_header __header;
+ user_handle_t shell_window;
+ user_handle_t shell_listview;
+};
+
+
+
enum request
{
REQ_new_process,
@@ -3291,6 +3317,8 @@
REQ_get_next_hook,
REQ_set_clipboard_info,
REQ_open_token,
+ REQ_set_shell_windows,
+ REQ_get_shell_windows,
REQ_NB_REQUESTS
};
@@ -3476,6 +3504,8 @@
struct get_next_hook_request get_next_hook_request;
struct set_clipboard_info_request set_clipboard_info_request;
struct open_token_request open_token_request;
+ struct set_shell_windows_request set_shell_windows_request;
+ struct get_shell_windows_request get_shell_windows_request;
};
union generic_reply
{
@@ -3659,8 +3689,10 @@
struct get_next_hook_reply get_next_hook_reply;
struct set_clipboard_info_reply set_clipboard_info_reply;
struct open_token_reply open_token_reply;
+ struct set_shell_windows_reply set_shell_windows_reply;
+ struct get_shell_windows_reply get_shell_windows_reply;
};
-#define SERVER_PROTOCOL_VERSION 120
+#define SERVER_PROTOCOL_VERSION 121
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.80
diff -u -r1.80 protocol.def
--- server/protocol.def 19 Aug 2003 03:08:17 -0000 1.80
+++ server/protocol.def 27 Aug 2003 12:08:53 -0000
@@ -2178,3 +2178,18 @@
@END
#define OPEN_TOKEN_THREAD 1
#define OPEN_TOKEN_AS_SELF 2
+
+
+/* Set the shell windows */
+@REQ(set_shell_windows)
+ user_handle_t shell_window; /* handle to the new shell window */
+ user_handle_t shell_listview; /* handle to the new shell listview window */
+@END
+
+/* Get the shell windows */
+@REQ(get_shell_windows)
+@REPLY
+ user_handle_t shell_window; /* handle to the shell window */
+ user_handle_t shell_listview; /* handle to the shell listview window */
+@END
+
Index: server/request.h
===================================================================
RCS file: /home/wine/wine/server/request.h,v
retrieving revision 1.88
diff -u -r1.88 request.h
--- server/request.h 19 Aug 2003 03:08:17 -0000 1.88
+++ server/request.h 27 Aug 2003 12:08:53 -0000
@@ -281,6 +281,8 @@
DECL_HANDLER(get_next_hook);
DECL_HANDLER(set_clipboard_info);
DECL_HANDLER(open_token);
+DECL_HANDLER(set_shell_windows);
+DECL_HANDLER(get_shell_windows);
#ifdef WANT_REQUEST_HANDLERS
@@ -465,6 +467,8 @@
(req_handler)req_get_next_hook,
(req_handler)req_set_clipboard_info,
(req_handler)req_open_token,
+ (req_handler)req_set_shell_windows,
+ (req_handler)req_get_shell_windows,
};
#endif /* WANT_REQUEST_HANDLERS */
Index: server/trace.c
===================================================================
RCS file: /home/wine/wine/server/trace.c,v
retrieving revision 1.177
diff -u -r1.177 trace.c
--- server/trace.c 19 Aug 2003 03:08:17 -0000 1.177
+++ server/trace.c 27 Aug 2003 12:08:55 -0000
@@ -2502,6 +2502,22 @@
fprintf( stderr, " token=%p", req->token );
}
+static void dump_set_shell_windows_request( const struct set_shell_windows_request *req )
+{
+ fprintf( stderr, " shell_window=%p,", req->shell_window );
+ fprintf( stderr, " shell_listview=%p", req->shell_listview );
+}
+
+static void dump_get_shell_windows_request( const struct get_shell_windows_request *req )
+{
+}
+
+static void dump_get_shell_windows_reply( const struct get_shell_windows_reply *req )
+{
+ fprintf( stderr, " shell_window=%p,", req->shell_window );
+ fprintf( stderr, " shell_listview=%p", req->shell_listview );
+}
+
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request,
@@ -2681,6 +2697,8 @@
(dump_func)dump_get_next_hook_request,
(dump_func)dump_set_clipboard_info_request,
(dump_func)dump_open_token_request,
+ (dump_func)dump_set_shell_windows_request,
+ (dump_func)dump_get_shell_windows_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -2862,6 +2880,8 @@
(dump_func)dump_get_next_hook_reply,
(dump_func)dump_set_clipboard_info_reply,
(dump_func)dump_open_token_reply,
+ (dump_func)0,
+ (dump_func)dump_get_shell_windows_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -3043,6 +3063,8 @@
"get_next_hook",
"set_clipboard_info",
"open_token",
+ "set_shell_windows",
+ "get_shell_windows",
};
/* ### make_requests end ### */
Index: server/window.c
===================================================================
RCS file: /home/wine/wine/server/window.c,v
retrieving revision 1.22
diff -u -r1.22 window.c
--- server/window.c 8 Jan 2003 19:55:08 -0000 1.22
+++ server/window.c 27 Aug 2003 12:08:56 -0000
@@ -80,6 +80,15 @@
static struct window *top_window; /* top-level (desktop) window */
+/* globally stored shell window pointers */
+
+static struct window* shell_window = 0;
+static struct window* shell_listview = 0;
+
+/* process, which currently owns the shell window */
+static struct process* shell_window_owner = 0;
+
+
/* retrieve a pointer to a window from its handle */
inline static struct window *get_window( user_handle_t handle )
{
@@ -243,6 +252,23 @@
if (win->paint_count) inc_queue_paint_count( win->thread, -win->paint_count );
queue_cleanup_window( win->thread, win->handle );
}
+
+ /* reset shell window pointers, if the corresponding window is destroyed */
+ if (win == shell_window)
+ {
+ shell_window = 0;
+
+ /* release the shell window owner pointer */
+ if (shell_window_owner)
+ {
+ release_object(shell_window_owner);
+ shell_window_owner = 0;
+ }
+ }
+
+ if (win == shell_listview)
+ shell_listview = 0;
+
free_user_handle( win->handle );
destroy_properties( win );
unlink_window( win );
@@ -817,4 +843,37 @@
data++;
count--;
}
+}
+
+
+/* set the shell windows */
+DECL_HANDLER(set_shell_windows)
+{
+ /* test if we are permitted to change the shell window */
+ if (shell_window_owner && current->process!=shell_window_owner)
+ {
+ set_error(STATUS_ACCESS_DENIED);
+ }
+ else
+ {
+ shell_window = req->shell_window? get_window(req->shell_window): 0;
+ shell_listview = req->shell_listview? get_window(req->shell_listview): 0;
+
+ /* We only have to set shell_window_owner if there was none previously.
+ It can't be the case, that we have to owerwrite the owner with
+ another process, since we already checked for this case above. */
+ if (shell_window && !shell_window_owner)
+ {
+ /* request shell window for the calling process */
+ shell_window_owner = (struct process*)grab_object(current->process);
+ }
+ }
+}
+
+
+/* get the shell windows */
+DECL_HANDLER(get_shell_windows)
+{
+ reply->shell_window = shell_window? shell_window->handle: 0;
+ reply->shell_listview = shell_listview? shell_listview->handle: 0;
}
Index: windows/winpos.c
===================================================================
RCS file: /home/wine/wine/windows/winpos.c,v
retrieving revision 1.145
diff -u -r1.145 winpos.c
--- windows/winpos.c 19 May 2003 19:00:02 -0000 1.145
+++ windows/winpos.c 27 Aug 2003 12:08:58 -0000
@@ -65,7 +65,6 @@
/* ----- internal variables ----- */
-static HWND hGlobalShellWindow=0; /*the shell*/
static HWND hGlobalTaskmanWindow=0;
static HWND hGlobalProgmanWindow=0;
@@ -630,27 +629,6 @@
}
-/*******************************************************************
- * SetShellWindow (USER32.@)
- */
-HWND WINAPI SetShellWindow(HWND hwndshell)
-{ WARN("(hWnd=%p) semi stub\n",hwndshell );
-
- hGlobalShellWindow = WIN_GetFullHandle( hwndshell );
- return hGlobalShellWindow;
-}
-
-
-/*******************************************************************
- * GetShellWindow (USER32.@)
- */
-HWND WINAPI GetShellWindow(void)
-{ WARN("(hWnd=%p) semi stub\n",hGlobalShellWindow );
-
- return hGlobalShellWindow;
-}
-
-
/***********************************************************************
* BringWindowToTop (USER32.@)
*/
@@ -1360,25 +1338,6 @@
HWND WINAPI GetProgmanWindow(void)
{
return hGlobalProgmanWindow;
-}
-
-/***********************************************************************
- * SetShellWindowEx (USER32.@)
- * hwndProgman = Progman[Program Manager]
- * |-> SHELLDLL_DefView
- * hwndListView = | |-> SysListView32
- * | | |-> tooltips_class32
- * | |
- * | |-> SysHeader32
- * |
- * |-> ProxyTarget
- */
-HWND WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
-{
- FIXME("%p %p stub\n",hwndProgman ,hwndListView );
- hGlobalShellWindow = hwndProgman;
- return hGlobalShellWindow;
-
}
/***********************************************************************