[NTUSER] Always reference a window when using it as parent/child etc.

CORE-18811
This commit is contained in:
Jérôme Gardou 2023-07-24 22:20:29 +02:00 committed by Jérôme Gardou
parent b3d0591e76
commit 1599d7b794
3 changed files with 80 additions and 32 deletions

View file

@ -242,7 +242,7 @@ IntDeactivateWindow(PTHREADINFO pti, HANDLE tid)
if ( pti->MessageQueue->spwndActive ) if ( pti->MessageQueue->spwndActive )
{ {
pwndPrev = pti->MessageQueue->spwndActive; pwndPrev = pti->MessageQueue->spwndActive;
ptiPrev = pwndPrev->head.pti; ptiPrev = pwndPrev->head.pti;
if (!co_IntSendDeactivateMessages(UserHMGetHandle(pwndPrev), 0, TRUE)) if (!co_IntSendDeactivateMessages(UserHMGetHandle(pwndPrev), 0, TRUE))
{ {
@ -403,7 +403,7 @@ IntActivateWindow(PWND Wnd, PTHREADINFO pti, HANDLE tid, DWORD Type)
{ {
Wnd = pmq->spwndActive; // Use active window from current queue. Wnd = pmq->spwndActive; // Use active window from current queue.
UserRefObjectCo(Wnd, &Ref); UserRefObjectCo(Wnd, &Ref);
co_IntSendMessage( UserHMGetHandle(Wnd), WM_NCACTIVATE, TRUE, 0); co_IntSendMessage( UserHMGetHandle(Wnd), WM_NCACTIVATE, TRUE, 0);
@ -433,7 +433,7 @@ co_IntMakeWindowActive(PWND Window)
{ {
spwndOwner = spwndOwner->spwndOwner; spwndOwner = spwndOwner->spwndOwner;
} }
spwndOwner->spwndLastActive = Window; WndSetLastActive(spwndOwner, Window);
return TRUE; return TRUE;
} }
ERR("MakeWindowActive Failed!\n"); ERR("MakeWindowActive Failed!\n");
@ -830,7 +830,7 @@ co_IntSetForegroundMessageQueue(
MsqPostMessage(ptiPrev, &Msg, FALSE, QS_EVENT, POSTEVENT_DAW, (LONG_PTR)tid); MsqPostMessage(ptiPrev, &Msg, FALSE, QS_EVENT, POSTEVENT_DAW, (LONG_PTR)tid);
} }
} }
pumqChg = NULL; pumqChg = NULL;
if ( ptiChg && !(ptiChg->TIF_flags & TIF_INCLEANUP) ) if ( ptiChg && !(ptiChg->TIF_flags & TIF_INCLEANUP) )
{ {

View file

@ -593,8 +593,6 @@ LRESULT co_UserFreeWindow(PWND Window,
Window->style &= ~WS_VISIBLE; Window->style &= ~WS_VISIBLE;
Window->head.pti->cVisWindows--; Window->head.pti->cVisWindows--;
WndSetOwner(Window, NULL);
/* remove the window already at this point from the thread window list so we /* remove the window already at this point from the thread window list so we
don't get into trouble when destroying the thread windows while we're still don't get into trouble when destroying the thread windows while we're still
in co_UserFreeWindow() */ in co_UserFreeWindow() */
@ -733,6 +731,12 @@ LRESULT co_UserFreeWindow(PWND Window,
ASSERT(Window->PropListItems==0); ASSERT(Window->PropListItems==0);
} }
/* Kill any reference to linked windows. Prev & Next are taken care of in IntUnlinkWindow */
WndSetOwner(Window, NULL);
WndSetParent(Window, NULL);
WndSetChild(Window, NULL);
WndSetLastActive(Window, NULL);
UserReferenceObject(Window); UserReferenceObject(Window);
UserMarkObjectDestroy(Window); UserMarkObjectDestroy(Window);
@ -948,27 +952,27 @@ IntLinkWindow(
return; return;
} }
Wnd->spwndPrev = WndInsertAfter; WndSetPrev(Wnd, WndInsertAfter);
if (Wnd->spwndPrev) if (Wnd->spwndPrev)
{ {
/* Link after WndInsertAfter */ /* Link after WndInsertAfter */
ASSERT(Wnd != WndInsertAfter->spwndNext); ASSERT(Wnd != WndInsertAfter->spwndNext);
Wnd->spwndNext = WndInsertAfter->spwndNext; WndSetNext(Wnd, WndInsertAfter->spwndNext);
if (Wnd->spwndNext) if (Wnd->spwndNext)
Wnd->spwndNext->spwndPrev = Wnd; WndSetPrev(Wnd->spwndNext, Wnd);
ASSERT(Wnd != Wnd->spwndPrev); ASSERT(Wnd != Wnd->spwndPrev);
Wnd->spwndPrev->spwndNext = Wnd; WndSetNext(Wnd->spwndPrev, Wnd);
} }
else else
{ {
/* Link at the top */ /* Link at the top */
ASSERT(Wnd != Wnd->spwndParent->spwndChild); ASSERT(Wnd != Wnd->spwndParent->spwndChild);
Wnd->spwndNext = Wnd->spwndParent->spwndChild; WndSetNext(Wnd, Wnd->spwndParent->spwndChild);
if (Wnd->spwndNext) if (Wnd->spwndNext)
Wnd->spwndNext->spwndPrev = Wnd; WndSetPrev(Wnd->spwndNext, Wnd);
Wnd->spwndParent->spwndChild = Wnd; WndSetChild(Wnd->spwndParent, Wnd);
} }
} }
@ -1220,7 +1224,7 @@ co_IntSetParent(PWND Wnd, PWND WndNewParent)
Wnd->ExStyle2 &= ~WS_EX2_LINKED; Wnd->ExStyle2 &= ~WS_EX2_LINKED;
/* Set the new parent */ /* Set the new parent */
Wnd->spwndParent = WndNewParent; WndSetParent(Wnd, WndNewParent);
if ( Wnd->style & WS_CHILD && if ( Wnd->style & WS_CHILD &&
Wnd->spwndOwner && Wnd->spwndOwner &&
@ -1352,15 +1356,16 @@ IntUnlinkWindow(PWND Wnd)
ASSERT(Wnd != Wnd->spwndPrev); ASSERT(Wnd != Wnd->spwndPrev);
if (Wnd->spwndNext) if (Wnd->spwndNext)
Wnd->spwndNext->spwndPrev = Wnd->spwndPrev; WndSetPrev(Wnd->spwndNext, Wnd->spwndPrev);
if (Wnd->spwndPrev) if (Wnd->spwndPrev)
Wnd->spwndPrev->spwndNext = Wnd->spwndNext; WndSetNext(Wnd->spwndPrev, Wnd->spwndNext);
if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd) if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd)
Wnd->spwndParent->spwndChild = Wnd->spwndNext; WndSetChild(Wnd->spwndParent, Wnd->spwndNext);
Wnd->spwndPrev = Wnd->spwndNext = NULL; WndSetPrev(Wnd, NULL);
WndSetNext(Wnd, NULL);
} }
// Win: ExpandWindowList // Win: ExpandWindowList
@ -1876,10 +1881,10 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
* Fill out the structure describing it. * Fill out the structure describing it.
*/ */
/* Remember, pWnd->head is setup in object.c ... */ /* Remember, pWnd->head is setup in object.c ... */
pWnd->spwndParent = ParentWindow; WndSetParent(pWnd, ParentWindow);
WndSetOwner(pWnd, OwnerWindow); WndSetOwner(pWnd, OwnerWindow);
pWnd->fnid = 0; pWnd->fnid = 0;
pWnd->spwndLastActive = pWnd; WndSetLastActive(pWnd, pWnd);
// Ramp up compatible version sets. // Ramp up compatible version sets.
if ( dwVer >= WINVER_WIN31 ) if ( dwVer >= WINVER_WIN31 )
{ {
@ -2932,7 +2937,7 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
pwndTemp = pwndTemp->spwndOwner; pwndTemp = pwndTemp->spwndOwner;
if (pwndTemp->spwndLastActive == Window) if (pwndTemp->spwndLastActive == Window)
pwndTemp->spwndLastActive = Window->spwndOwner; WndSetLastActive(pwndTemp, Window->spwndOwner);
} }
if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window))) if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window)))

