For https://gitlab.winehq.org/wine/wine/-/merge_requests/7512 to use it to locate window shared objects.
-- v17: win32u: Use the session shared object for user handle entries. win32u: Use the session shared object to implement is_window. server: Move the user object handle table to the shared memory. server: Allocate a session shared memory header structure. server: Use NTUSER_OBJ constants for user object types. server: Remove const qualifier from shared memory pointers. include: Implement ReadAcquire64.
From: Rémi Bernon rbernon@codeweavers.com
--- include/winnt.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/include/winnt.h b/include/winnt.h index 31d836029f1..980ece57367 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -7117,6 +7117,22 @@ static FORCEINLINE LONG ReadAcquire( LONG const volatile *src ) return value; }
+static FORCEINLINE LONG64 ReadAcquire64( LONG64 const volatile *src ) +{ + LONG64 value; +#if defined(__i386__) && _MSC_VER < 1700 + __asm { + mov eax, src + fild qword ptr [eax] + fistp value + } +#else + value = __WINE_LOAD64_NO_FENCE( (__int64 const volatile *)src ); + __wine_memory_barrier_acq_rel(); +#endif + return value; +} + static FORCEINLINE LONG ReadNoFence( LONG const volatile *src ) { LONG value = __WINE_LOAD32_NO_FENCE( (int const volatile *)src ); @@ -7331,6 +7347,17 @@ static FORCEINLINE LONG ReadAcquire( LONG const volatile *src ) return value; }
+static FORCEINLINE LONG64 ReadAcquire64( LONG64 const volatile *src ) +{ + LONG64 value; +#ifdef __i386__ + __asm__ __volatile__( "fildq %1\n\tfistpq %0" : "=m" (value) : "m" (*src) : "memory", "st" ); +#else + __WINE_ATOMIC_LOAD_ACQUIRE( src, &value ); +#endif + return value; +} + static FORCEINLINE LONG ReadNoFence( LONG const volatile *src ) { LONG value;
From: Rémi Bernon rbernon@codeweavers.com
--- server/file.h | 11 +++--- server/mapping.c | 8 ++-- server/queue.c | 98 ++++++++++++++++++++++++------------------------ server/user.h | 2 +- 4 files changed, 59 insertions(+), 60 deletions(-)
diff --git a/server/file.h b/server/file.h index 59b73c0245c..8fc82a460ff 100644 --- a/server/file.h +++ b/server/file.h @@ -193,15 +193,14 @@ extern struct mapping *create_session_mapping( struct object *root, const struct unsigned int attr, const struct security_descriptor *sd ); extern void set_session_mapping( struct mapping *mapping );
-extern const volatile void *alloc_shared_object(void); -extern void free_shared_object( const volatile void *object_shm ); -extern void invalidate_shared_object( const volatile void *object_shm ); -extern struct obj_locator get_shared_object_locator( const volatile void *object_shm ); +extern volatile void *alloc_shared_object(void); +extern void free_shared_object( volatile void *object_shm ); +extern void invalidate_shared_object( volatile void *object_shm ); +extern struct obj_locator get_shared_object_locator( volatile void *object_shm );
#define SHARED_WRITE_BEGIN( object_shm, type ) \ do { \ - const type *__shared = (object_shm); \ - type *shared = (type *)__shared; \ + type *shared = (object_shm); \ shared_object_t *__obj = CONTAINING_RECORD( shared, shared_object_t, shm ); \ LONG64 __seq = __obj->seq + 1, __end = __seq + 1; \ assert( (__seq & 1) != 0 ); \ diff --git a/server/mapping.c b/server/mapping.c index 247b28cf6f5..a74573efe0e 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -1375,7 +1375,7 @@ static struct session_block *find_free_session_block( mem_size_t size ) return grow_session_mapping( size ); }
-const volatile void *alloc_shared_object(void) +volatile void *alloc_shared_object(void) { struct session_object *object; struct list *ptr; @@ -1407,7 +1407,7 @@ const volatile void *alloc_shared_object(void) return &object->obj.shm; }
-void free_shared_object( const volatile void *object_shm ) +void free_shared_object( volatile void *object_shm ) { struct session_object *object = CONTAINING_RECORD( object_shm, struct session_object, obj.shm );
@@ -1422,7 +1422,7 @@ void free_shared_object( const volatile void *object_shm ) }
/* invalidate client caches for a shared object by giving it a new id */ -void invalidate_shared_object( const volatile void *object_shm ) +void invalidate_shared_object( volatile void *object_shm ) { struct session_object *object = CONTAINING_RECORD( object_shm, struct session_object, obj.shm );
@@ -1433,7 +1433,7 @@ void invalidate_shared_object( const volatile void *object_shm ) SHARED_WRITE_END; }
-struct obj_locator get_shared_object_locator( const volatile void *object_shm ) +struct obj_locator get_shared_object_locator( volatile void *object_shm ) { struct session_object *object = CONTAINING_RECORD( object_shm, struct session_object, obj.shm ); struct obj_locator locator = {.offset = object->offset, .id = object->obj.id}; diff --git a/server/queue.c b/server/queue.c index b4b6069f927..cfbc9e6c89b 100644 --- a/server/queue.c +++ b/server/queue.c @@ -109,7 +109,7 @@ struct thread_input int caret_state; /* caret on/off state */ struct list msg_list; /* list of hardware messages */ unsigned char desktop_keystate[256]; /* desktop keystate when keystate was synced */ - const input_shm_t *shared; /* thread input in session shared memory */ + input_shm_t *shared; /* thread input in session shared memory */ };
struct msg_queue @@ -133,7 +133,7 @@ struct msg_queue struct hook_table *hooks; /* hook table */ timeout_t last_get_msg; /* time of last get message call */ int keystate_lock; /* owns an input keystate lock */ - const queue_shm_t *shared; /* queue in session shared memory */ + queue_shm_t *shared; /* queue in session shared memory */ };
struct hotkey @@ -359,8 +359,8 @@ void free_msg_queue( struct thread *thread ) /* synchronize thread input keystate with the desktop */ static void sync_input_keystate( struct thread_input *input ) { - const input_shm_t *input_shm = input->shared; - const desktop_shm_t *desktop_shm; + input_shm_t *input_shm = input->shared; + desktop_shm_t *desktop_shm; int i;
if (!input->desktop || input_shm->keystate_lock) return; @@ -380,7 +380,7 @@ static void sync_input_keystate( struct thread_input *input ) /* locks thread input keystate to prevent synchronization */ static void lock_input_keystate( struct thread_input *input ) { - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared;
SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { @@ -392,7 +392,7 @@ static void lock_input_keystate( struct thread_input *input ) /* unlock the thread input keystate and synchronize it again */ static void unlock_input_keystate( struct thread_input *input ) { - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared;
SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { @@ -407,7 +407,7 @@ static void unlock_input_keystate( struct thread_input *input ) static int assign_thread_input( struct thread *thread, struct thread_input *new_input ) { struct msg_queue *queue = thread->queue; - const input_shm_t *input_shm; + input_shm_t *input_shm;
if (!queue) { @@ -471,7 +471,7 @@ static struct message *alloc_hardware_message( lparam_t info, struct hw_msg_sour
static int is_cursor_clipped( struct desktop *desktop ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; struct rectangle top_rect, clip_rect = desktop_shm->cursor.clip; get_virtual_screen_rect( desktop, &top_rect, 1 ); return !is_rect_equal( &clip_rect, &top_rect ); @@ -481,7 +481,7 @@ static void queue_cursor_message( struct desktop *desktop, user_handle_t win, un lparam_t wparam, lparam_t lparam ) { static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM }; - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; struct thread_input *input; struct message *msg;
@@ -518,7 +518,7 @@ static int update_desktop_cursor_window( struct desktop *desktop, user_handle_t
if (updated && (input = get_desktop_cursor_thread_input( desktop ))) { - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared; user_handle_t handle = input_shm->cursor_count < 0 ? 0 : input_shm->cursor; /* when clipping send the message to the foreground window as well, as some driver have an artificial overlay window */ if (is_cursor_clipped( desktop )) queue_cursor_message( desktop, 0, WM_WINE_SETCURSOR, win, handle ); @@ -530,7 +530,7 @@ static int update_desktop_cursor_window( struct desktop *desktop, user_handle_t
static int update_desktop_cursor_pos( struct desktop *desktop, user_handle_t win, int x, int y ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; int updated; unsigned int time = get_tick_count();
@@ -588,7 +588,7 @@ static void set_cursor_pos( struct desktop *desktop, int x, int y ) /* sync cursor position after window change */ void update_cursor_pos( struct desktop *desktop ) { - const desktop_shm_t *desktop_shm; + desktop_shm_t *desktop_shm;
desktop_shm = desktop->shared; set_cursor_pos( desktop, desktop_shm->cursor.x, desktop_shm->cursor.y ); @@ -598,7 +598,7 @@ void update_cursor_pos( struct desktop *desktop ) static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsigned int *time ) { struct desktop *desktop = queue->input->desktop; - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared;
*x = desktop_shm->cursor.x; *y = desktop_shm->cursor.y; @@ -608,7 +608,7 @@ static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsig /* set the cursor clip rectangle */ void set_clip_rectangle( struct desktop *desktop, const struct rectangle *rect, unsigned int flags, int reset ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; struct rectangle top_rect, new_rect; unsigned int old_flags; int x, y; @@ -650,7 +650,7 @@ void set_clip_rectangle( struct desktop *desktop, const struct rectangle *rect, /* change the foreground input and reset the cursor clip rect */ static void set_foreground_input( struct desktop *desktop, struct thread_input *input ) { - const input_shm_t *input_shm, *old_input_shm; + input_shm_t *input_shm, *old_input_shm; shared_object_t dummy_obj = {0};
if (desktop->foreground_input == input) return; @@ -706,7 +706,7 @@ void add_queue_hook_count( struct thread *thread, unsigned int index, int count /* check the queue status */ static inline int is_signaled( struct msg_queue *queue ) { - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared; return (queue_shm->wake_bits & queue_shm->wake_mask) || (queue_shm->changed_bits & queue_shm->changed_mask); } @@ -714,7 +714,7 @@ static inline int is_signaled( struct msg_queue *queue ) /* set some queue bits */ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) { - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared;
if (bits & (QS_KEY | QS_MOUSEBUTTON)) { @@ -735,7 +735,7 @@ static inline void set_queue_bits( struct msg_queue *queue, unsigned int bits ) /* clear some queue bits */ static inline void clear_queue_bits( struct msg_queue *queue, unsigned int bits ) { - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared;
SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) { @@ -1300,7 +1300,7 @@ static void msg_queue_remove_queue(struct object *obj, struct wait_queue_entry * static void msg_queue_dump( struct object *obj, int verbose ) { struct msg_queue *queue = (struct msg_queue *)obj; - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared; fprintf( stderr, "Msg queue bits=%x mask=%x\n", queue_shm->wake_bits, queue_shm->wake_mask ); } @@ -1325,7 +1325,7 @@ static int msg_queue_signaled( struct object *obj, struct wait_queue_entry *entr static void msg_queue_satisfied( struct object *obj, struct wait_queue_entry *entry ) { struct msg_queue *queue = (struct msg_queue *)obj; - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared;
SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) { @@ -1340,7 +1340,7 @@ static void msg_queue_destroy( struct object *obj ) struct msg_queue *queue = (struct msg_queue *)obj; struct list *ptr; struct hotkey *hotkey, *hotkey2; - const input_shm_t *input_shm = queue->input->shared; + input_shm_t *input_shm = queue->input->shared; int i;
cleanup_results( queue ); @@ -1393,7 +1393,7 @@ static void msg_queue_poll_event( struct fd *fd, int event ) static void thread_input_dump( struct object *obj, int verbose ) { struct thread_input *input = (struct thread_input *)obj; - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared; fprintf( stderr, "Thread input focus=%08x capture=%08x active=%08x\n", input_shm->focus, input_shm->capture, input_shm->active ); } @@ -1416,7 +1416,7 @@ static void thread_input_destroy( struct object *obj ) static inline void thread_input_cleanup_window( struct msg_queue *queue, user_handle_t window ) { struct thread_input *input = queue->input; - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared;
SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { @@ -1454,7 +1454,7 @@ static int check_queue_input_window( struct msg_queue *queue, user_handle_t wind void check_thread_queue_idle( struct thread *thread ) { struct msg_queue *queue = thread->queue; - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared;
if ((queue_shm->wake_mask & QS_SMRESULT)) return; if (thread->process->idle_event) set_event( thread->process->idle_event ); @@ -1488,7 +1488,7 @@ int attach_thread_input( struct thread *thread_from, struct thread *thread_to )
if (thread_from->queue) { - const input_shm_t *old_input_shm, *input_shm; + input_shm_t *old_input_shm, *input_shm; old_input = thread_from->queue->input; old_input_shm = old_input->shared; input_shm = input->shared; @@ -1504,7 +1504,7 @@ int attach_thread_input( struct thread *thread_from, struct thread *thread_to ) ret = assign_thread_input( thread_from, input ); if (ret) { - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared; SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { memset( (void *)shared->keystate, 0, sizeof(shared->keystate) ); @@ -1523,7 +1523,7 @@ void detach_thread_input( struct thread *thread_from )
if ((input = create_thread_input( thread_from ))) { - const input_shm_t *old_input_shm, *input_shm; + input_shm_t *old_input_shm, *input_shm; old_input_shm = old_input->shared; input_shm = input->shared;
@@ -1767,7 +1767,7 @@ static void update_key_state( volatile unsigned char *keystate, unsigned int msg
static void update_thread_input_key_state( struct thread_input *input, unsigned int msg, lparam_t wparam ) { - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared; SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { update_key_state( shared->keystate, msg, wparam, 0 ); @@ -1816,7 +1816,7 @@ static void release_hardware_message( struct msg_queue *queue, unsigned int hw_i
static int queue_hotkey_message( struct desktop *desktop, struct message *msg ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; struct hotkey *hotkey; unsigned int modifiers = 0;
@@ -1857,7 +1857,7 @@ static user_handle_t find_hardware_message_window( struct desktop *desktop, stru struct message *msg, unsigned int *msg_code, struct thread **thread ) { - const input_shm_t *input_shm = input ? input->shared : NULL; + input_shm_t *input_shm = input ? input->shared : NULL; user_handle_t win = 0;
*thread = NULL; @@ -1930,7 +1930,7 @@ static unsigned int get_rawinput_device_flags( struct process *process, struct m /* queue a hardware message into a given thread input */ static void queue_hardware_message( struct desktop *desktop, struct message *msg, int always_queue ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; user_handle_t win; struct thread *thread; struct thread_input *input; @@ -2042,7 +2042,7 @@ static struct thread *get_foreground_thread( struct desktop *desktop, user_handl /* if desktop has no foreground process, assume the receiving window is */ if (desktop->foreground_input) { - const input_shm_t *input_shm = desktop->foreground_input->shared; + input_shm_t *input_shm = desktop->foreground_input->shared; return get_window_thread( input_shm->focus ); } if (window) return get_window_thread( window ); @@ -2247,7 +2247,7 @@ static void dispatch_rawinput_message( struct desktop *desktop, struct rawinput_ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const union hw_input *input, unsigned int origin, struct msg_queue *sender ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; struct hardware_msg_data *msg_data; struct rawinput_message raw_msg; struct message *msg; @@ -2372,7 +2372,7 @@ static void stop_key_repeat( struct desktop *desktop ) static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, const union hw_input *input, unsigned int origin, struct msg_queue *sender, int repeat ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; struct hw_msg_source source = { IMDT_KEYBOARD, origin }; struct hardware_msg_data *msg_data; struct message *msg; @@ -2563,7 +2563,7 @@ static void queue_pointer_message( struct pointer *pointer, int repeated ) }; struct hw_msg_source source = { IMDT_UNAVAILABLE, IMDT_TOUCH }; struct desktop *desktop = pointer->desktop; - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; const union hw_input *input = &pointer->input; unsigned int i, wparam = input->hw.wparam; timeout_t time = get_tick_count(); @@ -2642,7 +2642,7 @@ static struct pointer *find_pointer_from_id( struct desktop *desktop, unsigned i static void queue_custom_hardware_message( struct desktop *desktop, user_handle_t win, unsigned int origin, const union hw_input *input ) { - const desktop_shm_t *desktop_shm = desktop->shared; + desktop_shm_t *desktop_shm = desktop->shared; struct hw_msg_source source = { IMDT_UNAVAILABLE, origin }; struct thread *foreground; struct pointer *pointer; @@ -3140,7 +3140,7 @@ DECL_HANDLER(set_queue_mask)
if (queue) { - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared;
SHARED_WRITE_BEGIN( queue_shm, queue_shm_t ) { @@ -3176,7 +3176,7 @@ DECL_HANDLER(get_queue_status) struct msg_queue *queue = current->queue; if (queue) { - const queue_shm_t *queue_shm = queue->shared; + queue_shm_t *queue_shm = queue->shared;
reply->wake_bits = queue_shm->wake_bits; reply->changed_bits = queue_shm->changed_bits; @@ -3277,7 +3277,7 @@ DECL_HANDLER(send_hardware_message) struct desktop *desktop; unsigned int origin = (req->flags & SEND_HWMSG_INJECTED ? IMO_INJECTED : IMO_HARDWARE); struct msg_queue *sender = req->flags & SEND_HWMSG_INJECTED ? get_current_queue() : NULL; - const desktop_shm_t *desktop_shm; + desktop_shm_t *desktop_shm; int wait = 0;
if (!(desktop = get_hardware_input_desktop( req->win ))) return; @@ -3334,7 +3334,7 @@ DECL_HANDLER(get_message) struct list *ptr; struct msg_queue *queue = get_current_queue(); user_handle_t get_win = get_user_full_handle( req->get_win ); - const queue_shm_t *queue_shm; + queue_shm_t *queue_shm; unsigned int filter;
if (get_win && get_win != 1 && get_win != -1 && !get_user_object( get_win, USER_WINDOW )) @@ -3804,7 +3804,7 @@ DECL_HANDLER(get_key_state) else { struct msg_queue *queue = get_current_queue(); - const input_shm_t *input_shm = queue->input->shared; + input_shm_t *input_shm = queue->input->shared; unsigned char *keystate = (void *)input_shm->keystate; sync_input_keystate( queue->input ); reply->state = keystate[req->key & 0xff]; @@ -3818,7 +3818,7 @@ DECL_HANDLER(set_key_state) struct msg_queue *queue = get_current_queue(); struct desktop *desktop = queue->input->desktop; data_size_t size = min( 256, get_req_data_size() ); - const input_shm_t *input_shm = queue->input->shared; + input_shm_t *input_shm = queue->input->shared;
SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { @@ -3879,7 +3879,7 @@ DECL_HANDLER(set_focus_window) reply->previous = 0; if (queue && check_queue_input_window( queue, req->handle )) { - const input_shm_t *input_shm = queue->input->shared; + input_shm_t *input_shm = queue->input->shared; SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { reply->previous = shared->focus; @@ -3900,7 +3900,7 @@ DECL_HANDLER(set_active_window) { if (!req->handle || make_window_active( req->handle )) { - const input_shm_t *input_shm = queue->input->shared; + input_shm_t *input_shm = queue->input->shared; SHARED_WRITE_BEGIN( input_shm, input_shm_t ) { reply->previous = shared->active; @@ -3922,7 +3922,7 @@ DECL_HANDLER(set_capture_window) if (queue && check_queue_input_window( queue, req->handle )) { struct thread_input *input = queue->input; - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared;
/* if in menu mode, reject all requests to change focus, except if the menu bit is set */ if (input_shm->menu_owner && !(req->flags & CAPTURE_MENU)) @@ -3954,7 +3954,7 @@ DECL_HANDLER(set_caret_window) if (queue && check_queue_input_window( queue, req->handle )) { struct thread_input *input = queue->input; - const input_shm_t *input_shm = input->shared; + input_shm_t *input_shm = input->shared; user_handle_t caret = get_user_full_handle(req->handle);
reply->previous = input_shm->caret; @@ -3977,7 +3977,7 @@ DECL_HANDLER(set_caret_window) DECL_HANDLER(set_caret_info) { struct msg_queue *queue = get_current_queue(); - const input_shm_t *input_shm; + input_shm_t *input_shm; struct thread_input *input;
if (!queue) return; @@ -4036,9 +4036,9 @@ DECL_HANDLER(set_cursor) struct msg_queue *queue = get_current_queue(); user_handle_t prev_cursor, new_cursor; struct thread_input *input; - const input_shm_t *input_shm; + input_shm_t *input_shm; struct desktop *desktop; - const desktop_shm_t *desktop_shm; + desktop_shm_t *desktop_shm;
if (!queue) return; input = queue->input; diff --git a/server/user.h b/server/user.h index ce463b9395d..3040dffee75 100644 --- a/server/user.h +++ b/server/user.h @@ -94,7 +94,7 @@ struct desktop struct key_repeat key_repeat; /* key auto-repeat */ unsigned int clip_flags; /* last cursor clip flags */ user_handle_t cursor_win; /* window that contains the cursor */ - const desktop_shm_t *shared; /* desktop session shared memory */ + desktop_shm_t *shared; /* desktop session shared memory */ };
/* user handles functions */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/ntuser_private.h | 8 ++++---- dlls/win32u/window.c | 10 ++++++---- server/hook.c | 6 +++--- server/protocol.def | 2 ++ server/queue.c | 4 ++-- server/user.c | 30 ++++++++++++++++++++++-------- server/user.h | 17 +++++------------ server/window.c | 24 ++++++++++++------------ 8 files changed, 56 insertions(+), 45 deletions(-)
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index fbc3c0d6d64..ae2a8b04d22 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -231,11 +231,11 @@ extern BOOL vulkan_init(void); extern void vulkan_detach_surfaces( struct list *surfaces );
/* window.c */ -HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ); -void *free_user_handle( HANDLE handle, unsigned int type ); -void *get_user_handle_ptr( HANDLE handle, unsigned int type ); +HANDLE alloc_user_handle( struct user_object *ptr, unsigned short type ); +void *free_user_handle( HANDLE handle, unsigned short type ); +void *get_user_handle_ptr( HANDLE handle, unsigned short type ); void release_user_handle_ptr( void *ptr ); -void *next_process_user_handle_ptr( HANDLE *handle, unsigned int type ); +void *next_process_user_handle_ptr( HANDLE *handle, unsigned short type ); UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask );
static inline UINT win_get_flags( HWND hwnd ) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 9acb9350144..81396fb06d0 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -55,12 +55,13 @@ static void *user_handles[NB_USER_HANDLES]; /*********************************************************************** * alloc_user_handle */ -HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) +HANDLE alloc_user_handle( struct user_object *ptr, unsigned short type ) { HANDLE handle = 0;
SERVER_START_REQ( alloc_user_handle ) { + req->type = type; if (!wine_server_call_err( req )) handle = wine_server_ptr_handle( reply->handle ); } SERVER_END_REQ; @@ -80,7 +81,7 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) /*********************************************************************** * get_user_handle_ptr */ -void *get_user_handle_ptr( HANDLE handle, unsigned int type ) +void *get_user_handle_ptr( HANDLE handle, unsigned short type ) { struct user_object *ptr; WORD index = USER_HANDLE_TO_INDEX( handle ); @@ -106,7 +107,7 @@ void *get_user_handle_ptr( HANDLE handle, unsigned int type ) * * user_lock must be held by caller. */ -void *next_process_user_handle_ptr( HANDLE *handle, unsigned int type ) +void *next_process_user_handle_ptr( HANDLE *handle, unsigned short type ) { struct user_object *ptr; WORD index = *handle ? USER_HANDLE_TO_INDEX( *handle ) + 1 : 0; @@ -143,7 +144,7 @@ void release_user_handle_ptr( void *ptr ) /*********************************************************************** * free_user_handle */ -void *free_user_handle( HANDLE handle, unsigned int type ) +void *free_user_handle( HANDLE handle, unsigned short type ) { struct user_object *ptr; WORD index = USER_HANDLE_TO_INDEX( handle ); @@ -152,6 +153,7 @@ void *free_user_handle( HANDLE handle, unsigned int type ) { SERVER_START_REQ( free_user_handle ) { + req->type = type; req->handle = wine_server_user_handle( handle ); if (wine_server_call( req )) ptr = NULL; else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr ); diff --git a/server/hook.c b/server/hook.c index ffe7206369e..bf2ad266e76 100644 --- a/server/hook.c +++ b/server/hook.c @@ -153,7 +153,7 @@ static struct hook *add_hook( struct desktop *desktop, struct process *process, } if (!(hook = mem_alloc( sizeof(*hook) ))) return NULL;
- if (!(hook->handle = alloc_user_handle( hook, USER_HOOK ))) + if (!(hook->handle = alloc_user_handle( hook, NTUSER_OBJ_HOOK ))) { free( hook ); return NULL; @@ -502,7 +502,7 @@ DECL_HANDLER(remove_hook)
if (req->handle) { - if (!(hook = get_user_object( req->handle, USER_HOOK ))) + if (!(hook = get_user_object( req->handle, NTUSER_OBJ_HOOK ))) { set_error( STATUS_INVALID_HANDLE ); return; @@ -589,7 +589,7 @@ DECL_HANDLER(get_hook_info) { struct hook *hook;
- if (!(hook = get_user_object( req->handle, USER_HOOK ))) return; + if (!(hook = get_user_object( req->handle, NTUSER_OBJ_HOOK ))) return; if (hook->thread && (hook->thread != current)) { set_error( STATUS_INVALID_HANDLE ); diff --git a/server/protocol.def b/server/protocol.def index 8bfce724756..8ff35b6e401 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3930,6 +3930,7 @@ struct handle_info
/* Allocate an arbitrary user handle */ @REQ(alloc_user_handle) + unsigned short type; /* user object type */ @REPLY user_handle_t handle; /* allocated handle */ @END @@ -3937,6 +3938,7 @@ struct handle_info
/* Free an arbitrary user handle */ @REQ(free_user_handle) + unsigned short type; /* user object type */ user_handle_t handle; /* handle to free*/ @END
diff --git a/server/queue.c b/server/queue.c index cfbc9e6c89b..10c8b70f659 100644 --- a/server/queue.c +++ b/server/queue.c @@ -3337,7 +3337,7 @@ DECL_HANDLER(get_message) queue_shm_t *queue_shm; unsigned int filter;
- if (get_win && get_win != 1 && get_win != -1 && !get_user_object( get_win, USER_WINDOW )) + if (get_win && get_win != 1 && get_win != -1 && !get_user_object( get_win, NTUSER_OBJ_WINDOW )) { set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); return; @@ -4053,7 +4053,7 @@ DECL_HANDLER(set_cursor) reply->prev_y = desktop_shm->cursor.y;
if ((req->flags & SET_CURSOR_HANDLE) && req->handle && - !get_user_object( req->handle, USER_CLIENT )) + !get_user_object( req->handle, NTUSER_OBJ_ICON )) { set_win32_error( ERROR_INVALID_CURSOR_HANDLE ); return; diff --git a/server/user.c b/server/user.c index 2d038a6ddbf..22d72c669e7 100644 --- a/server/user.c +++ b/server/user.c @@ -90,7 +90,7 @@ static inline void *free_user_entry( struct user_handle *ptr ) }
/* allocate a user handle for a given object */ -user_handle_t alloc_user_handle( void *ptr, enum user_object type ) +user_handle_t alloc_user_handle( void *ptr, unsigned short type ) { struct user_handle *entry = alloc_user_entry(); if (!entry) return 0; @@ -101,7 +101,7 @@ user_handle_t alloc_user_handle( void *ptr, enum user_object type ) }
/* return a pointer to a user object from its handle */ -void *get_user_object( user_handle_t handle, enum user_object type ) +void *get_user_object( user_handle_t handle, unsigned short type ) { struct user_handle *entry;
@@ -120,7 +120,7 @@ user_handle_t get_user_full_handle( user_handle_t handle ) }
/* same as get_user_object plus set the handle to the full 32-bit value */ -void *get_user_object_handle( user_handle_t *handle, enum user_object type ) +void *get_user_object_handle( user_handle_t *handle, unsigned short type ) { struct user_handle *entry;
@@ -143,7 +143,7 @@ void *free_user_handle( user_handle_t handle ) }
/* return the next user handle after 'handle' that is of a given type */ -void *next_user_handle( user_handle_t *handle, enum user_object type ) +void *next_user_handle( user_handle_t *handle, unsigned short type ) { struct user_handle *entry;
@@ -172,14 +172,28 @@ void free_process_user_handles( struct process *process ) unsigned int i;
for (i = 0; i < nb_handles; i++) - if (handles[i].type == USER_CLIENT && handles[i].ptr == process) - free_user_entry( &handles[i] ); + { + switch (handles[i].type) + { + case NTUSER_OBJ_MENU: + case NTUSER_OBJ_ICON: + case NTUSER_OBJ_WINPOS: + case NTUSER_OBJ_ACCEL: + case NTUSER_OBJ_IMC: + if (handles[i].ptr == process) free_user_entry( &handles[i] ); + break; + case NTUSER_OBJ_HOOK: + case NTUSER_OBJ_WINDOW: + default: + continue; + } + } }
/* allocate an arbitrary user handle */ DECL_HANDLER(alloc_user_handle) { - reply->handle = alloc_user_handle( current->process, USER_CLIENT ); + reply->handle = alloc_user_handle( current->process, req->type ); }
@@ -188,7 +202,7 @@ DECL_HANDLER(free_user_handle) { struct user_handle *entry;
- if ((entry = handle_to_entry( req->handle )) && entry->type == USER_CLIENT) + if ((entry = handle_to_entry( req->handle )) && entry->type == req->type) free_user_entry( entry ); else set_error( STATUS_INVALID_HANDLE ); diff --git a/server/user.h b/server/user.h index 3040dffee75..23c2c338210 100644 --- a/server/user.h +++ b/server/user.h @@ -34,13 +34,6 @@ struct window_class; struct atom_table; struct clipboard;
-enum user_object -{ - USER_WINDOW = 1, - USER_HOOK, - USER_CLIENT /* arbitrary client handle */ -}; - #define DESKTOP_ATOM ((atom_t)32769)
#define MAX_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1) @@ -99,12 +92,12 @@ struct desktop
/* user handles functions */
-extern user_handle_t alloc_user_handle( void *ptr, enum user_object type ); -extern void *get_user_object( user_handle_t handle, enum user_object type ); -extern void *get_user_object_handle( user_handle_t *handle, enum user_object type ); +extern user_handle_t alloc_user_handle( void *ptr, unsigned short type ); +extern void *get_user_object( user_handle_t handle, unsigned short type ); +extern void *get_user_object_handle( user_handle_t *handle, unsigned short type ); extern user_handle_t get_user_full_handle( user_handle_t handle ); extern void *free_user_handle( user_handle_t handle ); -extern void *next_user_handle( user_handle_t *handle, enum user_object type ); +extern void *next_user_handle( user_handle_t *handle, unsigned short type ); extern void free_process_user_handles( struct process *process );
/* clipboard functions */ @@ -314,7 +307,7 @@ static inline void union_rect( struct rectangle *dest, const struct rectangle *s /* validate a window handle and return the full handle */ static inline user_handle_t get_valid_window_handle( user_handle_t win ) { - if (get_user_object_handle( &win, USER_WINDOW )) return win; + if (get_user_object_handle( &win, NTUSER_OBJ_WINDOW )) return win; set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); return 0; } diff --git a/server/window.c b/server/window.c index f7f9d5e517f..1eb815dfe3e 100644 --- a/server/window.c +++ b/server/window.c @@ -185,7 +185,7 @@ static void window_destroy( struct object *obj ) /* retrieve a pointer to a window from its handle */ static inline struct window *get_window( user_handle_t handle ) { - struct window *ret = get_user_object( handle, USER_WINDOW ); + struct window *ret = get_user_object( handle, NTUSER_OBJ_WINDOW ); if (!ret) set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); return ret; } @@ -672,7 +672,7 @@ static struct window *create_window( struct window *parent, struct window *owner memset( win->extra_bytes, 0, extra_bytes ); win->nb_extra_bytes = extra_bytes; } - if (!(win->handle = alloc_user_handle( win, USER_WINDOW ))) goto failed; + if (!(win->handle = alloc_user_handle( win, NTUSER_OBJ_WINDOW ))) goto failed; win->last_active = win->handle;
/* if parent belongs to a different thread and the window isn't */ @@ -728,7 +728,7 @@ void destroy_thread_windows( struct thread *thread ) user_handle_t handle = 0; struct window *win;
- while ((win = next_user_handle( &handle, USER_WINDOW ))) + while ((win = next_user_handle( &handle, NTUSER_OBJ_WINDOW ))) { if (win->thread != thread) continue; if (is_desktop_window( win )) detach_window_thread( win ); @@ -751,8 +751,8 @@ static struct window *get_desktop_window( struct thread *thread ) /* check whether child is a descendant of parent */ int is_child_window( user_handle_t parent, user_handle_t child ) { - struct window *child_ptr = get_user_object( child, USER_WINDOW ); - struct window *parent_ptr = get_user_object( parent, USER_WINDOW ); + struct window *child_ptr = get_user_object( child, NTUSER_OBJ_WINDOW ); + struct window *parent_ptr = get_user_object( parent, NTUSER_OBJ_WINDOW );
if (!child_ptr || !parent_ptr) return 0; while (child_ptr->parent) @@ -766,7 +766,7 @@ int is_child_window( user_handle_t parent, user_handle_t child ) /* check if window can be set as foreground window */ int is_valid_foreground_window( user_handle_t window ) { - struct window *win = get_user_object( window, USER_WINDOW ); + struct window *win = get_user_object( window, NTUSER_OBJ_WINDOW ); return win && (win->style & (WS_POPUP|WS_CHILD)) != WS_CHILD; }
@@ -782,7 +782,7 @@ int make_window_active( user_handle_t window ) while (owner) { owner->last_active = win->handle; - owner = get_user_object( owner->owner, USER_WINDOW ); + owner = get_user_object( owner->owner, NTUSER_OBJ_WINDOW ); } return 1; } @@ -860,14 +860,14 @@ static int is_visible( const struct window *win ) /* same as is_visible but takes a window handle */ int is_window_visible( user_handle_t window ) { - struct window *win = get_user_object( window, USER_WINDOW ); + struct window *win = get_user_object( window, NTUSER_OBJ_WINDOW ); if (!win) return 0; return is_visible( win ); }
int is_window_transparent( user_handle_t window ) { - struct window *win = get_user_object( window, USER_WINDOW ); + struct window *win = get_user_object( window, NTUSER_OBJ_WINDOW ); if (!win) return 0; return (win->ex_style & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT); } @@ -1026,7 +1026,7 @@ user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) /* return thread of top-most window containing point (in absolute raw coords) */ struct thread *window_thread_from_point( user_handle_t scope, int x, int y ) { - struct window *win = get_user_object( scope, USER_WINDOW ); + struct window *win = get_user_object( scope, NTUSER_OBJ_WINDOW );
if (!win) return NULL;
@@ -1068,7 +1068,7 @@ static int all_windows_from_point( struct window *top, int x, int y, unsigned in /* return the thread owning a window */ struct thread *get_window_thread( user_handle_t handle ) { - struct window *win = get_user_object( handle, USER_WINDOW ); + struct window *win = get_user_object( handle, NTUSER_OBJ_WINDOW ); if (!win || !win->thread) return NULL; return (struct thread *)grab_object( win->thread ); } @@ -2326,7 +2326,7 @@ DECL_HANDLER(get_window_info) reply->is_unicode = win->is_unicode; reply->dpi_context = win->dpi_context;
- if (get_user_object( win->last_active, USER_WINDOW )) reply->last_active = win->last_active; + if (get_user_object( win->last_active, NTUSER_OBJ_WINDOW )) reply->last_active = win->last_active; if (win->thread) { reply->tid = get_thread_id( win->thread );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/class.c | 5 +++++ dlls/win32u/gdiobj.c | 2 -- dlls/win32u/ntgdi_private.h | 2 -- dlls/win32u/win32u_private.h | 3 +++ dlls/win32u/winstation.c | 12 ++++++++++++ server/file.h | 1 + server/mapping.c | 6 ++++-- server/protocol.def | 5 +++++ 8 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index ea0d7efe74b..8c5f2819a67 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -36,6 +36,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(class); WINE_DECLARE_DEBUG_CHANNEL(win);
+SYSTEM_BASIC_INFORMATION system_info; + #define MAX_WINPROCS 4096 #define WINPROC_PROC16 ((void *)1) /* placeholder for 16-bit window procs */
@@ -248,6 +250,9 @@ DLGPROC get_dialog_proc( DLGPROC ret, BOOL ansi )
static void init_user(void) { + NtQuerySystemInformation( SystemBasicInformation, &system_info, sizeof(system_info), NULL ); + + shared_session_init(); gdi_init(); sysparams_init(); winstation_init(); diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index ec8b7d20ea2..ff354a0a529 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -48,7 +48,6 @@ static GDI_SHARED_MEMORY *gdi_shared; static GDI_HANDLE_ENTRY *next_free; static GDI_HANDLE_ENTRY *next_unused; static LONG debug_count; -SYSTEM_BASIC_INFORMATION system_info;
static inline HGDIOBJ entry_to_handle( GDI_HANDLE_ENTRY *entry ) { @@ -1040,7 +1039,6 @@ void gdi_init(void) pthread_mutex_init( &gdi_lock, &attr ); pthread_mutexattr_destroy( &attr );
- NtQuerySystemInformation( SystemBasicInformation, &system_info, sizeof(system_info), NULL ); init_gdi_shared(); if (!gdi_shared) return;
diff --git a/dlls/win32u/ntgdi_private.h b/dlls/win32u/ntgdi_private.h index 99ebb127d68..136921a211c 100644 --- a/dlls/win32u/ntgdi_private.h +++ b/dlls/win32u/ntgdi_private.h @@ -641,6 +641,4 @@ extern void free_heap_bits( struct gdi_image_bits *bits );
void set_gdi_client_ptr( HGDIOBJ handle, void *ptr );
-extern SYSTEM_BASIC_INFORMATION system_info; - #endif /* __WINE_NTGDI_PRIVATE_H */ diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 80ca1058d97..19c666928a8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -218,6 +218,7 @@ struct object_lock * The data read from the objects may be transient and no logic should be executed based * on it, within the loop, or after, unless the function has returned STATUS_SUCCESS. */ +extern const session_shm_t *shared_session; extern NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm ); extern NTSTATUS get_shared_queue( struct object_lock *lock, const queue_shm_t **queue_shm ); extern NTSTATUS get_shared_input( UINT tid, struct object_lock *lock, const input_shm_t **input_shm ); @@ -279,6 +280,8 @@ static inline void release_win_ptr( struct tagWND *ptr ) user_unlock(); }
+extern SYSTEM_BASIC_INFORMATION system_info; +extern void shared_session_init(void); extern void gdi_init(void); extern void winstation_init(void); extern void sysparams_init(void); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index 9b9ea935a48..edef603308e 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -71,6 +71,7 @@ struct session_block
static pthread_mutex_t session_lock = PTHREAD_MUTEX_INITIALIZER; static struct list session_blocks = LIST_INIT(session_blocks); +const session_shm_t *shared_session;
static struct session_thread_data *get_session_thread_data(void) { @@ -195,6 +196,17 @@ static const shared_object_t *find_shared_session_object( struct obj_locator loc return NULL; }
+void shared_session_init(void) +{ + struct session_block *block; + UINT status; + + if ((status = find_shared_session_block( 0, sizeof(*shared_session), &block ))) + ERR( "Failed to map initial shared session block, status %#x\n", status ); + else + shared_session = (const session_shm_t *)block->data; +} + NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm ) { struct session_thread_data *data = get_session_thread_data(); diff --git a/server/file.h b/server/file.h index 8fc82a460ff..4510a8b4e88 100644 --- a/server/file.h +++ b/server/file.h @@ -193,6 +193,7 @@ extern struct mapping *create_session_mapping( struct object *root, const struct unsigned int attr, const struct security_descriptor *sd ); extern void set_session_mapping( struct mapping *mapping );
+extern session_shm_t *shared_session; extern volatile void *alloc_shared_object(void); extern void free_shared_object( volatile void *object_shm ); extern void invalidate_shared_object( volatile void *object_shm ); diff --git a/server/mapping.c b/server/mapping.c index a74573efe0e..83538831ea2 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -249,6 +249,7 @@ struct session object_id_t last_object_id; };
+session_shm_t *shared_session; static struct mapping *session_mapping; static struct session session = { @@ -1303,7 +1304,7 @@ struct mapping *create_session_mapping( struct object *root, const struct unicod unsigned int attr, const struct security_descriptor *sd ) { static const unsigned int access = FILE_READ_DATA | FILE_WRITE_DATA; - size_t size = max( sizeof(shared_object_t) * 512, 0x10000 ); + size_t size = max( sizeof(*shared_session) + sizeof(object_shm_t) * 512, 0x10000 );
size = round_size( size, host_page_mask ); return create_mapping( root, name, attr, size, SEC_COMMIT, 0, access, sd ); @@ -1325,9 +1326,10 @@ void set_session_mapping( struct mapping *mapping )
block->data = tmp; block->offset = 0; - block->used_size = 0; + block->used_size = sizeof(*shared_session); block->block_size = size;
+ shared_session = tmp; session_mapping = mapping; list_add_tail( &session.blocks, &block->entry ); } diff --git a/server/protocol.def b/server/protocol.def index 8ff35b6e401..e4c2694d606 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1023,6 +1023,11 @@ typedef volatile struct object_shm_t shm; /* object shared data */ } shared_object_t;
+typedef volatile struct +{ + unsigned __int64 placeholder; +} session_shm_t; + struct obj_locator { object_id_t id; /* object unique id, object data is valid if != 0 */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index cccf14bed20..5143093b381 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -77,6 +77,20 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned short type ) return handle; }
+static BOOL is_valid_entry_uniq( HANDLE handle, unsigned short type, UINT64 uniq ) +{ + if (!HIWORD(handle) || HIWORD(handle) == 0xffff) return LOWORD(uniq) == type; + return uniq == MAKELONG(type, HIWORD(handle)); +} + +static BOOL is_valid_entry( HANDLE handle, unsigned short type ) +{ + const volatile struct user_entry *entries = shared_session->user_entries; + WORD index = USER_HANDLE_TO_INDEX( handle ); + if (index >= MAX_USER_HANDLES) return FALSE; + return is_valid_entry_uniq( handle, type, ReadAcquire64( (LONG64 *)&entries[index].uniq ) ); +} + /*********************************************************************** * get_user_handle_ptr */ @@ -290,26 +304,13 @@ HWND is_current_process_window( HWND hwnd ) /* see IsWindow */ BOOL is_window( HWND hwnd ) { - WND *win; - BOOL ret; - - if (!(win = get_win_ptr( hwnd ))) return FALSE; - if (win == WND_DESKTOP) return TRUE; - - if (win != WND_OTHER_PROCESS) - { - release_win_ptr( win ); - return TRUE; - } - - /* check other processes */ - SERVER_START_REQ( get_window_info ) + if (!hwnd) return FALSE; + if (!is_valid_entry( hwnd, NTUSER_OBJ_WINDOW )) { - req->handle = wine_server_user_handle( hwnd ); - ret = !wine_server_call_err( req ); + RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); + return FALSE; } - SERVER_END_REQ; - return ret; + return TRUE; }
/* see GetWindowThreadProcessId */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 11 ++- include/ntuser.h | 19 ++++++ server/protocol.def | 2 +- server/user.c | 155 +++++++++++++++++++++++++------------------ server/user.h | 2 - 5 files changed, 116 insertions(+), 73 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 81396fb06d0..cccf14bed20 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -34,10 +34,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
-#define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1) #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
-static void *user_handles[NB_USER_HANDLES]; +static void *user_handles[MAX_USER_HANDLES];
#define SWP_AGG_NOGEOMETRYCHANGE \ (SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOZORDER) @@ -70,7 +69,7 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned short type ) { UINT index = USER_HANDLE_TO_INDEX( handle );
- assert( index < NB_USER_HANDLES ); + assert( index < MAX_USER_HANDLES ); ptr->handle = handle; ptr->type = type; InterlockedExchangePointer( &user_handles[index], ptr ); @@ -86,7 +85,7 @@ void *get_user_handle_ptr( HANDLE handle, unsigned short type ) struct user_object *ptr; WORD index = USER_HANDLE_TO_INDEX( handle );
- if (index >= NB_USER_HANDLES) return NULL; + if (index >= MAX_USER_HANDLES) return NULL;
user_lock(); if ((ptr = user_handles[index])) @@ -112,7 +111,7 @@ void *next_process_user_handle_ptr( HANDLE *handle, unsigned short type ) struct user_object *ptr; WORD index = *handle ? USER_HANDLE_TO_INDEX( *handle ) + 1 : 0;
- while (index < NB_USER_HANDLES) + while (index < MAX_USER_HANDLES) { if (!(ptr = user_handles[index++])) continue; /* OBJ_OTHER_PROCESS */ if (ptr->type != type) continue; @@ -128,7 +127,7 @@ void *next_process_user_handle_ptr( HANDLE *handle, unsigned short type ) static void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) { WORD index = USER_HANDLE_TO_INDEX(handle); - assert( index < NB_USER_HANDLES ); + assert( index < MAX_USER_HANDLES ); InterlockedExchangePointer( &user_handles[index], ptr ); }
diff --git a/include/ntuser.h b/include/ntuser.h index 9922c1da4b2..0647efe7082 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -46,6 +46,25 @@ typedef enum MONITOR_DPI_TYPE typedef NTSTATUS (WINAPI *ntuser_callback)( void *args, ULONG len ); NTSYSAPI NTSTATUS KeUserModeCallback( ULONG id, const void *args, ULONG len, void **ret_ptr, ULONG *ret_len );
+struct user_entry +{ + ULONG64 offset; /* shared user object offset */ + ULONG tid; /* owner thread id */ + ULONG pid; /* owner process id */ + ULONG64 padding; + union + { + struct + { + USHORT type; /* object type (0 if free) */ + USHORT generation; /* generation counter */ + }; + LONG64 uniq; + }; +}; + +#define MAX_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1) + /* KernelCallbackTable codes, not compatible with Windows. All of these functions must live inside user32.dll. Overwatch 2's KiUserCallbackDispatcher hook verifies this and prevents the callback from diff --git a/server/protocol.def b/server/protocol.def index e4c2694d606..5de40b1fc1d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1025,7 +1025,7 @@ typedef volatile struct
typedef volatile struct { - unsigned __int64 placeholder; + struct user_entry user_entries[MAX_USER_HANDLES]; } session_shm_t;
struct obj_locator diff --git a/server/user.c b/server/user.c index 22d72c669e7..2f7970e95b6 100644 --- a/server/user.c +++ b/server/user.c @@ -18,101 +18,122 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" + #include "thread.h" +#include "file.h" #include "user.h" +#include "file.h" +#include "process.h" #include "request.h"
-struct user_handle -{ - void *ptr; /* pointer to object */ - unsigned short type; /* object type (0 if free) */ - unsigned short generation; /* generation counter */ -}; +typedef volatile struct user_entry user_entry_t;
-static struct user_handle *handles; -static struct user_handle *freelist; +static void *server_objects[MAX_USER_HANDLES]; +static mem_size_t freelist = -1; static int nb_handles; -static int allocated_handles;
-static struct user_handle *handle_to_entry( user_handle_t handle ) +static void *get_server_object( user_entry_t *entry ) { - unsigned short generation; - int index = ((handle & 0xffff) - FIRST_USER_HANDLE) >> 1; + user_entry_t *handles = shared_session->user_entries; + return server_objects[entry - handles]; +} + +static void *set_server_object( user_entry_t *entry, void *ptr ) +{ + user_entry_t *handles = shared_session->user_entries; + void *prev = server_objects[entry - handles]; + server_objects[entry - handles] = ptr; + return prev; +} + +static user_entry_t *handle_to_entry( user_handle_t handle ) +{ + user_entry_t *entry, *handles = shared_session->user_entries; + unsigned short generation = handle >> 16; + int index; + + index = ((handle & 0xffff) - FIRST_USER_HANDLE) >> 1; if (index < 0 || index >= nb_handles) return NULL; - if (!handles[index].type) return NULL; - generation = handle >> 16; - if (generation == handles[index].generation || !generation || generation == 0xffff) - return &handles[index]; + entry = handles + index; + + if (!entry->type) return NULL; + if (!generation || generation == 0xffff) return entry; + if (generation == entry->generation) return entry; return NULL; }
-static inline user_handle_t entry_to_handle( struct user_handle *ptr ) +static user_handle_t entry_to_handle( user_entry_t *entry ) { - unsigned int index = ptr - handles; - return (index << 1) + FIRST_USER_HANDLE + (ptr->generation << 16); + user_entry_t *handles = shared_session->user_entries; + unsigned int index = entry - handles; + return (index << 1) + FIRST_USER_HANDLE + (entry->generation << 16); }
-static inline struct user_handle *alloc_user_entry(void) +static user_entry_t *alloc_user_entry( unsigned short type ) { - struct user_handle *handle; + user_entry_t *entry, *handles = shared_session->user_entries; + unsigned short generation;
- if (freelist) + if (freelist != -1) { - handle = freelist; - freelist = handle->ptr; - return handle; + entry = handles + freelist; + generation = entry->generation + 1; + freelist = entry->offset; } - if (nb_handles >= allocated_handles) /* need to grow the array */ + else { - struct user_handle *new_handles; - /* grow array by 50% (but at minimum 32 entries) */ - int growth = max( 32, allocated_handles / 2 ); - int new_size = min( allocated_handles + growth, MAX_USER_HANDLES ); - if (new_size <= allocated_handles) return NULL; - if (!(new_handles = realloc( handles, new_size * sizeof(*handles) ))) - return NULL; - handles = new_handles; - allocated_handles = new_size; + entry = handles + nb_handles; + generation = 1; + nb_handles++; } - handle = &handles[nb_handles++]; - handle->generation = 0; - return handle; + + if (generation == 0 || generation == 0xffff) generation = 1; + + entry->offset = -1; + entry->tid = get_thread_id( current ); + entry->pid = get_process_id( current->process ); + entry->padding = -1; + WriteRelease64( &entry->uniq, MAKELONG(type, generation) ); + return entry; }
-static inline void *free_user_entry( struct user_handle *ptr ) +static void free_user_entry( user_entry_t *entry ) { - void *ret; - ret = ptr->ptr; - ptr->ptr = freelist; - ptr->type = 0; - freelist = ptr; - return ret; + user_entry_t *handles = shared_session->user_entries; + size_t index = entry - handles; + + WriteRelease64( &entry->uniq, MAKELONG(0, entry->generation) ); + entry->offset = freelist; + freelist = index; }
/* allocate a user handle for a given object */ user_handle_t alloc_user_handle( void *ptr, unsigned short type ) { - struct user_handle *entry = alloc_user_entry(); - if (!entry) return 0; - entry->ptr = ptr; - entry->type = type; - if (++entry->generation >= 0xffff) entry->generation = 1; + user_entry_t *entry; + + if (!(entry = alloc_user_entry( type ))) return 0; + set_server_object( entry, ptr ); return entry_to_handle( entry ); }
/* return a pointer to a user object from its handle */ void *get_user_object( user_handle_t handle, unsigned short type ) { - struct user_handle *entry; + user_entry_t *entry;
if (!(entry = handle_to_entry( handle )) || entry->type != type) return NULL; - return entry->ptr; + return get_server_object( entry ); }
/* get the full handle for a possibly truncated handle */ user_handle_t get_user_full_handle( user_handle_t handle ) { - struct user_handle *entry; + user_entry_t *entry;
if (handle >> 16) return handle; if (!(entry = handle_to_entry( handle ))) return handle; @@ -122,30 +143,34 @@ user_handle_t get_user_full_handle( user_handle_t handle ) /* same as get_user_object plus set the handle to the full 32-bit value */ void *get_user_object_handle( user_handle_t *handle, unsigned short type ) { - struct user_handle *entry; + user_entry_t *entry;
if (!(entry = handle_to_entry( *handle )) || entry->type != type) return NULL; *handle = entry_to_handle( entry ); - return entry->ptr; + return get_server_object( entry ); }
/* free a user handle and return a pointer to the object */ void *free_user_handle( user_handle_t handle ) { - struct user_handle *entry; + user_entry_t *entry; + void *ret;
if (!(entry = handle_to_entry( handle ))) { set_error( STATUS_INVALID_HANDLE ); return NULL; } - return free_user_entry( entry ); + + ret = set_server_object( entry, NULL ); + free_user_entry( entry ); + return ret; }
/* return the next user handle after 'handle' that is of a given type */ void *next_user_handle( user_handle_t *handle, unsigned short type ) { - struct user_handle *entry; + user_entry_t *entry, *handles = shared_session->user_entries;
if (!*handle) entry = handles; else @@ -159,7 +184,7 @@ void *next_user_handle( user_handle_t *handle, unsigned short type ) if (!type || entry->type == type) { *handle = entry_to_handle( entry ); - return entry->ptr; + return get_server_object( entry ); } entry++; } @@ -169,18 +194,20 @@ void *next_user_handle( user_handle_t *handle, unsigned short type ) /* free client-side user handles managed by the process */ void free_process_user_handles( struct process *process ) { - unsigned int i; + user_entry_t *handles = shared_session->user_entries; + unsigned int i, pid = get_process_id( process );
for (i = 0; i < nb_handles; i++) { - switch (handles[i].type) + user_entry_t *entry = handles + i; + switch (entry->type) { case NTUSER_OBJ_MENU: case NTUSER_OBJ_ICON: case NTUSER_OBJ_WINPOS: case NTUSER_OBJ_ACCEL: case NTUSER_OBJ_IMC: - if (handles[i].ptr == process) free_user_entry( &handles[i] ); + if (entry->pid == pid) free_user_entry( entry ); break; case NTUSER_OBJ_HOOK: case NTUSER_OBJ_WINDOW: @@ -193,14 +220,14 @@ void free_process_user_handles( struct process *process ) /* allocate an arbitrary user handle */ DECL_HANDLER(alloc_user_handle) { - reply->handle = alloc_user_handle( current->process, req->type ); + reply->handle = alloc_user_handle( (void *)-1 /* never used */, req->type ); }
/* free an arbitrary user handle */ DECL_HANDLER(free_user_handle) { - struct user_handle *entry; + user_entry_t *entry;
if ((entry = handle_to_entry( req->handle )) && entry->type == req->type) free_user_entry( entry ); diff --git a/server/user.h b/server/user.h index 23c2c338210..50b275e4eb2 100644 --- a/server/user.h +++ b/server/user.h @@ -36,8 +36,6 @@ struct clipboard;
#define DESKTOP_ATOM ((atom_t)32769)
-#define MAX_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1) - struct winstation { struct object obj; /* object header */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/win32u_private.h | 7 ++++ dlls/win32u/window.c | 74 ++++++++++++++++++++++++++---------- dlls/win32u/winstation.c | 7 ---- 3 files changed, 60 insertions(+), 28 deletions(-)
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 19c666928a8..a7bee5bd93a 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -212,6 +212,13 @@ struct object_lock }; #define OBJECT_LOCK_INIT {0}
+#if defined(__i386__) || defined(__x86_64__) +/* this prevents compilers from incorrectly reordering non-volatile reads (e.g., memcpy) from shared memory */ +#define __SHARED_READ_FENCE do { __asm__ __volatile__( "" ::: "memory" ); } while (0) +#else +#define __SHARED_READ_FENCE __atomic_thread_fence( __ATOMIC_ACQUIRE ) +#endif + /* Get shared session object's data pointer, must be called in a loop while STATUS_PENDING * is returned, lock must be initialized with OBJECT_LOCK_INIT. * diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 5143093b381..9611e855ff8 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -35,8 +35,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
#define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1) +#define USER_HANDLE_FROM_INDEX(index, generation) UlongToHandle( (index << 1) + FIRST_USER_HANDLE + (generation << 16) )
-static void *user_handles[MAX_USER_HANDLES]; +static void *client_objects[MAX_USER_HANDLES];
#define SWP_AGG_NOGEOMETRYCHANGE \ (SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOZORDER) @@ -72,7 +73,7 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned short type ) assert( index < MAX_USER_HANDLES ); ptr->handle = handle; ptr->type = type; - InterlockedExchangePointer( &user_handles[index], ptr ); + InterlockedExchangePointer( &client_objects[index], ptr ); } return handle; } @@ -91,27 +92,57 @@ static BOOL is_valid_entry( HANDLE handle, unsigned short type ) return is_valid_entry_uniq( handle, type, ReadAcquire64( (LONG64 *)&entries[index].uniq ) ); }
+static BOOL read_acquire_user_entry( HANDLE handle, unsigned short type, const volatile struct user_entry *src, struct user_entry *dst ) +{ + UINT64 uniq = ReadAcquire64( (LONG64 *)&src->uniq ); + if (!is_valid_entry_uniq( handle, type, uniq )) return FALSE; + dst->offset = src->offset; + dst->tid = src->tid; + dst->pid = src->pid; + dst->padding = src->padding; + __SHARED_READ_FENCE; + dst->uniq = ReadNoFence64( &src->uniq ); + return dst->uniq == uniq; +} + +static BOOL get_user_entry( HANDLE handle, unsigned short type, struct user_entry *entry, HANDLE *full ) +{ + const volatile struct user_entry *entries = shared_session->user_entries; + WORD index = USER_HANDLE_TO_INDEX( handle ); + + if (index >= MAX_USER_HANDLES) return FALSE; + if (!read_acquire_user_entry( handle, type, entries + index, entry )) return FALSE; + *full = USER_HANDLE_FROM_INDEX( index, entry->generation ); + return TRUE; +} + +static BOOL get_user_entry_at( WORD index, unsigned short type, struct user_entry *entry, HANDLE *full ) +{ + const volatile struct user_entry *entries = shared_session->user_entries; + if (index >= MAX_USER_HANDLES) return FALSE; + if (!read_acquire_user_entry( 0, type, entries + index, entry )) return FALSE; + *full = USER_HANDLE_FROM_INDEX( index, entry->generation ); + return TRUE; +} + /*********************************************************************** * get_user_handle_ptr */ void *get_user_handle_ptr( HANDLE handle, unsigned short type ) { - struct user_object *ptr; WORD index = USER_HANDLE_TO_INDEX( handle ); + struct user_object *ptr = NULL; + struct user_entry entry;
if (index >= MAX_USER_HANDLES) return NULL;
user_lock(); - if ((ptr = user_handles[index])) - { - if (ptr->type == type && - ((UINT)(UINT_PTR)ptr->handle == (UINT)(UINT_PTR)handle || - !HIWORD(handle) || HIWORD(handle) == 0xffff)) - return ptr; - ptr = NULL; - } - else ptr = OBJ_OTHER_PROCESS; - user_unlock(); + + if (!get_user_entry( handle, type, &entry, &handle )) ptr = NULL; + else if (entry.pid != GetCurrentProcessId()) ptr = OBJ_OTHER_PROCESS; + else ptr = client_objects[index]; + + if (!ptr || ptr == OBJ_OTHER_PROCESS) user_unlock(); return ptr; }
@@ -122,16 +153,17 @@ void *get_user_handle_ptr( HANDLE handle, unsigned short type ) */ void *next_process_user_handle_ptr( HANDLE *handle, unsigned short type ) { - struct user_object *ptr; WORD index = *handle ? USER_HANDLE_TO_INDEX( *handle ) + 1 : 0; + struct user_entry entry; + UINT i;
- while (index < MAX_USER_HANDLES) + for (i = index; i < MAX_USER_HANDLES; i++) { - if (!(ptr = user_handles[index++])) continue; /* OBJ_OTHER_PROCESS */ - if (ptr->type != type) continue; - *handle = ptr->handle; - return ptr; + if (!get_user_entry_at( i, type, &entry, handle )) continue; + if (entry.pid != GetCurrentProcessId()) continue; + return client_objects[i]; } + return NULL; }
@@ -142,7 +174,7 @@ static void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) { WORD index = USER_HANDLE_TO_INDEX(handle); assert( index < MAX_USER_HANDLES ); - InterlockedExchangePointer( &user_handles[index], ptr ); + InterlockedExchangePointer( &client_objects[index], ptr ); }
/*********************************************************************** @@ -169,7 +201,7 @@ void *free_user_handle( HANDLE handle, unsigned short type ) req->type = type; req->handle = wine_server_user_handle( handle ); if (wine_server_call( req )) ptr = NULL; - else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr ); + else InterlockedCompareExchangePointer( &client_objects[index], NULL, ptr ); } SERVER_END_REQ; user_unlock(); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index edef603308e..766043ce282 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -80,13 +80,6 @@ static struct session_thread_data *get_session_thread_data(void) return thread_info->session_data; }
-#if defined(__i386__) || defined(__x86_64__) -/* this prevents compilers from incorrectly reordering non-volatile reads (e.g., memcpy) from shared memory */ -#define __SHARED_READ_FENCE do { __asm__ __volatile__( "" ::: "memory" ); } while (0) -#else -#define __SHARED_READ_FENCE __atomic_thread_fence( __ATOMIC_ACQUIRE ) -#endif - static void shared_object_acquire_seqlock( const shared_object_t *object, UINT64 *seq ) { while ((*seq = ReadNoFence64( &object->seq )) & 1) YieldProcessor();
v6: Remove const qualifier from server shared memory pointers.
Tests failures don't seem related, `d3d10core:d3d10core` has been randomly crashing since 11/04, `ole32:marshal` broke from https://gitlab.winehq.org/wine/wine/-/merge_requests/7868, `user32:winstation` failure is a flaky failure from the recent window activation changes.
Jacek Caban (@jacek) commented about server/user.c:
- if (!entry) return 0;
- entry->ptr = ptr;
- entry->type = type;
- if (++entry->generation >= 0xffff) entry->generation = 1;
- user_entry_t *entry;
- if (!(entry = alloc_user_entry( type ))) return 0;
- set_server_object( entry, ptr ); return entry_to_handle( entry );
}
/* return a pointer to a user object from its handle */ void *get_user_object( user_handle_t handle, unsigned short type ) {
- struct user_handle *entry;
- user_entry_t *entry;
You could still keep const here and in similar places.
Please move the new commit out of this MR. I'm not sure about it and, more importantly, it's unrelated and this MR is complex enough on its own.