From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/win32u_private.h | 1 + dlls/win32u/winstation.c | 18 ++++++++++++++++-- server/protocol.def | 13 +++++++++++-- server/user.c | 23 +++++++++++++++++++++++ server/user.h | 1 + server/winstation.c | 3 +++ 6 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index b4738ed6b16..dad7a12880e 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -219,6 +219,7 @@ struct object_lock * The data read from the objects may be transient and no logic should be executed based * on it, within the loop, or after, unless the function has returned STATUS_SUCCESS. */ +extern const session_shm_t *shared_session; extern NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm ); extern NTSTATUS get_shared_queue( struct object_lock *lock, const queue_shm_t **queue_shm ); extern NTSTATUS get_shared_input( UINT tid, struct object_lock *lock, const input_shm_t **input_shm ); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index b350b706454..25eea73dbd4 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -71,6 +71,7 @@ struct session_block
static pthread_mutex_t session_lock = PTHREAD_MUTEX_INITIALIZER; static struct list session_blocks = LIST_INIT(session_blocks); +const session_shm_t *shared_session;
static struct session_thread_data *get_session_thread_data(void) { @@ -195,6 +196,13 @@ static const shared_object_t *find_shared_session_object( struct obj_locator loc return NULL; }
+static void init_shared_session( struct obj_locator locator ) +{ + const shared_object_t *object; + if (shared_session || !(object = find_shared_session_object( locator ))) return; + shared_session = &object->shm.session; +} + NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm ) { struct session_thread_data *data = get_session_thread_data(); @@ -409,14 +417,17 @@ BOOL WINAPI NtUserCloseWindowStation( HWINSTA handle ) */ HWINSTA WINAPI NtUserGetProcessWindowStation(void) { + struct obj_locator session_locator; HWINSTA ret = 0;
SERVER_START_REQ( get_process_winstation ) { - if (!wine_server_call_err( req )) - ret = wine_server_ptr_handle( reply->handle ); + if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle ); + session_locator = reply->session_locator; } SERVER_END_REQ; + + init_shared_session( session_locator ); return ret; }
@@ -425,15 +436,18 @@ HWINSTA WINAPI NtUserGetProcessWindowStation(void) */ BOOL WINAPI NtUserSetProcessWindowStation( HWINSTA handle ) { + struct obj_locator session_locator; BOOL ret;
SERVER_START_REQ( set_process_winstation ) { req->handle = wine_server_obj_handle( handle ); ret = !wine_server_call_err( req ); + session_locator = reply->session_locator; } SERVER_END_REQ;
+ init_shared_session( session_locator ); reset_monitor_update_serial(); return ret; } diff --git a/server/protocol.def b/server/protocol.def index 871c3909e8c..1931be9a41c 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -976,6 +976,11 @@ struct shared_cursor struct rectangle clip; /* cursor clip rectangle */ };
+typedef volatile struct +{ + int placeholder; +} session_shm_t; + typedef volatile struct { unsigned int flags; /* desktop flags */ @@ -1011,6 +1016,7 @@ typedef volatile struct
typedef volatile union { + session_shm_t session; desktop_shm_t desktop; queue_shm_t queue; input_shm_t input; @@ -2894,13 +2900,16 @@ enum coords_relative /* Get the process current window station */ @REQ(get_process_winstation) @REPLY - obj_handle_t handle; /* handle to the window station */ + struct obj_locator session_locator; /* locator for the shared session object */ + obj_handle_t handle; /* handle to the window station */ @END
/* Set the process current window station */ @REQ(set_process_winstation) - obj_handle_t handle; /* handle to the window station */ + obj_handle_t handle; /* handle to the window station */ +@REPLY + struct obj_locator session_locator; /* locator for the shared session object */ @END
diff --git a/server/user.c b/server/user.c index 2d038a6ddbf..86f5c810933 100644 --- a/server/user.c +++ b/server/user.c @@ -18,7 +18,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" + #include "thread.h" +#include "file.h" #include "user.h" #include "request.h"
@@ -34,6 +40,23 @@ static struct user_handle *freelist; static int nb_handles; static int allocated_handles;
+const session_shm_t *get_session_shm(void) +{ + static const session_shm_t *session; + C_ASSERT( sizeof(*session) <= 1024 * 1024 ); + + if (!session && (session = alloc_shared_object())) + { + SHARED_WRITE_BEGIN( session, session_shm_t ) + { + shared->placeholder = 0; + } + SHARED_WRITE_END; + } + + return session; +} + static struct user_handle *handle_to_entry( user_handle_t handle ) { unsigned short generation; diff --git a/server/user.h b/server/user.h index ce463b9395d..c77bc030fad 100644 --- a/server/user.h +++ b/server/user.h @@ -99,6 +99,7 @@ struct desktop
/* user handles functions */
+extern const session_shm_t *get_session_shm(void); extern user_handle_t alloc_user_handle( void *ptr, enum user_object type ); extern void *get_user_object( user_handle_t handle, enum user_object type ); extern void *get_user_object_handle( user_handle_t *handle, enum user_object type ); diff --git a/server/winstation.c b/server/winstation.c index b3746090ccf..06c2706f1a2 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -680,6 +680,7 @@ DECL_HANDLER(set_winstation_monitors) /* get the process current window station */ DECL_HANDLER(get_process_winstation) { + reply->session_locator = get_shared_object_locator( get_session_shm() ); reply->handle = current->process->winstation; }
@@ -696,6 +697,8 @@ DECL_HANDLER(set_process_winstation) current->process->winstation = req->handle; release_object( winstation ); } + + reply->session_locator = get_shared_object_locator( get_session_shm() ); }
/* create a desktop */