From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 84 +++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 25 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 3c3161acdd1..19fcfc09b77 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 *client_objects[MAX_USER_HANDLES];
#define SWP_AGG_NOGEOMETRYCHANGE \ (SWP_NOSIZE | SWP_NOCLIENTSIZE | SWP_NOZORDER) @@ -52,6 +51,12 @@ static void *user_handles[NB_USER_HANDLES]; #define PLACE_MAX 0x0002 #define PLACE_RECT 0x0004
+static HANDLE entry_to_handle( const session_shm_t *session, const user_entry_t *entry ) +{ + unsigned int index = entry - session->user_entries; + return UlongToHandle( (index << 1) + FIRST_USER_HANDLE + (entry->generation << 16) ); +} + /*********************************************************************** * alloc_user_handle */ @@ -70,35 +75,53 @@ 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 ); + InterlockedExchangePointer( &client_objects[index], ptr ); } return handle; }
+/* must be called within a session_shm read loop */ +static const user_entry_t *get_session_entry( const session_shm_t *session_shm, HANDLE handle, unsigned short type ) +{ + const user_entry_t *entry, *begin = session_shm->user_entries, *end = begin + session_shm->user_entry_count; + unsigned short index = USER_HANDLE_TO_INDEX( handle ); + + entry = session_shm->user_entries + index; + if (entry < begin || entry >= end || entry->type != type) return NULL; + if (!entry->generation || entry->generation == 0xffff) return NULL; + if (entry_to_handle( session_shm, entry ) != handle) return NULL; + + return entry; +} + /*********************************************************************** * get_user_handle_ptr */ void *get_user_handle_ptr( HANDLE handle, unsigned short type ) { - struct user_object *ptr; + UINT status, pid = GetCurrentProcessId(), tid = GetCurrentThreadId(); WORD index = USER_HANDLE_TO_INDEX( handle ); + struct object_lock lock = OBJECT_LOCK_INIT; + const session_shm_t *session_shm; + struct user_object *ptr = NULL;
- if (index >= NB_USER_HANDLES) return NULL; + if (index >= MAX_USER_HANDLES) return NULL;
user_lock(); - if ((ptr = user_handles[index])) + + while ((status = get_shared_session( &lock, &session_shm )) == STATUS_PENDING) { - if (ptr->type == type && - ((UINT)(UINT_PTR)ptr->handle == (UINT)(UINT_PTR)handle || - !HIWORD(handle) || HIWORD(handle) == 0xffff)) - return ptr; - ptr = NULL; + const user_entry_t *entry; + if (!(entry = get_session_entry( session_shm, handle, type ))) ptr = NULL; + else if (entry->pid != pid || entry->tid != tid) ptr = OBJ_OTHER_PROCESS; + else ptr = client_objects[entry - session_shm->user_entries]; } - else ptr = OBJ_OTHER_PROCESS; - user_unlock(); + if (status) ptr = NULL; + + if (!ptr || ptr == OBJ_OTHER_PROCESS) user_unlock(); return ptr; }
@@ -109,17 +132,29 @@ 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; + struct user_object *ptr = NULL; + UINT status, pid = GetCurrentProcessId(), tid = GetCurrentThreadId(), i; WORD index = *handle ? USER_HANDLE_TO_INDEX( *handle ) + 1 : 0; + struct object_lock lock = OBJECT_LOCK_INIT; + const session_shm_t *session_shm; + HANDLE next = NULL;
- while (index < NB_USER_HANDLES) + while ((status = get_shared_session( &lock, &session_shm )) == STATUS_PENDING) { - if (!(ptr = user_handles[index++])) continue; /* OBJ_OTHER_PROCESS */ - if (ptr->type != type) continue; - *handle = ptr->handle; - return ptr; + const user_entry_t *entry = session_shm->user_entries; + + for (i = index, ptr = NULL; i < session_shm->user_entry_count; i++) + { + if (entry->pid != pid || entry->tid != tid || entry->type != type) continue; + ptr = client_objects[entry - session_shm->user_entries]; + next = entry_to_handle( session_shm, entry ); + break; + } } - return NULL; + if (status) next = ptr = NULL; + + *handle = next; + return ptr; }
/*********************************************************************** @@ -128,8 +163,8 @@ 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 ); - InterlockedExchangePointer( &user_handles[index], ptr ); + assert( index < MAX_USER_HANDLES ); + InterlockedExchangePointer( &client_objects[index], ptr ); }
/*********************************************************************** @@ -147,7 +182,6 @@ void release_user_handle_ptr( void *ptr ) void *free_user_handle( HANDLE handle, unsigned short type ) { struct user_object *ptr; - WORD index = USER_HANDLE_TO_INDEX( handle );
if ((ptr = get_user_handle_ptr( handle, type )) && ptr != OBJ_OTHER_PROCESS) { @@ -156,7 +190,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 set_user_handle_ptr( handle, NULL ); } SERVER_END_REQ; user_unlock();