From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 84 +++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 24 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 3c3161acdd1..e6b2ab298f9 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,55 @@ 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; + + handle = UlongToHandle( HandleToUlong( handle ) ); + if (entry_to_handle( session_shm, entry ) == handle) return entry; + if (!HIWORD(handle) || HIWORD(handle) == 0xffff) return entry; + + return NULL; +} + /*********************************************************************** * get_user_handle_ptr */ void *get_user_handle_ptr( HANDLE handle, unsigned short type ) { - struct user_object *ptr; + UINT status, pid = GetCurrentProcessId(); 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) 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 +134,28 @@ 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(), 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; + for (i = index, ptr = next = NULL; i < session_shm->user_entry_count; i++) + { + const user_entry_t *entry = session_shm->user_entries + i; + if (entry->pid != pid || entry->type != type) continue; + next = entry_to_handle( session_shm, entry ); + ptr = client_objects[i]; + break; + } } - return NULL; + if (status) next = ptr = NULL; + + *handle = next; + return ptr; }
/*********************************************************************** @@ -128,8 +164,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 ); }
/*********************************************************************** @@ -156,7 +192,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();