View file

@ -125,23 +125,66 @@ BOOL FASTCALL IntBroadcastImeShowStatusChange(PWND pImeWnd, BOOL bShow);
VOID FASTCALL IntNotifyImeShowStatus(PWND pImeWnd); VOID FASTCALL IntNotifyImeShowStatus(PWND pImeWnd);
VOID FASTCALL IntCheckImeShowStatusInThread(PWND pImeWnd); VOID FASTCALL IntCheckImeShowStatusInThread(PWND pImeWnd);
static inline
VOID
ReplaceWndPtr(_Inout_ PWND* ppwnd, _In_opt_ PWND pwndNew)
{
/* First reference the new one */
if (pwndNew != NULL)
{
UserReferenceObject(pwndNew);
}
/* Then dereference the previous one */
if (*ppwnd != NULL)
{
UserDereferenceObject(*ppwnd);
}
/* And set */
*ppwnd = pwndNew;
}
static inline static inline
VOID VOID
WndSetOwner(_Inout_ PWND pwnd, _In_opt_ PWND pwndOwner) WndSetOwner(_Inout_ PWND pwnd, _In_opt_ PWND pwndOwner)
{ {
/* First reference the new owner window */ ReplaceWndPtr(&pwnd->spwndOwner, pwndOwner);
if (pwndOwner != NULL) }
{
UserReferenceObject(pwndOwner);
}
/* Now dereference the previous owner window */ static inline
if (pwnd->spwndOwner != NULL) VOID
{ WndSetParent(_Inout_ PWND pwnd, _In_opt_ PWND pwndParent)
UserDereferenceObject(pwnd->spwndOwner); {
} ReplaceWndPtr(&pwnd->spwndParent, pwndParent);
}
pwnd->spwndOwner = pwndOwner; static inline
VOID
WndSetChild(_Inout_ PWND pwnd, _In_opt_ PWND pwndChild)
{
ReplaceWndPtr(&pwnd->spwndChild, pwndChild);
}
static inline
VOID
WndSetNext(_Inout_ PWND pwnd, _In_opt_ PWND pwndNext)
{
ReplaceWndPtr(&pwnd->spwndNext, pwndNext);
}
static inline
VOID
WndSetPrev(_Inout_ PWND pwnd, _In_opt_ PWND pwndPrev)
{
ReplaceWndPtr(&pwnd->spwndPrev, pwndPrev);
}
static inline
VOID
WndSetLastActive(_Inout_ PWND pwnd, _In_opt_ PWND pwndLastActive)
{
ReplaceWndPtr(&pwnd->spwndLastActive, pwndLastActive);
} }
/* EOF */ /* EOF */