Index: include/ntuser.h =================================================================== --- win32ss/include/ntuser.h (revision 66208) +++ win32ss/include/ntuser.h (working copy) @@ -638,6 +638,7 @@ #define WNDS2_FORCENCPAINT 0X00400000 #define WNDS2_FORCEFULLNCPAINTCLIPRGN 0X00800000 #define WNDS2_FULLSCREENMODE 0X01000000 +#define WNDS2_DESTROYMSGSENT 0X02000000 #define WNDS2_CAPTIONTEXTTRUNCATED 0X08000000 #define WNDS2_NOMINMAXANIMATERECTS 0X10000000 #define WNDS2_SMALLICONFROMWMQUERYDRAG 0X20000000 Index: user/ntuser/window.c =================================================================== --- win32ss/user/ntuser/window.c (revision 66208) +++ win32ss/user/ntuser/window.c (working copy) @@ -486,7 +486,7 @@ if(Window->state2 & WNDS2_INDESTROY) { - TRACE("Tried to call IntDestroyWindow() twice\n"); + TRACE("Tried to call co_UserFreeWindow() twice\n"); return 0; } Window->state2 |= WNDS2_INDESTROY; @@ -511,25 +511,37 @@ } /* free child windows */ - Children = IntWinListChildren(Window); - if (Children) + for (;;) { - for (ChildHandle = Children; *ChildHandle; ++ChildHandle) + BOOL GotOne = FALSE; + Children = IntWinListChildren(Window); + if (Children) { - if ((Child = IntGetWindowObject(*ChildHandle))) + for (ChildHandle = Children; *ChildHandle; ++ChildHandle) { - if(!IntWndBelongsToThread(Child, ThreadData)) + Child = IntGetWindowObject(*ChildHandle); + if (Child == NULL) + continue; + + if (!IntWndBelongsToThread(Child, ThreadData)) { /* send WM_DESTROY messages to windows not belonging to the same thread */ + if (Child->state2 & WNDS2_DESTROYMSGSENT) + continue; IntSendDestroyMsg(Child->head.h); + Child->state2 |= WNDS2_DESTROYMSGSENT; } else co_UserFreeWindow(Child, ProcessData, ThreadData, SendMessages); UserDereferenceObject(Child); + GotOne = TRUE; + break; } + ExFreePoolWithTag(Children, USERTAG_WINDOWLIST); } - ExFreePoolWithTag(Children, USERTAG_WINDOWLIST); + if (!GotOne) + break; } if(SendMessages)