From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 13 +++++++------ dlls/win32u/win32u_private.h | 1 + dlls/win32u/winstation.c | 35 +++++++++++++++++++++++++++++++++++ server/protocol.def | 2 +- server/queue.c | 4 +--- 5 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index b7062414658..43f6f19050e 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2941,16 +2941,17 @@ static void process_sent_messages(void) static HANDLE get_server_queue_handle(void) { struct user_thread_info *thread_info = get_user_thread_info(); + struct object_lock lock = OBJECT_LOCK_INIT; + const queue_shm_t *queue_shm; + UINT status; HANDLE ret;
if (!(ret = thread_info->server_queue)) { - SERVER_START_REQ( get_msg_queue ) - { - wine_server_call( req ); - ret = wine_server_ptr_handle( reply->handle ); - } - SERVER_END_REQ; + while ((status = get_shared_queue( &lock, &queue_shm )) == STATUS_PENDING) + ret = wine_server_ptr_handle( queue_shm->handle ); + if (status) ret = 0; + thread_info->server_queue = ret; if (!ret) ERR( "Cannot get server thread queue\n" ); } 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 ); }