From 743f12cdc8e3fd9b1a2c69b77fa15c0a2fbcc380 Mon Sep 17 00:00:00 2001 From: Joachim Henze Date: Wed, 23 Dec 2020 02:21:19 +0100 Subject: [PATCH] [0.4.9][WIN32K:NTUSER] Properly fix IntSendChildNCPaint() & IntLinkWindow() Hack has been introduced in IntSendChildNCPaint() in r73532 == 6d7fcc4 to attempt to pseudo-fix CORE-12071 and CORE-12085 while breaking other stuff, amongst which CORE-14763 is one of the latest manifestations, and re-enable the correct original code. This fixes painting hangs under diverse situations, while CORE-12071 and CORE-12085 remain fixed. When it was hanging like CORE-14763, we could not even ACPI shutdown anymore. by porting back: 0.4.10-dev-324-g 25004bb5b424960358fda4ba9d8438246c0bef9e 0.4.10-dev-323-g ee0511b49db6197897386df44078c8048a49c821 0.4.10-dev-322-g 4d057cf6267bcbe7be3253fa3caa59f5b1feeb87 --- win32ss/user/ntuser/painting.c | 42 ++++------------ win32ss/user/ntuser/window.c | 89 ++++++++++++++++++++-------------- win32ss/user/ntuser/winpos.c | 2 - 3 files changed, 63 insertions(+), 70 deletions(-) diff --git a/win32ss/user/ntuser/painting.c b/win32ss/user/ntuser/painting.c index 5b4d04ff204..6a8b2a9bf73 100644 --- a/win32ss/user/ntuser/painting.c +++ b/win32ss/user/ntuser/painting.c @@ -366,38 +366,16 @@ IntSendNCPaint(PWND pWnd, HRGN hRgn) VOID FASTCALL IntSendChildNCPaint(PWND pWnd) { - PWND Child; - HWND *List, *phWnd; - - List = IntWinListChildren(UserGetDesktopWindow()); - if ( List ) - { - for (phWnd = List; *phWnd; ++phWnd) - { - Child = ValidateHwndNoErr(*phWnd); - if ( Child && Child->hrgnUpdate == NULL && Child->state & WNDS_SENDNCPAINT) - { - USER_REFERENCE_ENTRY Ref; - UserRefObjectCo(Child, &Ref); - IntSendNCPaint(Child, HRGN_WINDOW); - UserDerefObjectCo(Child); - } - } - ExFreePoolWithTag(List, USERTAG_WINDOWLIST); - } -/* FIXME : Use snap shot mode until window death is fixed while surfing menus! Fix CORE-12085 and CORE-12071. - pWnd = pWnd->spwndChild; - while(pWnd) - { - if (pWnd->hrgnUpdate == NULL && pWnd->state & WNDS_SENDNCPAINT) - { - USER_REFERENCE_ENTRY Ref; - UserRefObjectCo(pWnd, &Ref); - IntSendNCPaint(pWnd, HRGN_WINDOW); - UserDerefObjectCo(pWnd); - } - pWnd = pWnd->spwndNext; - }*/ + for (pWnd = pWnd->spwndChild; pWnd; pWnd = pWnd->spwndNext) + { + if ((pWnd->hrgnUpdate == NULL) && (pWnd->state & WNDS_SENDNCPAINT)) + { + USER_REFERENCE_ENTRY Ref; + UserRefObjectCo(pWnd, &Ref); + IntSendNCPaint(pWnd, HRGN_WINDOW); + UserDerefObjectCo(pWnd); + } + } } /* diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c index 67602adef4b..d350df65026 100644 --- a/win32ss/user/ntuser/window.c +++ b/win32ss/user/ntuser/window.c @@ -894,32 +894,41 @@ IntIsChildWindow(PWND Parent, PWND BaseWindow) } //// -/* - Link the window into siblings list - children and parent are kept in place. -*/ +/* Link the window into siblings list. Children and parent are kept in place. */ VOID FASTCALL IntLinkWindow( - PWND Wnd, - PWND WndInsertAfter /* set to NULL if top sibling */ + PWND Wnd, + PWND WndInsertAfter /* Set to NULL if top sibling */ ) { - if ((Wnd->spwndPrev = WndInsertAfter)) - { - /* link after WndInsertAfter */ - if ((Wnd->spwndNext = WndInsertAfter->spwndNext)) - Wnd->spwndNext->spwndPrev = Wnd; + if (Wnd == WndInsertAfter) + { + ERR("IntLinkWindow -- Trying to link window 0x%p to itself!!\n", Wnd); + return; + } - Wnd->spwndPrev->spwndNext = Wnd; - } - else - { - /* link at top */ - if ((Wnd->spwndNext = Wnd->spwndParent->spwndChild)) - Wnd->spwndNext->spwndPrev = Wnd; + Wnd->spwndPrev = WndInsertAfter; + if (Wnd->spwndPrev) + { + /* Link after WndInsertAfter */ + ASSERT(Wnd != WndInsertAfter->spwndNext); + Wnd->spwndNext = WndInsertAfter->spwndNext; + if (Wnd->spwndNext) + Wnd->spwndNext->spwndPrev = Wnd; - Wnd->spwndParent->spwndChild = Wnd; - } + ASSERT(Wnd != Wnd->spwndPrev); + Wnd->spwndPrev->spwndNext = Wnd; + } + else + { + /* Link at the top */ + ASSERT(Wnd != Wnd->spwndParent->spwndChild); + Wnd->spwndNext = Wnd->spwndParent->spwndChild; + if (Wnd->spwndNext) + Wnd->spwndNext->spwndPrev = Wnd; + + Wnd->spwndParent->spwndChild = Wnd; + } } /* @@ -929,8 +938,8 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) { if (hWndPrev == HWND_NOTOPMOST) { - if (!(Wnd->ExStyle & WS_EX_TOPMOST) && - (Wnd->ExStyle2 & WS_EX2_LINKED)) return; /* nothing to do */ + if (!(Wnd->ExStyle & WS_EX_TOPMOST) && (Wnd->ExStyle2 & WS_EX2_LINKED)) + return; /* nothing to do */ Wnd->ExStyle &= ~WS_EX_TOPMOST; hWndPrev = HWND_TOP; /* fallback to the HWND_TOP case */ } @@ -943,8 +952,10 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) PWND WndInsertAfter; WndInsertAfter = Wnd->spwndParent->spwndChild; - while( WndInsertAfter && WndInsertAfter->spwndNext) + while (WndInsertAfter && WndInsertAfter->spwndNext) + { WndInsertAfter = WndInsertAfter->spwndNext; + } IntLinkWindow(Wnd, WndInsertAfter); Wnd->ExStyle &= ~WS_EX_TOPMOST; @@ -953,7 +964,6 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) { /* Link in the top of the list */ IntLinkWindow(Wnd, NULL); - Wnd->ExStyle |= WS_EX_TOPMOST; } else if (hWndPrev == HWND_TOP) @@ -967,7 +977,9 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) { while (WndInsertBefore != NULL && WndInsertBefore->spwndNext != NULL) { - if (!(WndInsertBefore->ExStyle & WS_EX_TOPMOST)) break; + if (!(WndInsertBefore->ExStyle & WS_EX_TOPMOST)) + break; + if (WndInsertBefore == Wnd->spwndOwner) /* keep it above owner */ { Wnd->ExStyle |= WS_EX_TOPMOST; @@ -986,13 +998,15 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) WndInsertAfter = UserGetWindowObject(hWndPrev); /* Are we called with an erroneous handle */ - if(WndInsertAfter == NULL) + if (WndInsertAfter == NULL) { /* Link in a default position */ IntLinkHwnd(Wnd, HWND_TOP); return; } + if (Wnd == WndInsertAfter) + ERR("IntLinkHwnd -- Trying to link window 0x%p to itself!!\n", Wnd); IntLinkWindow(Wnd, WndInsertAfter); /* Fix the WS_EX_TOPMOST flag */ @@ -1002,8 +1016,8 @@ VOID FASTCALL IntLinkHwnd(PWND Wnd, HWND hWndPrev) } else { - if(WndInsertAfter->spwndNext && - WndInsertAfter->spwndNext->ExStyle & WS_EX_TOPMOST) + if (WndInsertAfter->spwndNext && + (WndInsertAfter->spwndNext->ExStyle & WS_EX_TOPMOST)) { Wnd->ExStyle |= WS_EX_TOPMOST; } @@ -1287,20 +1301,23 @@ co_UserSetParent(HWND hWndChild, HWND hWndNewParent) return( hWndOldParent); } -/* Unlink the window from siblings. children and parent are kept in place. */ +/* Unlink the window from siblings. Children and parent are kept in place. */ VOID FASTCALL IntUnlinkWindow(PWND Wnd) { - if (Wnd->spwndNext) - Wnd->spwndNext->spwndPrev = Wnd->spwndPrev; + ASSERT(Wnd != Wnd->spwndNext); + ASSERT(Wnd != Wnd->spwndPrev); - if (Wnd->spwndPrev) - Wnd->spwndPrev->spwndNext = Wnd->spwndNext; + if (Wnd->spwndNext) + Wnd->spwndNext->spwndPrev = Wnd->spwndPrev; - if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd) - Wnd->spwndParent->spwndChild = Wnd->spwndNext; + if (Wnd->spwndPrev) + Wnd->spwndPrev->spwndNext = Wnd->spwndNext; - Wnd->spwndPrev = Wnd->spwndNext = NULL; + if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd) + Wnd->spwndParent->spwndChild = Wnd->spwndNext; + + Wnd->spwndPrev = Wnd->spwndNext = NULL; } /* FUNCTIONS *****************************************************************/ diff --git a/win32ss/user/ntuser/winpos.c b/win32ss/user/ntuser/winpos.c index 13e7367e93d..0c8c5b71807 100644 --- a/win32ss/user/ntuser/winpos.c +++ b/win32ss/user/ntuser/winpos.c @@ -30,8 +30,6 @@ DBG_DEFAULT_CHANNEL(UserWinpos); #define PLACE_MAX 0x0002 #define PLACE_RECT 0x0004 -VOID FASTCALL IntLinkWindow(PWND Wnd,PWND WndInsertAfter); - /* FUNCTIONS *****************************************************************/ #if DBG