Alexandre Julliard : user32: Use a simplified sequence to destroy windows at thread exit, since we don' t want to send messages.

Alexandre Julliard julliard at winehq.org
Wed Jun 3 09:31:14 CDT 2009


Module: wine
Branch: master
Commit: 95f8371a16dc2cb9754122abca56ea628a4bed7b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=95f8371a16dc2cb9754122abca56ea628a4bed7b

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jun  3 11:30:29 2009 +0200

user32: Use a simplified sequence to destroy windows at thread exit, since we don't want to send messages.

---

 dlls/user32/win.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 7e599ba..da196ed 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -712,6 +712,75 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
     return 0;
 }
 
+
+/***********************************************************************
+ *		destroy_thread_window
+ *
+ * Destroy a window upon exit of its thread.
+ */
+static void destroy_thread_window( HWND hwnd )
+{
+    WND *wndPtr;
+    HWND *list;
+    HMENU menu = 0, sys_menu = 0;
+    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 */
+
+    index = USER_HANDLE_TO_INDEX(hwnd);
+    if (index >= NB_USER_HANDLES) return;
+    USER_Lock();
+    if ((wndPtr = user_handles[index]))
+    {
+        if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) menu = (HMENU)wndPtr->wIDmenu;
+        sys_menu = wndPtr->hSysMenu;
+        free_dce( wndPtr->dce, hwnd );
+        user_handles[index] = NULL;
+        wndPtr->dwMagic = 0;
+    }
+    USER_Unlock();
+
+    HeapFree( GetProcessHeap(), 0, wndPtr );
+    if (menu) DestroyMenu( menu );
+    if (sys_menu) DestroyMenu( sys_menu );
+}
+
+
+/***********************************************************************
+ *		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
  *
@@ -723,13 +792,18 @@ void WIN_DestroyThreadWindows( HWND hwnd )
     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] ))
-            DestroyWindow( list[i] );
-        else
-            WIN_DestroyThreadWindows( list[i] );
+        if (!WIN_IsCurrentThread( list[i] ))
+        {
+            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 );
 }
 




More information about the wine-cvs mailing list