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@winehq.org>
This commit is contained in:
parent
c102efbc35
commit
460b4e7adf
|
@ -374,8 +374,7 @@ static void thread_detach(void)
|
||||||
WDML_NotifyThreadDetach();
|
WDML_NotifyThreadDetach();
|
||||||
USER_Driver->pThreadDetach();
|
USER_Driver->pThreadDetach();
|
||||||
|
|
||||||
if (thread_info->top_window) WIN_DestroyThreadWindows( thread_info->top_window );
|
destroy_thread_windows();
|
||||||
if (thread_info->msg_window) WIN_DestroyThreadWindows( thread_info->msg_window );
|
|
||||||
CloseHandle( thread_info->server_queue );
|
CloseHandle( thread_info->server_queue );
|
||||||
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
|
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
|
||||||
HeapFree( GetProcessHeap(), 0, thread_info->key_state );
|
HeapFree( GetProcessHeap(), 0, thread_info->key_state );
|
||||||
|
|
|
@ -287,8 +287,8 @@ static void free_window_handle( HWND hwnd )
|
||||||
SERVER_START_REQ( destroy_window )
|
SERVER_START_REQ( destroy_window )
|
||||||
{
|
{
|
||||||
req->handle = wine_server_user_handle( hwnd );
|
req->handle = wine_server_user_handle( hwnd );
|
||||||
if (wine_server_call_err( req )) ptr = NULL;
|
wine_server_call( req );
|
||||||
else InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
|
InterlockedCompareExchangePointer( &user_handles[index], NULL, ptr );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
USER_Unlock();
|
USER_Unlock();
|
||||||
|
@ -1027,47 +1027,53 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* destroy_thread_window
|
* next_thread_window
|
||||||
*
|
|
||||||
* Destroy a window upon exit of its thread.
|
|
||||||
*/
|
*/
|
||||||
static void destroy_thread_window( HWND hwnd )
|
static WND *next_thread_window( HWND *hwnd )
|
||||||
|
{
|
||||||
|
struct user_object *ptr;
|
||||||
|
WND *win;
|
||||||
|
WORD index = *hwnd ? USER_HANDLE_TO_INDEX( *hwnd ) + 1 : 0;
|
||||||
|
|
||||||
|
USER_Lock();
|
||||||
|
while (index < NB_USER_HANDLES)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* destroy_thread_windows
|
||||||
|
*
|
||||||
|
* Destroy all window owned by the current thread.
|
||||||
|
*/
|
||||||
|
void destroy_thread_windows(void)
|
||||||
{
|
{
|
||||||
WND *wndPtr;
|
WND *wndPtr;
|
||||||
HWND *list;
|
HWND hwnd = 0, *list;
|
||||||
HMENU menu = 0, sys_menu = 0;
|
HMENU menu, sys_menu;
|
||||||
struct window_surface *surface = NULL;
|
struct window_surface *surface;
|
||||||
WORD index;
|
|
||||||
|
|
||||||
/* free child windows */
|
|
||||||
|
|
||||||
if ((list = WIN_ListChildren( hwnd )))
|
|
||||||
{
|
|
||||||
int i;
|
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while ((wndPtr = next_thread_window( &hwnd )))
|
||||||
|
{
|
||||||
/* destroy the client-side storage */
|
/* destroy the client-side storage */
|
||||||
|
|
||||||
index = USER_HANDLE_TO_INDEX(hwnd);
|
list = WIN_ListChildren( hwnd );
|
||||||
if (index >= NB_USER_HANDLES) return;
|
menu = ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) ? (HMENU)wndPtr->wIDmenu : 0;
|
||||||
USER_Lock();
|
|
||||||
if ((wndPtr = user_handles[index]))
|
|
||||||
{
|
|
||||||
if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
|
|
||||||
sys_menu = wndPtr->hSysMenu;
|
sys_menu = wndPtr->hSysMenu;
|
||||||
free_dce( wndPtr->dce, hwnd );
|
free_dce( wndPtr->dce, hwnd );
|
||||||
surface = wndPtr->surface;
|
surface = wndPtr->surface;
|
||||||
wndPtr->surface = NULL;
|
InterlockedCompareExchangePointer( &user_handles[USER_HANDLE_TO_INDEX(hwnd)], NULL, wndPtr );
|
||||||
InterlockedCompareExchangePointer( &user_handles[index], NULL, wndPtr );
|
WIN_ReleasePtr( wndPtr );
|
||||||
}
|
|
||||||
USER_Unlock();
|
|
||||||
|
|
||||||
HeapFree( GetProcessHeap(), 0, wndPtr );
|
HeapFree( GetProcessHeap(), 0, wndPtr );
|
||||||
if (menu) DestroyMenu( menu );
|
if (menu) DestroyMenu( menu );
|
||||||
if (sys_menu) DestroyMenu( sys_menu );
|
if (sys_menu) DestroyMenu( sys_menu );
|
||||||
|
@ -1076,55 +1082,15 @@ static void destroy_thread_window( HWND hwnd )
|
||||||
register_window_surface( surface, NULL );
|
register_window_surface( surface, NULL );
|
||||||
window_surface_release( surface );
|
window_surface_release( surface );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/* free child windows */
|
||||||
|
|
||||||
/***********************************************************************
|
if (!list) continue;
|
||||||
* destroy_thread_child_windows
|
|
||||||
*
|
|
||||||
* Destroy child windows upon exit of its thread.
|
|
||||||
*/
|
|
||||||
static void destroy_thread_child_windows( HWND hwnd )
|
|
||||||
{
|
|
||||||
HWND *list;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (WIN_IsCurrentThread( hwnd ))
|
|
||||||
{
|
|
||||||
destroy_thread_window( hwnd );
|
|
||||||
}
|
|
||||||
else if ((list = WIN_ListChildren( hwnd )))
|
|
||||||
{
|
|
||||||
for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
|
|
||||||
HeapFree( GetProcessHeap(), 0, list );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* 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++)
|
for (i = 0; list[i]; i++)
|
||||||
{
|
|
||||||
if (!WIN_IsCurrentThread( list[i] ))
|
if (!WIN_IsCurrentThread( list[i] ))
|
||||||
{
|
SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
|
||||||
HWND owner = GetWindow( list[i], GW_OWNER );
|
|
||||||
if (owner && WIN_IsCurrentThread( owner )) WIN_SetOwner( list[i], 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; list[i]; i++) destroy_thread_child_windows( list[i] );
|
|
||||||
HeapFree( GetProcessHeap(), 0, list );
|
HeapFree( GetProcessHeap(), 0, list );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 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 void map_window_region( HWND from, HWND to, HRGN hrgn ) DECLSPEC_HIDDEN;
|
||||||
extern LRESULT WIN_DestroyWindow( HWND hwnd ) 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 HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
|
||||||
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
|
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
|
||||||
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;
|
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Reference in New Issue