[1/3] server: Add an extra step to desktop shutdowns that explorer can interrupt.
Vincent Povirk
madewokherd at gmail.com
Fri Jan 24 15:11:31 CST 2014
-------------- next part --------------
From 18adb9fdf061bd1f19f78bfb0c415c5cd023aaf8 Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Fri, 24 Jan 2014 13:39:09 -0600
Subject: [PATCH 1/4] server: Add an extra step to desktop shutdowns that
explorer can interrupt.
---
dlls/user32/user32.spec | 1 +
dlls/user32/winstation.c | 18 ++++++++++++++++++
programs/explorer/desktop.c | 20 +++++++++++++++++++-
server/protocol.def | 6 ++++++
server/winstation.c | 29 +++++++++++++++++++++++++++--
5 files changed, 71 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 4b1f4b5..26fd4ee 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -780,3 +780,4 @@
#
@ cdecl __wine_send_input(long ptr)
@ cdecl __wine_set_pixel_format(long long)
+@ cdecl __wine_unlink_desktop(ptr)
diff --git a/dlls/user32/winstation.c b/dlls/user32/winstation.c
index 12b9edc..832d9e1 100644
--- a/dlls/user32/winstation.c
+++ b/dlls/user32/winstation.c
@@ -483,6 +483,24 @@ HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
/***********************************************************************
+ * __wine_unlink_desktop (USER32.@)
+ *
+ * Internal function to prevent new processes from accessing a desktop.
+ */
+BOOL CDECL __wine_unlink_desktop( HDESK handle )
+{
+ BOOL ret;
+ SERVER_START_REQ( unlink_desktop )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ ret = !wine_server_call_err( req );
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+
+/***********************************************************************
* GetUserObjectInformationA (USER32.@)
*/
BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
diff --git a/programs/explorer/desktop.c b/programs/explorer/desktop.c
index db6a355..4fa9351 100644
--- a/programs/explorer/desktop.c
+++ b/programs/explorer/desktop.c
@@ -492,6 +492,19 @@ static BOOL start_screensaver( void )
return FALSE;
}
+
+static void wine_unlink_desktop(HDESK desktop)
+{
+ BOOL (*CDECL __wine_unlink_desktop)(HDESK desktop) = NULL;
+
+ __wine_unlink_desktop = (void*)GetProcAddress(
+ GetModuleHandleA("user32"),
+ "__wine_unlink_desktop");
+
+ if (__wine_unlink_desktop != NULL)
+ __wine_unlink_desktop(desktop);
+}
+
/* window procedure for the desktop window */
static LRESULT WINAPI desktop_wnd_proc( HWND hwnd, UINT message, WPARAM wp, LPARAM lp )
{
@@ -511,7 +524,12 @@ static LRESULT WINAPI desktop_wnd_proc( HWND hwnd, UINT message, WPARAM wp, LPAR
return 0;
case WM_CLOSE:
- PostQuitMessage(0);
+ if (wp)
+ /* Desktop was unlinked */
+ PostQuitMessage(0);
+ else
+ /* Last process in this desktop quit */
+ wine_unlink_desktop( GetThreadDesktop( GetCurrentThreadId() ) );
return 0;
case WM_SETCURSOR:
diff --git a/server/protocol.def b/server/protocol.def
index fec5e75..ced9352 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2755,6 +2755,12 @@ enum coords_relative
@END
+/* Prevent new processes from accessing a desktop */
+ at REQ(unlink_desktop)
+ obj_handle_t handle; /* handle to the desktop */
+ at END
+
+
/* Get/set information about a user object (window station or desktop) */
@REQ(set_user_object_info)
obj_handle_t handle; /* handle to the object */
diff --git a/server/winstation.c b/server/winstation.c
index 08389bb..750637d 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -305,8 +305,7 @@ static void close_desktop_timeout( void *private )
struct desktop *desktop = private;
desktop->close_timeout = NULL;
- unlink_named_object( &desktop->obj ); /* make sure no other process can open it */
- post_desktop_message( desktop, WM_CLOSE, 0, 0 ); /* and signal the owner to quit */
+ post_desktop_message( desktop, WM_CLOSE, 0, 0 ); /* signal the owner to quit */
}
/* add a user of the desktop and cancel the close timeout */
@@ -724,3 +723,29 @@ DECL_HANDLER(enum_desktop)
release_object( winstation );
set_error( STATUS_NO_MORE_ENTRIES );
}
+
+
+/* Prevent new processes from accessing a desktop */
+DECL_HANDLER(unlink_desktop)
+{
+ struct desktop *desktop;
+ struct process *desktop_owner;
+
+ if ((desktop = (struct desktop *)get_handle_obj( current->process, req->handle,
+ 0, &desktop_ops )))
+ {
+ desktop_owner = get_top_window_owner( desktop );
+
+ /* Fail if there are other processes still in the desktop. */
+ if (desktop->users > ((desktop_owner && desktop_owner != current->process) ? 2 : 1))
+ set_error( STATUS_DEVICE_BUSY );
+ else
+ {
+ unlink_named_object( &desktop->obj );
+ post_desktop_message( desktop, WM_CLOSE, 1, 0 ); /* signal the owner to quit */
+ }
+
+ release_object( desktop );
+ }
+}
+
--
1.8.1.2
More information about the wine-patches
mailing list