Later, a similar inproc sync as the queue will be created for user APC alerts and sent on thread init as well, saving us the need to special case those in the get_inproc_sync request and in the cache.
-- v3: ntdll: Notify wineserver when waiting on inproc queue. server: Create an inproc sync for message queue signaling. win32u: Move server queue handle to ntuser_thread_info. ntdll: Introduce a helper to wait on an server-side sync object. ntdll: Check inproc sync signal rights in signal and wait. server: Move signal access checks outside of the objects.
From: Rémi Bernon rbernon@codeweavers.com
--- server/async.c | 4 ++-- server/atom.c | 2 +- server/change.c | 2 +- server/clipboard.c | 2 +- server/completion.c | 4 ++-- server/console.c | 18 +++++++++--------- server/debugger.c | 4 ++-- server/device.c | 8 ++++---- server/directory.c | 4 ++-- server/event.c | 17 ++++++----------- server/fd.c | 8 ++++---- server/file.c | 2 +- server/handle.c | 2 +- server/hook.c | 2 +- server/inproc_sync.c | 2 +- server/mailslot.c | 8 ++++---- server/mapping.c | 6 +++--- server/mutex.c | 13 ++++--------- server/named_pipe.c | 12 ++++++------ server/object.c | 10 ++-------- server/object.h | 4 ++-- server/process.c | 6 +++--- server/queue.c | 4 ++-- server/registry.c | 2 +- server/request.c | 2 +- server/semaphore.c | 13 ++++--------- server/serial.c | 2 +- server/signal.c | 2 +- server/sock.c | 6 +++--- server/symlink.c | 2 +- server/thread.c | 18 ++++++++++++++---- server/timer.c | 2 +- server/token.c | 2 +- server/window.c | 2 +- server/winstation.c | 4 ++-- 35 files changed, 95 insertions(+), 106 deletions(-)
diff --git a/server/async.c b/server/async.c index 4068f744567..4ccdbecd0ec 100644 --- a/server/async.c +++ b/server/async.c @@ -79,7 +79,7 @@ static const struct object_ops async_ops = remove_queue, /* remove_queue */ async_signaled, /* signaled */ async_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -701,7 +701,7 @@ static const struct object_ops iosb_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/atom.c b/server/atom.c index 0bba828e300..d8a4fd209c2 100644 --- a/server/atom.c +++ b/server/atom.c @@ -79,7 +79,7 @@ static const struct object_ops atom_table_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/change.c b/server/change.c index 5bcd0676e0d..4e152a39a22 100644 --- a/server/change.c +++ b/server/change.c @@ -113,7 +113,7 @@ static const struct object_ops dir_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ dir_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/clipboard.c b/server/clipboard.c index 59a50354b48..a0e7ffa38bd 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -77,7 +77,7 @@ static const struct object_ops clipboard_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/completion.c b/server/completion.c index a2028a89823..60f8ad409b2 100644 --- a/server/completion.c +++ b/server/completion.c @@ -93,7 +93,7 @@ static const struct object_ops completion_wait_ops = remove_queue, /* remove_queue */ completion_wait_signaled, /* signaled */ completion_wait_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -168,7 +168,7 @@ static const struct object_ops completion_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ completion_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/console.c b/server/console.c index f0cb6689d4b..0bb5a6b24c0 100644 --- a/server/console.c +++ b/server/console.c @@ -84,7 +84,7 @@ static const struct object_ops console_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ console_get_fd, /* get_fd */ console_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -163,7 +163,7 @@ static const struct object_ops console_server_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ console_server_get_fd, /* get_fd */ console_server_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -234,7 +234,7 @@ static const struct object_ops screen_buffer_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ screen_buffer_get_fd, /* get_fd */ screen_buffer_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -280,11 +280,11 @@ static const struct object_ops console_device_ops = sizeof(struct object), /* size */ &device_type, /* type */ console_device_dump, /* dump */ - no_add_queue, /* add_queue */ + NULL, /* add_queue */ NULL, /* remove_queue */ NULL, /* signaled */ - no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* satisfied */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -325,7 +325,7 @@ static const struct object_ops console_input_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ console_input_get_fd, /* get_fd */ console_input_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -386,7 +386,7 @@ static const struct object_ops console_output_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ console_output_get_fd, /* get_fd */ console_output_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -445,7 +445,7 @@ static const struct object_ops console_connection_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ console_connection_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/debugger.c b/server/debugger.c index 2956ee17b8e..cc096c46223 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -89,7 +89,7 @@ static const struct object_ops debug_event_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ debug_event_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -118,7 +118,7 @@ static const struct object_ops debug_obj_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ debug_obj_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/device.c b/server/device.c index f4b3f19028b..35c6cca1541 100644 --- a/server/device.c +++ b/server/device.c @@ -67,7 +67,7 @@ static const struct object_ops irp_call_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -109,7 +109,7 @@ static const struct object_ops device_manager_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ device_manager_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -167,7 +167,7 @@ static const struct object_ops device_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -220,7 +220,7 @@ static const struct object_ops device_file_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ device_file_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/directory.c b/server/directory.c index c56c216d6d5..c80e8e17702 100644 --- a/server/directory.c +++ b/server/directory.c @@ -70,7 +70,7 @@ static const struct object_ops object_type_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -121,7 +121,7 @@ static const struct object_ops directory_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/event.c b/server/event.c index c69554fc657..8a7155cc332 100644 --- a/server/event.c +++ b/server/event.c @@ -48,6 +48,7 @@ struct type_descr event_type = STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, EVENT_ALL_ACCESS }, + EVENT_MODIFY_STATE, /* signal access */ };
struct event_sync @@ -60,7 +61,7 @@ struct event_sync static void event_sync_dump( struct object *obj, int verbose ); static int event_sync_signaled( struct object *obj, struct wait_queue_entry *entry ); static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *entry ); -static int event_sync_signal( struct object *obj, unsigned int access ); +static int event_sync_signal( struct object *obj );
static const struct object_ops event_sync_ops = { @@ -133,7 +134,7 @@ static void event_sync_satisfied( struct object *obj, struct wait_queue_entry *e if (!event->manual) reset_sync( event ); }
-static int event_sync_signal( struct object *obj, unsigned int access ) +static int event_sync_signal( struct object *obj ) { struct event_sync *event = (struct event_sync *)obj; assert( obj->ops == &event_sync_ops ); @@ -150,7 +151,7 @@ struct event
static void event_dump( struct object *obj, int verbose ); static struct object *event_get_sync( struct object *obj ); -static int event_signal( struct object *obj, unsigned int access); +static int event_signal( struct object *obj ); static struct list *event_get_kernel_obj_list( struct object *obj ); static void event_destroy( struct object *obj );
@@ -211,7 +212,7 @@ static const struct object_ops keyed_event_ops = remove_queue, /* remove_queue */ keyed_event_signaled, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -281,16 +282,10 @@ static struct object *event_get_sync( struct object *obj ) return grab_object( event->sync ); }
-static int event_signal( struct object *obj, unsigned int access ) +static int event_signal( struct object *obj ) { struct event *event = (struct event *)obj; assert( obj->ops == &event_ops ); - - if (!(access & EVENT_MODIFY_STATE)) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } set_event( event ); return 1; } diff --git a/server/fd.c b/server/fd.c index 1b932cc3ae3..307de7afc07 100644 --- a/server/fd.c +++ b/server/fd.c @@ -169,7 +169,7 @@ static const struct object_ops fd_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ fd_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -211,7 +211,7 @@ static const struct object_ops device_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -252,7 +252,7 @@ static const struct object_ops inode_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -297,7 +297,7 @@ static const struct object_ops file_lock_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ file_lock_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/file.c b/server/file.c index cc5acc2aadc..840d635441d 100644 --- a/server/file.c +++ b/server/file.c @@ -95,7 +95,7 @@ static const struct object_ops file_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ file_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/handle.c b/server/handle.c index ddcf03accb2..27cccc9b249 100644 --- a/server/handle.c +++ b/server/handle.c @@ -127,7 +127,7 @@ static const struct object_ops handle_table_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/hook.c b/server/hook.c index e53ba4514bf..3ca96a44f7d 100644 --- a/server/hook.c +++ b/server/hook.c @@ -81,7 +81,7 @@ static const struct object_ops hook_table_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/inproc_sync.c b/server/inproc_sync.c index f20410c85ed..4615a5b3335 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -71,7 +71,7 @@ static const struct object_ops inproc_sync_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/mailslot.c b/server/mailslot.c index 430566d044d..f116b79f54a 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -83,7 +83,7 @@ static const struct object_ops mailslot_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ mailslot_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ mailslot_map_access, /* map_access */ @@ -145,7 +145,7 @@ static const struct object_ops mail_writer_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ mail_writer_get_fd, /* get_fd */ default_get_sync, /* get_sync */ mail_writer_map_access, /* map_access */ @@ -211,7 +211,7 @@ static const struct object_ops mailslot_device_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -242,7 +242,7 @@ static const struct object_ops mailslot_device_file_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ mailslot_device_file_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/mapping.c b/server/mapping.c index c3f57b6394c..63914d5a65e 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -68,7 +68,7 @@ static const struct object_ops ranges_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -105,7 +105,7 @@ static const struct object_ops shared_map_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -179,7 +179,7 @@ static const struct object_ops mapping_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ mapping_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/mutex.c b/server/mutex.c index e370d301472..b92328ecd20 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -48,6 +48,7 @@ struct type_descr mutex_type = STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, MUTANT_ALL_ACCESS }, + SYNCHRONIZE, /* signal access */ };
struct mutex_sync @@ -73,7 +74,7 @@ static const struct object_ops mutex_sync_ops = remove_queue, /* remove_queue */ mutex_sync_signaled, /* signaled */ mutex_sync_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -174,7 +175,7 @@ struct mutex
static void mutex_dump( struct object *obj, int verbose ); static struct object *mutex_get_sync( struct object *obj ); -static int mutex_signal( struct object *obj, unsigned int access ); +static int mutex_signal( struct object *obj ); static void mutex_destroy( struct object *obj );
static const struct object_ops mutex_ops = @@ -251,16 +252,10 @@ static struct object *mutex_get_sync( struct object *obj ) return grab_object( mutex->sync ); }
-static int mutex_signal( struct object *obj, unsigned int access ) +static int mutex_signal( struct object *obj ) { struct mutex *mutex = (struct mutex *)obj; assert( obj->ops == &mutex_ops ); - - if (!(access & SYNCHRONIZE)) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } return do_release( mutex->sync, current, 1 ); }
diff --git a/server/named_pipe.c b/server/named_pipe.c index e67b25bac5d..6871585d660 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -120,7 +120,7 @@ static const struct object_ops named_pipe_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ named_pipe_map_access, /* map_access */ @@ -169,7 +169,7 @@ static const struct object_ops pipe_server_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ pipe_end_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -214,7 +214,7 @@ static const struct object_ops pipe_client_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ pipe_end_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -263,7 +263,7 @@ static const struct object_ops named_pipe_device_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -295,7 +295,7 @@ static const struct object_ops named_pipe_device_file_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ named_pipe_device_file_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -346,7 +346,7 @@ static const struct object_ops named_pipe_dir_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ named_pipe_dir_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/object.c b/server/object.c index 356956aad6a..b5f9be18412 100644 --- a/server/object.c +++ b/server/object.c @@ -110,7 +110,7 @@ static const struct object_ops apc_reserve_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -135,7 +135,7 @@ static const struct object_ops completion_reserve_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -630,12 +630,6 @@ void no_satisfied( struct object *obj, struct wait_queue_entry *entry ) { }
-int no_signal( struct object *obj, unsigned int access ) -{ - set_error( STATUS_OBJECT_TYPE_MISMATCH ); - return 0; -} - struct fd *no_get_fd( struct object *obj ) { set_error( STATUS_OBJECT_TYPE_MISMATCH ); diff --git a/server/object.h b/server/object.h index 51b74429e73..af84f1fa6a2 100644 --- a/server/object.h +++ b/server/object.h @@ -56,6 +56,7 @@ struct type_descr struct unicode_str name; /* type name */ unsigned int valid_access; /* mask for valid access bits */ struct generic_map mapping; /* generic access mapping */ + unsigned int signal_access; /* mask for valid signal access */ unsigned int index; /* index in global array of types */ unsigned int obj_count; /* count of objects of this type */ unsigned int handle_count; /* count of handles of this type */ @@ -81,7 +82,7 @@ struct object_ops /* wait satisfied */ void (*satisfied)(struct object *,struct wait_queue_entry *); /* signal an object */ - int (*signal)(struct object *, unsigned int); + int (*signal)(struct object *); /* return an fd object that can be used to read/write from the object */ struct fd *(*get_fd)(struct object *); /* return a sync that can be used to wait/signal the object */ @@ -170,7 +171,6 @@ extern struct object *find_object( const struct namespace *namespace, const stru extern struct object *find_object_index( const struct namespace *namespace, unsigned int index ); extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry ); extern void no_satisfied( struct object *obj, struct wait_queue_entry *entry ); -extern int no_signal( struct object *obj, unsigned int access ); extern struct fd *no_get_fd( struct object *obj ); extern struct object *default_get_sync( struct object *obj ); static inline struct object *get_obj_sync( struct object *obj ) { return obj->ops->get_sync( obj ); } diff --git a/server/process.c b/server/process.c index 8e0f9189a61..d77a70bc655 100644 --- a/server/process.c +++ b/server/process.c @@ -107,7 +107,7 @@ static const struct object_ops process_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ process_get_sync, /* get_sync */ process_map_access, /* map_access */ @@ -160,7 +160,7 @@ static const struct object_ops startup_info_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ startup_info_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -222,7 +222,7 @@ static const struct object_ops job_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ job_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/queue.c b/server/queue.c index 596742bc64c..7623485d676 100644 --- a/server/queue.c +++ b/server/queue.c @@ -169,7 +169,7 @@ static const struct object_ops msg_queue_ops = msg_queue_remove_queue, /* remove_queue */ msg_queue_signaled, /* signaled */ msg_queue_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -207,7 +207,7 @@ static const struct object_ops thread_input_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/registry.c b/server/registry.c index 7cfefc7a6c3..3ceb9b00558 100644 --- a/server/registry.c +++ b/server/registry.c @@ -181,7 +181,7 @@ static const struct object_ops key_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ key_map_access, /* map_access */ diff --git a/server/request.c b/server/request.c index 835ea30cec3..a6b7e71cf15 100644 --- a/server/request.c +++ b/server/request.c @@ -90,7 +90,7 @@ static const struct object_ops master_socket_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/semaphore.c b/server/semaphore.c index 4b31bfe806c..f0ab1a10596 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -48,6 +48,7 @@ struct type_descr semaphore_type = STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE, SEMAPHORE_ALL_ACCESS }, + SEMAPHORE_MODIFY_STATE, /* signal access */ };
struct semaphore_sync @@ -70,7 +71,7 @@ static const struct object_ops semaphore_sync_ops = remove_queue, /* remove_queue */ semaphore_sync_signaled, /* signaled */ semaphore_sync_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -148,7 +149,7 @@ struct semaphore
static void semaphore_dump( struct object *obj, int verbose ); static struct object *semaphore_get_sync( struct object *obj ); -static int semaphore_signal( struct object *obj, unsigned int access ); +static int semaphore_signal( struct object *obj ); static void semaphore_destroy( struct object *obj );
static const struct object_ops semaphore_ops = @@ -218,16 +219,10 @@ static struct object *semaphore_get_sync( struct object *obj ) return grab_object( sem->sync ); }
-static int semaphore_signal( struct object *obj, unsigned int access ) +static int semaphore_signal( struct object *obj ) { struct semaphore *sem = (struct semaphore *)obj; assert( obj->ops == &semaphore_ops ); - - if (!(access & SEMAPHORE_MODIFY_STATE)) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } return release_semaphore( sem->sync, 1, NULL ); }
diff --git a/server/serial.c b/server/serial.c index 66cb4aabfbc..40150080ce1 100644 --- a/server/serial.c +++ b/server/serial.c @@ -92,7 +92,7 @@ static const struct object_ops serial_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ serial_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/signal.c b/server/signal.c index 078951af6e4..f7a03b3aaf1 100644 --- a/server/signal.c +++ b/server/signal.c @@ -63,7 +63,7 @@ static const struct object_ops handler_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/sock.c b/server/sock.c index 7785d3c7706..75971c3980a 100644 --- a/server/sock.c +++ b/server/sock.c @@ -487,7 +487,7 @@ static const struct object_ops sock_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ sock_get_fd, /* get_fd */ default_fd_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -3707,7 +3707,7 @@ static const struct object_ops ifchange_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ ifchange_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -3929,7 +3929,7 @@ static const struct object_ops socket_device_ops = NULL, /* remove_queue */ NULL, /* signaled */ no_satisfied, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/symlink.c b/server/symlink.c index 238dcfad1c7..f294e7f0912 100644 --- a/server/symlink.c +++ b/server/symlink.c @@ -72,7 +72,7 @@ static const struct object_ops symlink_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/thread.c b/server/thread.c index 64cd1a74702..b6d6d2230d1 100644 --- a/server/thread.c +++ b/server/thread.c @@ -109,7 +109,7 @@ static const struct object_ops thread_apc_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ thread_apc_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -154,7 +154,7 @@ static const struct object_ops context_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ context_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -204,7 +204,7 @@ static const struct object_ops thread_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ thread_get_sync, /* get_sync */ thread_map_access, /* map_access */ @@ -1257,6 +1257,14 @@ static void thread_timeout( void *ptr ) wake_thread( thread ); }
+/* check if an event flag, a semaphore or a mutex can be signaled */ +static unsigned int check_signal_access( struct object *obj, unsigned int access ) +{ + if (!obj->ops->type->signal_access) return STATUS_OBJECT_TYPE_MISMATCH; + if (!(access & obj->ops->type->signal_access)) return STATUS_ACCESS_DENIED; + return STATUS_SUCCESS; +} + /* try signaling an event flag, a semaphore or a mutex */ static int signal_object( obj_handle_t handle ) { @@ -1266,7 +1274,9 @@ static int signal_object( obj_handle_t handle ) obj = get_handle_obj( current->process, handle, 0, NULL ); if (obj) { - ret = obj->ops->signal( obj, get_handle_access( current->process, handle )); + unsigned int status, access = get_handle_access( current->process, handle ); + if ((status = check_signal_access( obj, access ))) set_error( status ); + else ret = obj->ops->signal( obj ); release_object( obj ); } return ret; diff --git a/server/timer.c b/server/timer.c index 522fc6a7113..4d2adf18672 100644 --- a/server/timer.c +++ b/server/timer.c @@ -77,7 +77,7 @@ static const struct object_ops timer_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ timer_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/token.c b/server/token.c index 5ce7298211e..f1502b718a8 100644 --- a/server/token.c +++ b/server/token.c @@ -146,7 +146,7 @@ static const struct object_ops token_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/window.c b/server/window.c index e237d40a153..86e89158cf6 100644 --- a/server/window.c +++ b/server/window.c @@ -109,7 +109,7 @@ static const struct object_ops window_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ diff --git a/server/winstation.c b/server/winstation.c index bfcd4a53613..a747af51162 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -77,7 +77,7 @@ static const struct object_ops winstation_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */ @@ -118,7 +118,7 @@ static const struct object_ops desktop_ops = NULL, /* remove_queue */ NULL, /* signaled */ NULL, /* satisfied */ - no_signal, /* signal */ + NULL, /* signal */ no_get_fd, /* get_fd */ default_get_sync, /* get_sync */ default_map_access, /* map_access */
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/sync.c | 42 +++++++++++++++++++++++++++++++++++++++--- server/inproc_sync.c | 1 + server/protocol.def | 3 ++- server/thread.c | 2 +- server/thread.h | 1 + 5 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index acdb7b3d9f8..2894e75d6f2 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -309,9 +309,10 @@ static unsigned int validate_open_object_attributes( const OBJECT_ATTRIBUTES *at
struct inproc_sync { - int fd; - unsigned int access; - unsigned int type : 2; + int fd; /* unix file descriptor */ + unsigned int access; /* handle access rights */ + unsigned short type; /* enum inproc_sync_type as short to save space */ + unsigned short internal; /* sync is internal and cannot be signaled */ };
static void release_inproc_sync( struct inproc_sync *sync ) @@ -339,6 +340,7 @@ static NTSTATUS get_inproc_sync( HANDLE handle, ACCESS_MASK desired_access, stru assert( wine_server_ptr_handle(fd_handle) == handle ); sync->access = reply->access; sync->type = reply->type; + sync->internal = reply->internal; } } SERVER_END_REQ; @@ -355,6 +357,21 @@ static NTSTATUS get_inproc_sync( HANDLE handle, ACCESS_MASK desired_access, stru return STATUS_SUCCESS; }
+extern unsigned int check_signal_access( struct inproc_sync *sync ) +{ + if (sync->internal) return STATUS_OBJECT_TYPE_MISMATCH; + + switch (sync->type) + { + case INPROC_SYNC_EVENT: + if (!(sync->access & EVENT_MODIFY_STATE)) return STATUS_ACCESS_DENIED; + return STATUS_SUCCESS; + } + + assert( 0 ); + return STATUS_OBJECT_TYPE_MISMATCH; +} + static NTSTATUS inproc_release_semaphore( HANDLE handle, ULONG count, ULONG *prev_count ) { if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; @@ -429,7 +446,26 @@ static NTSTATUS inproc_wait( DWORD count, const HANDLE *handles, BOOLEAN wait_an static NTSTATUS inproc_signal_and_wait( HANDLE signal, HANDLE wait, BOOLEAN alertable, const LARGE_INTEGER *timeout ) { + struct inproc_sync stack_signal, stack_wait, *signal_sync = &stack_signal, *wait_sync = &stack_wait; + NTSTATUS ret; + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; + + if ((ret = get_inproc_sync( signal, 0, signal_sync ))) return ret; + if ((ret = check_signal_access( signal_sync ))) + { + release_inproc_sync( signal_sync ); + return ret; + } + + if ((ret = get_inproc_sync( wait, SYNCHRONIZE, wait_sync ))) + { + release_inproc_sync( signal_sync ); + return ret; + } + + release_inproc_sync( signal_sync ); + release_inproc_sync( wait_sync ); return STATUS_NOT_IMPLEMENTED; }
diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 4615a5b3335..5c7dc1ae770 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -182,6 +182,7 @@ DECL_HANDLER(get_inproc_sync_fd) if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
reply->access = get_handle_access( current->process, req->handle ); + reply->internal = check_signal_access( obj, reply->access ) == STATUS_OBJECT_TYPE_MISMATCH;
if ((fd = get_inproc_sync_fd( obj, &reply->type )) < 0) set_error( STATUS_NOT_IMPLEMENTED ); else send_client_fd( current->process, fd, req->handle ); diff --git a/server/protocol.def b/server/protocol.def index 59c6436fa88..f6f0324054d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -4135,5 +4135,6 @@ enum inproc_sync_type obj_handle_t handle; /* handle to the object */ @REPLY int type; /* inproc sync type */ - unsigned int access; /* handle access rights */ + int internal; /* sync is an internal event sync */ + unsigned int access; /* handle access rights */ @END diff --git a/server/thread.c b/server/thread.c index b6d6d2230d1..a725800fb42 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1258,7 +1258,7 @@ static void thread_timeout( void *ptr ) }
/* check if an event flag, a semaphore or a mutex can be signaled */ -static unsigned int check_signal_access( struct object *obj, unsigned int access ) +unsigned int check_signal_access( struct object *obj, unsigned int access ) { if (!obj->ops->type->signal_access) return STATUS_OBJECT_TYPE_MISMATCH; if (!(access & obj->ops->type->signal_access)) return STATUS_ACCESS_DENIED; diff --git a/server/thread.h b/server/thread.h index b33a00d9f26..9b6e0c2a03b 100644 --- a/server/thread.h +++ b/server/thread.h @@ -117,6 +117,7 @@ extern void set_wait_status( struct wait_queue_entry *entry, int status ); extern void stop_thread( struct thread *thread ); extern int wake_thread( struct thread *thread ); extern int wake_thread_queue_entry( struct wait_queue_entry *entry ); +extern unsigned int check_signal_access( struct object *obj, unsigned int access ); extern int add_queue( struct object *obj, struct wait_queue_entry *entry ); extern void remove_queue( struct object *obj, struct wait_queue_entry *entry ); extern void kill_thread( struct thread *thread, int violent_death );
From: Elizabeth Figura zfigura@codeweavers.com
Some objects like async or completion waits are internal only, and their sync logic is still a bit complicated as they have various server side effects. They are only waited on alone, we can keep using server-side syncs for them. --- dlls/ntdll/unix/server.c | 15 +++++++++++++++ dlls/ntdll/unix/sync.c | 4 ++-- dlls/ntdll/unix/unix_private.h | 3 ++- 3 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index e8da94ebc64..25cc9bf0cbf 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -818,6 +818,21 @@ unsigned int server_wait( const union select_op *select_op, data_size_t size, UI }
+/* helper function to perform a server-side wait on an internal handle without + * using the fast synchronization path */ +unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ) +{ + union select_op select_op; + UINT flags = SELECT_INTERRUPTIBLE; + + if (alertable) flags |= SELECT_ALERTABLE; + + select_op.wait.op = SELECT_WAIT; + select_op.wait.handles[0] = wine_server_obj_handle( handle ); + return server_wait( &select_op, offsetof( union select_op, wait.handles[1] ), flags, timeout ); +} + + /*********************************************************************** * NtContinue (NTDLL.@) */ diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index 2894e75d6f2..eae3d49af5a 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -2324,7 +2324,7 @@ NTSTATUS WINAPI NtRemoveIoCompletion( HANDLE handle, ULONG_PTR *key, ULONG_PTR * } SERVER_END_REQ; if (status != STATUS_PENDING) return status; - if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, FALSE, timeout ); + if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, FALSE, timeout ); else status = STATUS_TIMEOUT; if (status != WAIT_OBJECT_0) return status;
@@ -2388,7 +2388,7 @@ NTSTATUS WINAPI NtRemoveIoCompletionEx( HANDLE handle, FILE_IO_COMPLETION_INFORM assert( status == STATUS_USER_APC ); goto done; } - if (!timeout || timeout->QuadPart) status = NtWaitForSingleObject( wait_handle, alertable, timeout ); + if (!timeout || timeout->QuadPart) status = server_wait_for_object( wait_handle, alertable, timeout ); else status = STATUS_TIMEOUT; if (status != WAIT_OBJECT_0) goto done;
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 974766b97a7..bd2d6a19334 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -230,6 +230,7 @@ extern unsigned int server_select( const union select_op *select_op, data_size_t timeout_t abs_timeout, struct context_data *context, struct user_apc *user_apc ); extern unsigned int server_wait( const union select_op *select_op, data_size_t size, UINT flags, const LARGE_INTEGER *timeout ); +extern unsigned int server_wait_for_object( HANDLE handle, BOOL alertable, const LARGE_INTEGER *timeout ); extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, union apc_result *result ); extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd, @@ -470,7 +471,7 @@ static inline struct async_data server_async( HANDLE handle, struct async_fileio
static inline NTSTATUS wait_async( HANDLE handle, BOOL alertable ) { - return NtWaitForSingleObject( handle, alertable, NULL ); + return server_wait_for_object( handle, alertable, NULL ); }
static inline BOOL in_wow64_call(void)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/message.c | 6 +++--- dlls/win32u/ntuser_private.h | 1 - dlls/win32u/sysparams.c | 4 +++- include/ntuser.h | 1 + 4 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 035ab6574e4..aafb46a7cc0 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3103,10 +3103,10 @@ static void process_sent_messages(void) */ static HANDLE get_server_queue_handle(void) { - struct user_thread_info *thread_info = get_user_thread_info(); + struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); HANDLE ret;
- if (!(ret = thread_info->server_queue)) + if (!(ret = UlongToHandle( thread_info->server_queue ))) { SERVER_START_REQ( get_msg_queue_handle ) { @@ -3114,7 +3114,7 @@ static HANDLE get_server_queue_handle(void) ret = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; - thread_info->server_queue = ret; + thread_info->server_queue = HandleToUlong( ret ); if (!ret) ERR( "Cannot get server thread queue\n" ); } return ret; diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index f5559c5ca4f..e546703f71b 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -100,7 +100,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 last_getmsg_time; /* Get/PeekMessage last request time */ LONGLONG last_driver_time; /* Get/PeekMessage driver event time */ WORD hook_call_depth; /* Number of recursively called hook procs */ diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index a242bc493fa..5f391a50a86 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -7047,6 +7047,7 @@ BOOL is_exiting_thread( DWORD tid ) static void thread_detach(void) { struct user_thread_info *thread_info = get_user_thread_info(); + HANDLE server_queue = UlongToHandle( thread_info->client_info.server_queue );
destroy_thread_windows(); user_driver->pThreadDetach(); @@ -7054,7 +7055,8 @@ static void thread_detach(void) free( thread_info->rawinput );
cleanup_imm_thread(); - NtClose( thread_info->server_queue ); + if (server_queue) NtClose( server_queue ); + thread_info->client_info.server_queue = 0; free( thread_info->session_data );
exiting_thread_id = 0; diff --git a/include/ntuser.h b/include/ntuser.h index ef09d7e97bb..1de2569bade 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -134,6 +134,7 @@ struct ntuser_thread_info UINT default_imc; /* default input context */ UINT64 client_imm; /* client IMM thread info */ UINT64 wmchar_data; /* client data for WM_CHAR mappings */ + UINT server_queue; /* handle of the server-side queue */ };
static inline struct ntuser_thread_info *NtUserGetThreadInfo(void)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/ntdll/unix/server.c | 5 +++++ dlls/ntdll/unix/thread.c | 20 ++++++++++++++++++-- dlls/ntdll/unix/unix_private.h | 1 + dlls/ntdll/unix/virtual.c | 9 +++++---- server/inproc_sync.c | 4 ++-- server/object.h | 1 + server/protocol.def | 2 ++ server/queue.c | 2 +- server/thread.c | 19 ++++++++++++++++++- server/thread.h | 1 + 10 files changed, 54 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 25cc9bf0cbf..220abacd4d2 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1677,6 +1677,11 @@ size_t server_init_process(void) inproc_device_fd = wine_server_receive_fd( &handle ); assert( handle == reply->inproc_device ); } + if (reply->queue_handle) + { + data->queue_sync_fd = wine_server_receive_fd( &handle ); + assert( handle == reply->queue_handle ); + } } } SERVER_END_REQ; diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 7f61a37bf2b..9eaae846970 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1104,6 +1104,7 @@ static void contexts_from_server( CONTEXT *context, struct context_data server_c */ static DECLSPEC_NORETURN void pthread_exit_wrapper( int status ) { + close( ntdll_get_thread_data()->queue_sync_fd ); close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); @@ -1324,7 +1325,7 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT struct object_attributes *objattr; struct ntdll_thread_data *thread_data; DWORD tid = 0; - int request_pipe[2]; + int request_pipe[2], queue_sync_fd = -1; TEB *teb; unsigned int status;
@@ -1376,6 +1377,11 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT
if (!access) access = THREAD_ALL_ACCESS;
+ /* We need to use fd_cache_mutex here to protect against races with + * other threads trying to receive fds for the fd cache, + * and we need to use an uninterrupted section to prevent reentrancy. */ + server_enter_uninterrupted_section( &fd_cache_mutex, &sigset ); + SERVER_START_REQ( new_thread ) { req->process = wine_server_obj_handle( process ); @@ -1385,6 +1391,12 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT wine_server_add_data( req, objattr, len ); if (!(status = wine_server_call( req ))) { + obj_handle_t token; + if (reply->queue_handle) + { + queue_sync_fd = wine_server_receive_fd( &token ); + assert( token == reply->queue_handle ); + } *handle = wine_server_ptr_handle( reply->handle ); tid = reply->tid; } @@ -1392,6 +1404,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT } SERVER_END_REQ;
+ server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + free( objattr ); if (status) { @@ -1412,7 +1426,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT set_thread_id( teb, GetCurrentProcessId(), tid );
thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - thread_data->request_fd = request_pipe[1]; + thread_data->request_fd = request_pipe[1]; + thread_data->queue_sync_fd = queue_sync_fd; thread_data->start = start; thread_data->param = param;
@@ -1434,6 +1449,7 @@ done: if (status) { NtClose( *handle ); + if (queue_sync_fd != -1) close( queue_sync_fd ); close( request_pipe[1] ); return status; } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index bd2d6a19334..98fb4dd6c74 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -108,6 +108,7 @@ struct ntdll_thread_data int request_fd; /* fd for sending server requests */ int reply_fd; /* fd for receiving server replies */ int wait_fd[2]; /* fd for sleeping server requests */ + int queue_sync_fd; /* inproc sync fd for message queue */ BOOL allow_writes; /* ThreadAllowWrites flags */ pthread_t pthread_id; /* pthread thread id */ void *kernel_stack; /* stack for thread startup and kernel syscalls */ diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 4b4d9d6cd7f..2b21715e1eb 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4022,10 +4022,11 @@ static TEB *init_teb( void *ptr, BOOL is_wow ) teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch; - thread_data->request_fd = -1; - thread_data->reply_fd = -1; - thread_data->wait_fd[0] = -1; - thread_data->wait_fd[1] = -1; + thread_data->request_fd = -1; + thread_data->reply_fd = -1; + thread_data->wait_fd[0] = -1; + thread_data->wait_fd[1] = -1; + thread_data->queue_sync_fd = -1; list_add_head( &teb_list, &thread_data->entry ); return teb; } diff --git a/server/inproc_sync.c b/server/inproc_sync.c index 5c7dc1ae770..a0973f42cca 100644 --- a/server/inproc_sync.c +++ b/server/inproc_sync.c @@ -127,7 +127,7 @@ static void inproc_sync_destroy( struct object *obj ) close( sync->fd ); }
-static int get_inproc_sync_fd( struct object *obj, int *type ) +int get_inproc_sync_fd( struct object *obj, int *type ) { struct object *sync; int fd = -1; @@ -167,7 +167,7 @@ void reset_inproc_sync( struct inproc_sync *sync ) { }
-static int get_inproc_sync_fd( struct object *obj, int *type ) +int get_inproc_sync_fd( struct object *obj, int *type ) { return -1; } diff --git a/server/object.h b/server/object.h index af84f1fa6a2..2a475b84c59 100644 --- a/server/object.h +++ b/server/object.h @@ -247,6 +247,7 @@ extern int get_inproc_device_fd(void); extern struct inproc_sync *create_inproc_event_sync( int manual, int signaled ); extern void signal_inproc_sync( struct inproc_sync *sync ); extern void reset_inproc_sync( struct inproc_sync *sync ); +extern int get_inproc_sync_fd( struct object *obj, int *type );
/* serial functions */
diff --git a/server/protocol.def b/server/protocol.def index f6f0324054d..a6cef01721e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1091,6 +1091,7 @@ struct obj_locator @REPLY thread_id_t tid; /* thread id */ obj_handle_t handle; /* thread handle (in the current process) */ + obj_handle_t queue_handle; /* inproc queue fd in flight with this handle */ @END
@@ -1127,6 +1128,7 @@ struct obj_locator timeout_t server_start; /* server start time */ unsigned int session_id; /* process session id */ obj_handle_t inproc_device;/* inproc device fd in flight with this handle */ + obj_handle_t queue_handle; /* inproc queue fd in flight with this handle */ data_size_t info_size; /* total size of startup info */ VARARG(machines,ushorts); /* array of supported machines */ @END diff --git a/server/queue.c b/server/queue.c index 7623485d676..c51a29c6a8c 100644 --- a/server/queue.c +++ b/server/queue.c @@ -328,7 +328,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_ list_init( &queue->expired_timers ); for (i = 0; i < NB_MSG_KINDS; i++) list_init( &queue->msg_list[i] );
- if (get_inproc_device_fd() >= 0 && !(queue->inproc_sync = create_inproc_event_sync( 1, 0 ))) goto error; + if (thread->queue_sync) queue->inproc_sync = (struct inproc_sync *)grab_object( thread->queue_sync ); if (!(queue->shared = alloc_shared_object())) goto error;
SHARED_WRITE_BEGIN( queue->shared, queue_shm_t ) diff --git a/server/thread.c b/server/thread.c index a725800fb42..45b65526a0f 100644 --- a/server/thread.c +++ b/server/thread.c @@ -397,6 +397,7 @@ static inline void init_thread_structure( struct thread *thread ) int i;
thread->sync = NULL; + thread->queue_sync = NULL; thread->unix_pid = -1; /* not known yet */ thread->unix_tid = -1; /* not known yet */ thread->context = NULL; @@ -560,6 +561,10 @@ struct thread *create_thread( int fd, struct process *process, const struct secu } if (!(thread->request_fd = create_anonymous_fd( &thread_fd_ops, fd, &thread->obj, 0 ))) goto error; if (!(thread->sync = create_event_sync( 1, 0 ))) goto error; + if (get_inproc_device_fd() >= 0) + { + if (!(thread->queue_sync = create_inproc_event_sync( 1, 0 ))) goto error; + }
if (process->desktop) { @@ -654,6 +659,7 @@ static void destroy_thread( struct object *obj ) release_object( thread->process ); if (thread->id) free_ptid( thread->id ); if (thread->token) release_object( thread->token ); + if (thread->queue_sync) release_object( thread->queue_sync ); if (thread->sync) release_object( thread->sync ); }
@@ -1631,6 +1637,7 @@ DECL_HANDLER(new_thread) const struct security_descriptor *sd; const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); int request_fd = thread_get_inflight_fd( current, req->request_fd ); + int fd, type;
if (!(process = get_process_from_handle( req->process, 0 ))) { @@ -1675,6 +1682,11 @@ DECL_HANDLER(new_thread) if ((reply->handle = alloc_handle_no_access_check( current->process, thread, req->access, objattr->attributes ))) { + if (thread->queue_sync && (fd = get_inproc_sync_fd( (struct object *)thread->queue_sync, &type )) >= 0) + { + reply->queue_handle = get_thread_id( thread ) | 1; + send_client_fd( thread->process, fd, reply->queue_handle ); + } /* thread object will be released when the thread gets killed */ goto done; } @@ -1719,7 +1731,7 @@ static int init_thread( struct thread *thread, int reply_fd, int wait_fd ) DECL_HANDLER(init_first_thread) { struct process *process = current->process; - int fd; + int fd, type;
if (!init_thread( current, req->reply_fd, req->wait_fd )) return;
@@ -1748,6 +1760,11 @@ DECL_HANDLER(init_first_thread) reply->inproc_device = get_process_id( process ) | 1; send_client_fd( process, fd, reply->inproc_device ); } + if (current->queue_sync && (fd = get_inproc_sync_fd( (struct object *)current->queue_sync, &type )) >= 0) + { + reply->queue_handle = get_thread_id( current ) | 1; + send_client_fd( process, fd, reply->queue_handle ); + } }
/* initialize a new thread */ diff --git a/server/thread.h b/server/thread.h index 9b6e0c2a03b..0952257ed84 100644 --- a/server/thread.h +++ b/server/thread.h @@ -51,6 +51,7 @@ struct thread { struct object obj; /* object header */ struct event_sync *sync; /* sync object for wait/signal */ + struct inproc_sync *queue_sync; /* inproc sync for message queue */ struct list entry; /* entry in system-wide thread list */ struct list proc_entry; /* entry in per-process thread list */ struct list desktop_entry; /* entry in per-desktop thread list */
From: Elizabeth Figura zfigura@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 );
I still think that a separate type for internal events would be cleaner than adding a flag.