From: Rémi Bernon rbernon@codeweavers.com
--- dlls/ntdll/unix/sync.c | 36 ++++++++++++++++++++++++++++++++++-- server/inproc_sync.c | 7 +++++++ server/protocol.def | 7 +++++++ server/queue.c | 10 ++++++++++ server/user.h | 2 ++ 5 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index eae3d49af5a..6aedc5e9d61 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -372,6 +372,26 @@ extern unsigned int check_signal_access( struct inproc_sync *sync ) return STATUS_OBJECT_TYPE_MISMATCH; }
+static void select_queue(void) +{ + SERVER_START_REQ( select_inproc_queue ) + { + req->select = 1; + wine_server_call( req ); + } + SERVER_END_REQ; +} + +static void unselect_queue( BOOL signaled ) +{ + SERVER_START_REQ( select_inproc_queue ) + { + req->signaled = signaled; + wine_server_call( req ); + } + SERVER_END_REQ; +} + static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) { if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; @@ -423,7 +443,9 @@ static NTSTATUS inproc_query_mutex( HANDLE handle, MUTANT_BASIC_INFORMATION *inf static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_any, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { + HANDLE server_queue = UlongToHandle( NtUserGetThreadInfo()->server_queue ); struct inproc_sync *syncs[64], stack[ARRAY_SIZE(syncs)]; + UINT queue = -1; NTSTATUS ret;
if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; @@ -436,16 +458,22 @@ static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_an while (i--) release_inproc_sync( syncs[i] ); return ret; } + if (handles[i] == server_queue) queue = i; syncs[i] = stack + i; }
+ if (queue != -1) select_queue(); + ret = STATUS_NOT_IMPLEMENTED; + if (queue != -1) unselect_queue( ret == queue ); + while (count--) release_inproc_sync( syncs[count] ); - return STATUS_NOT_IMPLEMENTED; + return ret; }
static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { + HANDLE server_queue = UlongToHandle( NtUserGetThreadInfo()->server_queue ); struct inproc_sync stack_signal, stack_wait, *signal_sync = &stack_signal, *wait_sync = &stack_wait; NTSTATUS ret;
@@ -464,9 +492,13 @@ static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, return ret; }
+ if (wait == server_queue) select_queue(); + ret = STATUS_NOT_IMPLEMENTED; + if (wait == server_queue) unselect_queue( !ret ); + release_inproc_sync( signal_sync ); release_inproc_sync( wait_sync ); - return STATUS_NOT_IMPLEMENTED; + return ret; }
diff --git a/server/inproc_sync.c b/server/inproc_sync.c index a0973f42cca..e9377dbb8ca 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -189,3 +189,10 @@ DECL_HANDLER(get_inproc_sync_fd)
release_object( obj ); } + +DECL_HANDLER(select_inproc_queue) +{ + if (!thread_queue_select( current, req->select )) return; + if (req->select) check_thread_queue_idle( current ); + if (req->signaled) thread_queue_satisfied( current ); +} diff --git a/server/protocol.def b/server/protocol.def index a6cef01721e..1c827a7196b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4140,3 +4140,10 @@ enum inproc_sync_type int internal; /* sync is an internal event sync */ unsigned int access; /* handle access rights */ @END + + +/* Begin/end a client-side wait on a message queue */ +@REQ(select_inproc_queue) + int select; /* 1: begin waiting, 0: end waiting */ + int signaled; /* was the queue signaled? */ +@END diff --git a/server/queue.c b/server/queue.c index c51a29c6a8c..e24f2dd09b8 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1359,6 +1359,16 @@ static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *en reset_queue_sync( queue ); }
+int thread_queue_select( struct thread *thread, int select ) +{ + return msg_queue_select( thread->queue, select ); +} + +void thread_queue_satisfied( struct thread *thread ) +{ + msg_queue_satisfied( &thread->queue->obj, NULL ); +} + static void msg_queue_destroy( struct object *obj ) { struct msg_queue *queue = (struct msg_queue *)obj; diff --git a/server/user.h b/server/user.h index 0ec6ef3145e..7a97ef3aef5 100644 --- a/server/user.h +++ b/server/user.h @@ -119,6 +119,8 @@ extern void add_queue_hook_count( struct thread *thread, unsigned int index, int extern void inc_queue_paint_count( struct thread *thread, int incr ); extern void queue_cleanup_window( struct thread *thread, user_handle_t win ); extern int init_thread_queue( struct thread *thread ); +extern int thread_queue_select( struct thread *thread, int select ); +extern void thread_queue_satisfied( struct thread *thread ); extern void check_thread_queue_idle( struct thread *thread ); extern struct object *thread_queue_inproc_sync( struct thread *thread ); extern int attach_thread_input( struct thread *thread_from, struct thread *thread_to );