From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 22 +++++++++++----------- dlls/win32u/ntuser_private.h | 1 - dlls/win32u/win32u_private.h | 1 + dlls/win32u/winstation.c | 35 +++++++++++++++++++++++++++++++++++ server/protocol.def | 2 +- server/queue.c | 4 +--- 6 files changed, 49 insertions(+), 16 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index b7062414658..711bebe6d7c 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2940,20 +2940,20 @@ static void process_sent_messages(void) */ static HANDLE get_server_queue_handle(void) { - struct user_thread_info *thread_info = get_user_thread_info(); - HANDLE ret; + struct object_lock lock = OBJECT_LOCK_INIT; + const queue_shm_t *queue_shm; + HANDLE ret = 0; + UINT status; + + while ((status = get_shared_queue( &lock, &queue_shm )) == STATUS_PENDING) + ret = wine_server_ptr_handle( queue_shm->handle );
- if (!(ret = thread_info->server_queue)) + if (status) { - SERVER_START_REQ( get_msg_queue ) - { - wine_server_call( req ); - ret = wine_server_ptr_handle( reply->handle ); - } - SERVER_END_REQ; - thread_info->server_queue = ret; - if (!ret) ERR( "Cannot get server thread queue\n" ); + ERR( "Cannot get server thread queue, status %#x\n", status ); + return 0; } + return ret; }
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index d95ea03d45f..93aba470d71 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -107,7 +107,6 @@ static inline BOOL is_broadcast( HWND hwnd ) struct user_thread_info { struct ntuser_thread_info client_info; /* Data shared with client */ - HANDLE server_queue; /* Handle to server-side queue */ DWORD wake_mask; /* Current queue wake mask */ DWORD changed_mask; /* Current queue changed mask */ WORD message_count; /* Get/PeekMessage loop counter */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index e2e35d6c40d..cd64751e95b 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -219,6 +219,7 @@ struct object_lock * on it, within the loop, or after, unless the function has returned STATUS_SUCCESS. */ 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 BOOL is_virtual_desktop(void);
diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 1676539c69c..1a1b37f6eda 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -48,6 +48,7 @@ WINE_DECLARE_DEBUG_CHANNEL(win); struct session_thread_data { const shared_object_t *shared_desktop; /* thread desktop shared session cached object */ + const shared_object_t *shared_queue; /* thread message queue shared session cached object */ };
struct session_block @@ -219,6 +220,40 @@ NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **des return STATUS_SUCCESS; }
+NTSTATUS get_shared_queue( struct object_lock *lock, const queue_shm_t **queue_shm ) +{ + struct session_thread_data *data = get_session_thread_data(); + const shared_object_t *object; + + TRACE( "lock %p, queue_shm %p\n", lock, queue_shm ); + + if (!(object = data->shared_queue)) + { + obj_locator_t locator; + + SERVER_START_REQ( get_msg_queue ) + { + wine_server_call( req ); + locator = reply->locator; + } + SERVER_END_REQ; + + data->shared_queue = find_shared_session_object( locator ); + if (!(object = data->shared_queue)) return STATUS_INVALID_HANDLE; + memset( lock, 0, sizeof(*lock) ); + } + + if (!lock->id || !shared_object_release_seqlock( object, lock->seq )) + { + shared_object_acquire_seqlock( object, &lock->seq ); + *queue_shm = &object->shm.queue; + lock->id = object->id; + return STATUS_PENDING; + } + + return STATUS_SUCCESS; +} + BOOL is_virtual_desktop(void) { HANDLE desktop = NtUserGetThreadDesktop( GetCurrentThreadId() ); diff --git a/server/protocol.def b/server/protocol.def index 70cd835b647..d200dfc7528 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2118,7 +2118,7 @@ struct process_info /* Get the message queue of the current thread */ @REQ(get_msg_queue) @REPLY - obj_handle_t handle; /* handle to the queue */ + obj_locator_t locator; /* locator for the shared session object */ @END
diff --git a/server/queue.c b/server/queue.c index d56b199f1f0..60c9b98dec8 100644 --- a/server/queue.c +++ b/server/queue.c @@ -2883,9 +2883,7 @@ DECL_HANDLER(is_window_hung) DECL_HANDLER(get_msg_queue) { struct msg_queue *queue = get_current_queue(); - - reply->handle = 0; - if (queue) reply->handle = queue->shared->handle; + if (queue) reply->locator = get_shared_object_locator( queue->shared ); }