Alexandre Julliard : user32: Destroy thread windows by going through the handle table.
Alexandre Julliard
julliard at winehq.org
Fri Apr 27 13:26:03 CDT 2018
Module: wine
Branch: master
Commit: 460b4e7adfef5280289f34b895e8d953e0d60579
URL: https://source.winehq.org/git/wine.git/?a=commit;h=460b4e7adfef5280289f34b895e8d953e0d60579
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Apr 27 16:23:39 2018 +0200
user32: Destroy thread windows by going through the handle table.
This makes sure we catch child windows that may not have been deleted
yet.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/user32/user_main.c | 3 +-
dlls/user32/win.c | 124 ++++++++++++++++++------------------------------
dlls/user32/win.h | 2 +-
3 files changed, 47 insertions(+), 82 deletions(-)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 418359a..e287150 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -374,8 +374,7 @@ static void thread_detach(void)
WDML_NotifyThreadDetach();
USER_Driver->pThreadDetach();
- if (thread_info->top_window) WIN_DestroyThreadWindows( thread_info->top_window );
- if (thread_info->msg_window) WIN_DestroyThreadWindows( thread_info->msg_window );
+ destroy_thread_windows();
CloseHandle( thread_info->server_queue );
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
HeapFree( GetProcessHeap(), 0, thread_info->key_state );
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 0272566..17a72d2 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -287,8 +287,8 @@ static void free_window_handle( HWND hwnd )
SERVER_START_REQ( destroy_window )
{
req->handle = wine_server_user_handle( hwnd );
- if (wine_server_call_err( req )) ptr = NULL;
- else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
+ wine_server_call( req );
+ InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
}
SERVER_END_REQ;
USER_Unlock();
@@ -1027,104 +1027,70 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
/***********************************************************************
- * destroy_thread_window
- *
- * Destroy a window upon exit of its thread.
+ * next_thread_window
*/
-static void destroy_thread_window( HWND hwnd )
+static WND *next_thread_window( HWND *hwnd )
{
- WND *wndPtr;
- HWND *list;
- HMENU menu = 0, sys_menu = 0;
- struct window_surface *surface = NULL;
- WORD index;
-
- /* free child windows */
-
- if ((list = WIN_ListChildren( hwnd )))
- {
- int i;
- for (i = 0; list[i]; i++)
- {
- if (WIN_IsCurrentThread( list[i] )) destroy_thread_window( list[i] );
- else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
- }
- HeapFree( GetProcessHeap(), 0, list );
- }
-
- /* destroy the client-side storage */
+ struct user_object *ptr;
+ WND *win;
+ WORD index = *hwnd ? USER_HANDLE_TO_INDEX( *hwnd ) + 1 : 0;
- index = USER_HANDLE_TO_INDEX(hwnd);
- if (index >= NB_USER_HANDLES) return;
USER_Lock();
- if ((wndPtr = user_handles[index]))
+ while (index < NB_USER_HANDLES)
{
- if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
- sys_menu = wndPtr->hSysMenu;
- free_dce( wndPtr->dce, hwnd );
- surface = wndPtr->surface;
- wndPtr->surface = NULL;
- InterlockedCompareExchangePointer( &user_handles[index], NULL, wndPtr );
+ if (!(ptr = user_handles[index++])) continue;
+ if (ptr->type != USER_WINDOW) continue;
+ win = (WND *)ptr;
+ if (win->tid != GetCurrentThreadId()) continue;
+ *hwnd = ptr->handle;
+ return win;
}
USER_Unlock();
-
- HeapFree( GetProcessHeap(), 0, wndPtr );
- if (menu) DestroyMenu( menu );
- if (sys_menu) DestroyMenu( sys_menu );
- if (surface)
- {
- register_window_surface( surface, NULL );
- window_surface_release( surface );
- }
+ return NULL;
}
/***********************************************************************
- * destroy_thread_child_windows
+ * destroy_thread_windows
*
- * Destroy child windows upon exit of its thread.
+ * Destroy all window owned by the current thread.
*/
-static void destroy_thread_child_windows( HWND hwnd )
+void destroy_thread_windows(void)
{
- HWND *list;
+ WND *wndPtr;
+ HWND hwnd = 0, *list;
+ HMENU menu, sys_menu;
+ struct window_surface *surface;
int i;
- if (WIN_IsCurrentThread( hwnd ))
- {
- destroy_thread_window( hwnd );
- }
- else if ((list = WIN_ListChildren( hwnd )))
+ while ((wndPtr = next_thread_window( &hwnd )))
{
- for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
- HeapFree( GetProcessHeap(), 0, list );
- }
-}
+ /* destroy the client-side storage */
-
-/***********************************************************************
- * WIN_DestroyThreadWindows
- *
- * Destroy all children of 'wnd' owned by the current thread.
- */
-void WIN_DestroyThreadWindows( HWND hwnd )
-{
- HWND *list;
- int i;
-
- if (!(list = WIN_ListChildren( hwnd ))) return;
-
- /* reset owners of top-level windows */
- for (i = 0; list[i]; i++)
- {
- if (!WIN_IsCurrentThread( list[i] ))
+ list = WIN_ListChildren( hwnd );
+ menu = ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) ? (HMENU)wndPtr->wIDmenu : 0;
+ sys_menu = wndPtr->hSysMenu;
+ free_dce( wndPtr->dce, hwnd );
+ surface = wndPtr->surface;
+ InterlockedCompareExchangePointer( &user_handles[USER_HANDLE_TO_INDEX(hwnd)], NULL, wndPtr );
+ WIN_ReleasePtr( wndPtr );
+ HeapFree( GetProcessHeap(), 0, wndPtr );
+ if (menu) DestroyMenu( menu );
+ if (sys_menu) DestroyMenu( sys_menu );
+ if (surface)
{
- HWND owner = GetWindow( list[i], GW_OWNER );
- if (owner && WIN_IsCurrentThread( owner )) WIN_SetOwner( list[i], 0 );
+ register_window_surface( surface, NULL );
+ window_surface_release( surface );
}
- }
- for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
- HeapFree( GetProcessHeap(), 0, list );
+ /* free child windows */
+
+ if (!list) continue;
+ for (i = 0; list[i]; i++)
+ if (!WIN_IsCurrentThread( list[i] ))
+ SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
+ HeapFree( GetProcessHeap(), 0, list );
+ }
}
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 0c7fcc8..65cb921 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -96,7 +96,7 @@ extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPE
extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN;
extern void map_window_region( HWND from, HWND to, HRGN hrgn ) DECLSPEC_HIDDEN;
extern LRESULT WIN_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN;
-extern void WIN_DestroyThreadWindows( HWND hwnd ) DECLSPEC_HIDDEN;
+extern void destroy_thread_windows(void) DECLSPEC_HIDDEN;
extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;
More information about the wine-cvs
mailing list