Index: message.c
===================================================================
--- message.c	(revision 66219)
+++ message.c	(working copy)
@@ -640,6 +640,14 @@
           if (wparam) UserDerefObjectCo(Window);
           return lRes;
        }
+       case WM_ASYNC_DESTROYWINDOW:
+       {
+          ERR("WM_ASYNC_DESTROYWINDOW\n");
+          if (pWnd->style & WS_CHILD)
+             return co_UserFreeWindow(pWnd, PsGetCurrentProcessWin32Process(), PsGetCurrentThreadWin32Thread(), TRUE);
+          else
+             co_UserDestroyWindow(pWnd);
+       }
     }
     return 0;
 }
Index: msgqueue.h
===================================================================
--- msgqueue.h	(revision 66219)
+++ msgqueue.h	(working copy)
@@ -112,7 +112,8 @@
 {
     WM_ASYNC_SHOWWINDOW = 0x80000000,
     WM_ASYNC_SETWINDOWPOS,
-    WM_ASYNC_SETACTIVEWINDOW
+    WM_ASYNC_SETACTIVEWINDOW,
+    WM_ASYNC_DESTROYWINDOW
 };
 
 BOOL FASTCALL MsqIsHung(PTHREADINFO pti);
Index: window.c
===================================================================
--- window.c	(revision 66219)
+++ window.c	(working copy)
@@ -408,32 +408,24 @@
     * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
     * make sure that the window still exists when we come back.
     */
-#if 0 /* FIXME */
 
-   if (IsWindow(Wnd))
+   if (IntIsWindow(hWnd))
    {
       HWND* pWndArray;
       int i;
 
-      if (!(pWndArray = WIN_ListChildren( hwnd )))
-         return;
+      if (!(pWndArray = IntWinListChildren( Window ))) return;
 
-      /* start from the end (FIXME: is this needed?) */
       for (i = 0; pWndArray[i]; i++)
-         ;
-
-      while (--i >= 0)
       {
-         if (IsWindow( pWndArray[i] ))
-            WIN_SendDestroyMsg( pWndArray[i] );
+         if (IntIsWindow( pWndArray[i] )) IntSendDestroyMsg( pWndArray[i] );
       }
-      HeapFree(GetProcessHeap(), 0, pWndArray);
+      ExFreePoolWithTag(pWndArray, USERTAG_WINDOWLIST);
    }
    else
    {
       TRACE("destroyed itself while in WM_DESTROY!\n");
    }
-#endif
 }
 
 static VOID
@@ -471,10 +463,10 @@
  * done in CreateWindow is undone here and not in DestroyWindow:-P
 
  */
-static LRESULT co_UserFreeWindow(PWND Window,
-                                   PPROCESSINFO ProcessData,
-                                   PTHREADINFO ThreadData,
-                                   BOOLEAN SendMessages)
+LRESULT co_UserFreeWindow(PWND Window,
+                          PPROCESSINFO ProcessData,
+                          PTHREADINFO ThreadData,
+                          BOOLEAN SendMessages)
 {
    HWND *Children;
    HWND *ChildHandle;
@@ -504,12 +496,6 @@
 
    IntDeRegisterShellHookWindow(Window->head.h);
 
-   if(SendMessages)
-   {
-      /* Send destroy messages */
-      IntSendDestroyMsg(Window->head.h);
-   }
-
    /* free child windows */
    Children = IntWinListChildren(Window);
    if (Children)
@@ -521,7 +507,7 @@
             if(!IntWndBelongsToThread(Child, ThreadData))
             {
                /* send WM_DESTROY messages to windows not belonging to the same thread */
-               IntSendDestroyMsg(Child->head.h);
+               co_IntSendMessage( UserHMGetHandle(Child), WM_ASYNC_DESTROYWINDOW, 0, 0 );
             }
             else
                co_UserFreeWindow(Child, ProcessData, ThreadData, SendMessages);
@@ -1415,8 +1401,8 @@
    {
       PETHREAD Thread;
       PTHREADINFO W32Thread;
-      PLIST_ENTRY Current;
       PWND Window;
+      HWND *List = NULL;
 
       Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
       if (!NT_SUCCESS(Status))
@@ -1431,35 +1417,42 @@
          return ERROR_INVALID_PARAMETER;
       }
 
-      Current = W32Thread->WindowListHead.Flink;
-      while (Current != &(W32Thread->WindowListHead))
+     // Do not use Thread link list due to co_UserFreeWindow!!!
+     // Current = W32Thread->WindowListHead.Flink;
+     // Fixes Api:CreateWindowEx tests!!!
+      List = IntWinListChildren(UserGetDesktopWindow());
+      if (List)
       {
-         Window = CONTAINING_RECORD(Current, WND, ThreadListEntry);
-         ASSERT(Window);
-
-         if (dwCount < *pBufSize && pWnd)
+         int i;
+         for (i = 0; List[i]; i++)
          {
-            _SEH2_TRY
+            Window = ValidateHwndNoErr(List[i]);
+            if (Window && Window->head.pti == W32Thread)
             {
-               ProbeForWrite(pWnd, sizeof(HWND), 1);
-               *pWnd = Window->head.h;
-               pWnd++;
+               if (dwCount < *pBufSize && pWnd)
+               {
+                  _SEH2_TRY
+                  {
+                     ProbeForWrite(pWnd, sizeof(HWND), 1);
+                     *pWnd = Window->head.h;
+                     pWnd++;
+                  }
+                  _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                  {
+                     Status = _SEH2_GetExceptionCode();
+                  }
+                  _SEH2_END
+                  if (!NT_SUCCESS(Status))
+                  {
+                     ERR("Failure to build window list!\n");
+                     SetLastNtError(Status);
+                     break;
+                  }
+               }
+               dwCount++;
             }
-            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-            {
-               Status = _SEH2_GetExceptionCode();
-            }
-            _SEH2_END
-            if (!NT_SUCCESS(Status))
-            {
-               ERR("Failure to build window list!\n");
-               SetLastNtError(Status);
-               break;
-            }
          }
-         dwCount++;
-         Current = Window->ThreadListEntry.Flink;
-      }
+      }      
 
       ObDereferenceObject(Thread);
    }
@@ -2712,6 +2705,10 @@
     msg.pt = gpsi->ptCursor;
     co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
 
+   /* Send destroy messages */
+
+   IntSendDestroyMsg(Window->head.h);
+
    if (!IntIsWindow(Window->head.h))
    {
       return TRUE;
Index: window.h
===================================================================
--- window.h	(revision 66219)
+++ window.h	(working copy)
@@ -63,5 +63,6 @@
 PWND FASTCALL IntGetNonChildAncestor(PWND);
 LONG FASTCALL co_UserSetWindowLong(HWND,DWORD,LONG,BOOL);
 HWND FASTCALL IntGetWindow(HWND,UINT);
+LRESULT co_UserFreeWindow(PWND,PPROCESSINFO,PTHREADINFO,BOOLEAN);
 
 /* EOF */
