mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[0.4.9][WIN32K:NTUSER] Fix CORE-12243 OS-freezing when closing nLite
This fixes CORE-12243 and allows .NET applications like nLite 1.4.9.3 to exit properly without freezing the whole OS. The actual fix was picked from 0.4.11-dev-78-g4d48b88bfb
"[WIN32K:NTUSER] co_UserDestroyWindow(): Simplify the destruction of the owned windows." but it made sense to also pick the related 0.4.11-dev-77-ge286c4c520
"[WIN32K:NTUSER] Optimize IntWinListOwnedPopups() a little bit. Improve a trace." and 0.4.11-dev-76-gf644a50cd7
"[WIN32K:NTUSER] Code formatting only."
This commit is contained in:
parent
2a9249b546
commit
bf8cbe2769
1 changed files with 92 additions and 69 deletions
|
@ -254,29 +254,69 @@ IntEnableWindow( HWND hWnd, BOOL bEnable )
|
|||
HWND* FASTCALL
|
||||
IntWinListChildren(PWND Window)
|
||||
{
|
||||
PWND Child;
|
||||
HWND *List;
|
||||
UINT Index, NumChildren = 0;
|
||||
PWND Child;
|
||||
HWND *List;
|
||||
UINT Index, NumChildren = 0;
|
||||
|
||||
if (!Window) return NULL;
|
||||
if (!Window) return NULL;
|
||||
|
||||
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
|
||||
++NumChildren;
|
||||
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
|
||||
{
|
||||
++NumChildren;
|
||||
}
|
||||
|
||||
List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
|
||||
if(!List)
|
||||
{
|
||||
ERR("Failed to allocate memory for children array\n");
|
||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
for (Child = Window->spwndChild, Index = 0;
|
||||
Child != NULL;
|
||||
Child = Child->spwndNext, ++Index)
|
||||
List[Index] = Child->head.h;
|
||||
List[Index] = NULL;
|
||||
List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
|
||||
if(!List)
|
||||
{
|
||||
ERR("Failed to allocate memory for children array\n");
|
||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return List;
|
||||
Index = 0;
|
||||
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
|
||||
{
|
||||
List[Index++] = Child->head.h;
|
||||
}
|
||||
List[Index] = NULL;
|
||||
|
||||
return List;
|
||||
}
|
||||
|
||||
HWND* FASTCALL
|
||||
IntWinListOwnedPopups(PWND Window)
|
||||
{
|
||||
PWND Child, Desktop;
|
||||
HWND *List;
|
||||
UINT Index, NumOwned = 0;
|
||||
|
||||
Desktop = co_GetDesktopWindow(Window);
|
||||
if (!Desktop)
|
||||
return NULL;
|
||||
|
||||
for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
|
||||
{
|
||||
if (Child->spwndOwner == Window)
|
||||
++NumOwned;
|
||||
}
|
||||
|
||||
List = ExAllocatePoolWithTag(PagedPool, (NumOwned + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
|
||||
if (!List)
|
||||
{
|
||||
ERR("Failed to allocate memory for children array\n");
|
||||
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Index = 0;
|
||||
for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
|
||||
{
|
||||
if (Child->spwndOwner == Window)
|
||||
List[Index++] = Child->head.h;
|
||||
}
|
||||
List[Index] = NULL;
|
||||
|
||||
return List;
|
||||
}
|
||||
|
||||
PWND FASTCALL
|
||||
|
@ -2572,7 +2612,7 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
|
|||
hWnd = Window->head.h;
|
||||
ti = PsGetCurrentThreadWin32Thread();
|
||||
|
||||
TRACE("co_UserDestroyWindow \n");
|
||||
TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
|
||||
|
||||
/* Check for owner thread */
|
||||
if ( Window->head.pti != PsGetCurrentThreadWin32Thread())
|
||||
|
@ -2632,7 +2672,7 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
|
|||
}
|
||||
}
|
||||
|
||||
// Adjust last active.
|
||||
/* Adjust last active */
|
||||
if ((pwndTemp = Window->spwndOwner))
|
||||
{
|
||||
while (pwndTemp->spwndOwner)
|
||||
|
@ -2683,58 +2723,41 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Recursively destroy owned windows */
|
||||
/* Recursively destroy owned windows */
|
||||
if (!(Window->style & WS_CHILD))
|
||||
{
|
||||
HWND* List;
|
||||
HWND* phWnd;
|
||||
PWND pWnd;
|
||||
|
||||
if (! (Window->style & WS_CHILD))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
BOOL GotOne = FALSE;
|
||||
HWND *Children;
|
||||
HWND *ChildHandle;
|
||||
PWND Child, Desktop;
|
||||
|
||||
Desktop = IntIsDesktopWindow(Window) ? Window :
|
||||
UserGetWindowObject(IntGetDesktopWindow());
|
||||
Children = IntWinListChildren(Desktop);
|
||||
|
||||
if (Children)
|
||||
{
|
||||
for (ChildHandle = Children; *ChildHandle; ++ChildHandle)
|
||||
List = IntWinListOwnedPopups(Window);
|
||||
if (List)
|
||||
{
|
||||
for (phWnd = List; *phWnd; ++phWnd)
|
||||
{
|
||||
Child = UserGetWindowObject(*ChildHandle);
|
||||
if (Child == NULL)
|
||||
continue;
|
||||
if (Child->spwndOwner != Window)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IntWndBelongsToThread(Child, PsGetCurrentThreadWin32Thread()))
|
||||
{
|
||||
USER_REFERENCE_ENTRY ChildRef;
|
||||
UserRefObjectCo(Child, &ChildRef); // Temp HACK?
|
||||
co_UserDestroyWindow(Child);
|
||||
UserDerefObjectCo(Child); // Temp HACK?
|
||||
|
||||
GotOne = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Child->spwndOwner != NULL)
|
||||
{
|
||||
Child->spwndOwner = NULL;
|
||||
}
|
||||
pWnd = ValidateHwndNoErr(*phWnd);
|
||||
if (pWnd == NULL)
|
||||
continue;
|
||||
ASSERT(pWnd->spwndOwner == Window);
|
||||
ASSERT(pWnd != Window);
|
||||
|
||||
pWnd->spwndOwner = NULL;
|
||||
if (IntWndBelongsToThread(pWnd, PsGetCurrentThreadWin32Thread()))
|
||||
{
|
||||
USER_REFERENCE_ENTRY Ref;
|
||||
UserRefObjectCo(pWnd, &Ref); // Temp HACK?
|
||||
co_UserDestroyWindow(pWnd);
|
||||
UserDerefObjectCo(pWnd); // Temp HACK?
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", pWnd);
|
||||
}
|
||||
}
|
||||
ExFreePoolWithTag(Children, USERTAG_WINDOWLIST);
|
||||
}
|
||||
if (! GotOne)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate mouse move message for the next window */
|
||||
msg.message = WM_MOUSEMOVE;
|
||||
|
|
Loading…
Reference in a new issue