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.
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 | 36 ++++++++++++++++++++++++++++++++++++ server/inproc_sync.c | 1 + server/protocol.def | 3 ++- server/thread.c | 2 +- server/thread.h | 1 + 5 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/sync.c b/dlls/ntdll/unix/sync.c index acdb7b3d9f8..706f8376b81 100644 --- a/dlls/ntdll/unix/sync.c +++ b/dlls/ntdll/unix/sync.c @@ -312,6 +312,7 @@ struct inproc_sync int fd; unsigned int access; unsigned int type : 2; + unsigned int internal : 1; };
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[2], *signal_sync = stack + 0, *wait_sync = stack + 1; + NTSTATUS ret; + if (inproc_device_fd < 0) return STATUS_NOT_IMPLEMENTED; + + if ((ret = get_inproc_sync( signal, 0, stack + 0 ))) return ret; + if ((ret = check_signal_access( signal_sync ))) + { + release_inproc_sync( signal_sync ); + return ret; + } + + if ((ret = get_inproc_sync( wait, SYNCHRONIZE, stack + 1 ))) + { + 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 706f8376b81..ce5e8cd9623 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 | 28 +++++++++++++++++++++++++--- dlls/ntdll/unix/thread.c | 3 ++- dlls/ntdll/unix/unix_private.h | 3 ++- 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 | 21 ++++++++++++++++++++- server/thread.h | 1 + 10 files changed, 61 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 25cc9bf0cbf..d82b8073c9d 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; @@ -1768,25 +1773,42 @@ void server_init_process_done(void) * * Send an init thread request. */ -void server_init_thread( void *entry_point, BOOL *suspend ) +void server_init_thread( struct ntdll_thread_data *data, BOOL *suspend ) { + sigset_t sigset; void *teb; int reply_pipe = init_thread_pipe();
/* always send the native TEB */ if (!(teb = NtCurrentTeb64())) teb = NtCurrentTeb();
+ /* 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( init_thread ) { req->unix_tid = get_unix_tid(); req->teb = wine_server_client_ptr( teb ); - req->entry = wine_server_client_ptr( entry_point ); + req->entry = wine_server_client_ptr( data->start ); req->reply_fd = reply_pipe; req->wait_fd = ntdll_get_thread_data()->wait_fd[1]; - wine_server_call( req ); + if (!wine_server_call( req )) + { + obj_handle_t handle; + if (reply->queue_handle) + { + data->queue_sync_fd = wine_server_receive_fd( &handle ); + assert( handle == reply->queue_handle ); + } + } *suspend = reply->suspend; } SERVER_END_REQ; + + server_leave_uninterrupted_section( &fd_cache_mutex, &sigset ); + close( reply_pipe ); }
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 7f61a37bf2b..a6f09b068b5 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 ); @@ -1126,7 +1127,7 @@ static void start_thread( TEB *teb ) thread_data->syscall_trace = TRACE_ON(syscall); thread_data->pthread_id = pthread_self(); pthread_setspecific( teb_key, teb ); - server_init_thread( thread_data->start, &suspend ); + server_init_thread( thread_data, &suspend ); signal_start_thread( thread_data->start, thread_data->param, suspend, teb ); }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index bd2d6a19334..887ff5a24f5 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 */ @@ -240,7 +241,7 @@ extern int wine_server_receive_fd( obj_handle_t *handle ); extern void process_exit_wrapper( int status ) DECLSPEC_NORETURN; extern size_t server_init_process(void); extern void server_init_process_done(void); -extern void server_init_thread( void *entry_point, BOOL *suspend ); +extern void server_init_thread( struct ntdll_thread_data *data, BOOL *suspend ); extern int server_pipe( int fd[2] );
extern void fpux_to_fpu( I386_FLOATING_SAVE_AREA *fpu, const XSAVE_FORMAT *fpux ); 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..d5b41b1eb5a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1127,6 +1127,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 @@ -1141,6 +1142,7 @@ struct obj_locator client_ptr_t entry; /* entry point (in thread address space) */ @REPLY int suspend; /* is thread suspended? */ + obj_handle_t queue_handle; /* inproc queue fd in flight with this handle */ @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..d37d1a609f1 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 ); }
@@ -1719,7 +1725,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,11 +1754,18 @@ 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 ) | 3; + send_client_fd( process, fd, reply->queue_handle ); + } }
/* initialize a new thread */ DECL_HANDLER(init_thread) { + int fd, type; + if (!init_thread( current, req->reply_fd, req->wait_fd )) return;
if (!is_valid_address(req->teb)) @@ -1772,6 +1785,12 @@ DECL_HANDLER(init_thread) set_thread_affinity( current, current->affinity );
reply->suspend = (is_thread_suspended( current ) || current->context != NULL); + + 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( current->process, fd, reply->queue_handle ); + } }
/* terminate a 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 ce5e8cd9623..2c91901930a 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[2], *signal_sync = stack + 0, *wait_sync = stack + 1; 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 d5b41b1eb5a..3226aef101f 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 );
This merge request was approved by Rémi Bernon.
``` unsigned int access; unsigned int type : 2; + unsigned int internal : 1; ```
How many more bitfields are you planning to use here? We could just make these uint8_t or uint16_t (or bool) instead, and that would be nicer to the compiler and the CPU.
``` + struct inproc_sync stack[2], *signal_sync = stack + 0, *wait_sync = stack + 1; ```
It's not my place to criticize style in ntdll, but why are we converting this into an array when it wasn't one previously, and why are we using pointer arithmetic to address it instead of &stack[0]?
``` @@ -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 */ ```
Why are we storing this in ntdll?
How many more bitfields are you planning to use here? We could just make these uint8_t or uint16_t (or bool) instead, and that would be nicer to the compiler and the CPU.
Only one more for the closed bit. Sure this could be changed to some other type as long as we keep it small, if you think it really matters. Would unsigned char be better?
Why are we storing this in ntdll?
This is to avoid having to special case the message queue in get_inproc_sync_fd request: the only object that request can be called with are normal objects, and retrieving their inproc sync can be done with `get_sync` object op directly.
It will also later make it unnecessary to cache it, saving some space and specific treatment there too, and avoiding any risk of eviction.
It's not my place to criticize style in ntdll, but why are we converting this into an array when it wasn't one previously, and why are we using pointer arithmetic to address it instead of &stack[0]?
Just a matter of taste I suppose, &...[] is much harder to type, I don't think it matters?
How many more bitfields are you planning to use here? We could just make these uint8_t or uint16_t (or bool) instead, and that would be nicer to the compiler and the CPU.
Only one more for the closed bit. Sure this could be changed to some other type as long as we keep it small, if you think it really matters. Would unsigned char be better?
They tend to be better than bitfields, as I understand. I don't think there's any reason to ever use bitfields, anywhere, if using uint8_t/bool takes up just as much space.
On Tue Sep 2 18:53:48 2025 +0000, Rémi Bernon wrote:
It's not my place to criticize style in ntdll, but why are we
converting this into an array when it wasn't one previously, and why are we using pointer arithmetic to address it instead of &stack[0]? Just a matter of taste I suppose, &...[] is much harder to type, I don't think it matters?
Why change it to an array in the first place, though? I really don't see how this is an improvement.
On Tue Sep 2 18:58:20 2025 +0000, Elizabeth Figura wrote:
Why change it to an array in the first place, though? I really don't see how this is an improvement.
It's just stack reservation, didn't seem to me that the stack location variables deserved to be separate or named. Anyway, I'll restore like it was if you prefer.