So wIDmenu and userdata can be removed from the WND struct and read from shared memory, before the window handle gets destroyed.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index bd70dbff019..70dde9ed27f 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5198,7 +5198,7 @@ BOOL WINAPI NtUserDestroyWindow( HWND hwnd ) */ void destroy_thread_windows(void) { - WND *win, *free_list = NULL; + WND *win, *entry, *free_list = NULL; HANDLE handle = 0;
user_lock(); @@ -5220,25 +5220,25 @@ void destroy_thread_windows(void) } user_unlock();
- while ((win = free_list)) + while ((entry = free_list)) { - free_list = (WND *)win->userdata; - TRACE( "destroying %p\n", win ); + free_list = (WND *)entry->userdata; + TRACE( "destroying %p\n", entry );
- user_driver->pDestroyWindow( win->handle ); - vulkan_detach_surfaces( &win->vulkan_surfaces ); + user_driver->pDestroyWindow( entry->handle ); + vulkan_detach_surfaces( &entry->vulkan_surfaces );
- if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD && win->wIDmenu) - NtUserDestroyMenu( UlongToHandle(win->wIDmenu) ); - if (win->hSysMenu) NtUserDestroyMenu( win->hSysMenu ); - if (win->surface) + if ((entry->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD && entry->wIDmenu) + NtUserDestroyMenu( UlongToHandle(entry->wIDmenu) ); + if (entry->hSysMenu) NtUserDestroyMenu( entry->hSysMenu ); + if (entry->surface) { - register_window_surface( win->surface, NULL ); - window_surface_release( win->surface ); + register_window_surface( entry->surface, NULL ); + window_surface_release( entry->surface ); } - free( win->pScroll ); - free( win->text ); - free( win ); + free( entry->pScroll ); + free( entry->text ); + free( entry ); } }
From: Rémi Bernon rbernon@codeweavers.com
So wIDmenu and userdata can be removed from the WND struct and read from shared memory, before the window handle gets destroyed. --- dlls/win32u/window.c | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 70dde9ed27f..ddb26057b12 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5198,16 +5198,43 @@ BOOL WINAPI NtUserDestroyWindow( HWND hwnd ) */ void destroy_thread_windows(void) { - WND *win, *entry, *free_list = NULL; + struct destroy_entry + { + HWND handle; + HMENU menu; + HMENU sys_menu; + struct list vulkan_surfaces; + struct window_surface *surface; + struct destroy_entry *next; + } *entry, *free_list = NULL; HANDLE handle = 0; + WND *win; + + /* recycle WND structs as destroy_entry structs */ + C_ASSERT( sizeof(struct destroy_entry) <= sizeof(WND) );
user_lock(); while ((win = next_thread_user_object( GetCurrentThreadId(), &handle, NTUSER_OBJ_WINDOW ))) { + BOOL is_child = (win->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD; + struct destroy_entry tmp = {0}; + free_dce( win->dce, win->handle ); set_user_handle_ptr( handle, NULL ); - win->userdata = (UINT_PTR)free_list; - free_list = win; + free( win->pScroll ); + free( win->text ); + + /* recycle the WND struct as a destroy_entry struct */ + entry = (struct destroy_entry *)win; + tmp.handle = win->handle; + tmp.vulkan_surfaces = win->vulkan_surfaces; + if (!is_child) tmp.menu = (HMENU)win->wIDmenu; + tmp.sys_menu = win->hSysMenu; + tmp.surface = win->surface; + *entry = tmp; + + entry->next = free_list; + free_list = entry; } if (free_list) { @@ -5222,22 +5249,19 @@ void destroy_thread_windows(void)
while ((entry = free_list)) { - free_list = (WND *)entry->userdata; + free_list = entry->next; TRACE( "destroying %p\n", entry );
user_driver->pDestroyWindow( entry->handle ); vulkan_detach_surfaces( &entry->vulkan_surfaces );
- if ((entry->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD && entry->wIDmenu) - NtUserDestroyMenu( UlongToHandle(entry->wIDmenu) ); - if (entry->hSysMenu) NtUserDestroyMenu( entry->hSysMenu ); + NtUserDestroyMenu( entry->menu ); + NtUserDestroyMenu( entry->sys_menu ); if (entry->surface) { register_window_surface( entry->surface, NULL ); window_surface_release( entry->surface ); } - free( entry->pScroll ); - free( entry->text ); free( entry ); } }