[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 )
{
pwndPrev = pti->MessageQueue->spwndActive;
ptiPrev = pwndPrev->head.pti;
ptiPrev = pwndPrev->head.pti;
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.
UserRefObjectCo(Wnd, &Ref);
UserRefObjectCo(Wnd, &Ref);
co_IntSendMessage( UserHMGetHandle(Wnd), WM_NCACTIVATE, TRUE, 0);
@ -433,7 +433,7 @@ co_IntMakeWindowActive(PWND Window)
{
spwndOwner = spwndOwner->spwndOwner;
}
spwndOwner->spwndLastActive = Window;
WndSetLastActive(spwndOwner, Window);
return TRUE;
}
ERR("MakeWindowActive Failed!\n");
@ -830,7 +830,7 @@ co_IntSetForegroundMessageQueue(
MsqPostMessage(ptiPrev, &Msg, FALSE, QS_EVENT, POSTEVENT_DAW, (LONG_PTR)tid);
}
}
pumqChg = NULL;
if ( ptiChg && !(ptiChg->TIF_flags & TIF_INCLEANUP) )
{

View file

@ -593,8 +593,6 @@ LRESULT co_UserFreeWindow(PWND Window,
Window->style &= ~WS_VISIBLE;
Window->head.pti->cVisWindows--;
WndSetOwner(Window, NULL);
/* 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
in co_UserFreeWindow() */
@ -733,6 +731,12 @@ LRESULT co_UserFreeWindow(PWND Window,
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);
UserMarkObjectDestroy(Window);
@ -948,27 +952,27 @@ IntLinkWindow(
return;
}
Wnd->spwndPrev = WndInsertAfter;
WndSetPrev(Wnd, WndInsertAfter);
if (Wnd->spwndPrev)
{
/* Link after WndInsertAfter */
ASSERT(Wnd != WndInsertAfter->spwndNext);
Wnd->spwndNext = WndInsertAfter->spwndNext;
WndSetNext(Wnd, WndInsertAfter->spwndNext);
if (Wnd->spwndNext)
Wnd->spwndNext->spwndPrev = Wnd;
WndSetPrev(Wnd->spwndNext, Wnd);
ASSERT(Wnd != Wnd->spwndPrev);
Wnd->spwndPrev->spwndNext = Wnd;
WndSetNext(Wnd->spwndPrev, Wnd);
}
else
{
/* Link at the top */
ASSERT(Wnd != Wnd->spwndParent->spwndChild);
Wnd->spwndNext = Wnd->spwndParent->spwndChild;
WndSetNext(Wnd, Wnd->spwndParent->spwndChild);
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;
/* Set the new parent */
Wnd->spwndParent = WndNewParent;
WndSetParent(Wnd, WndNewParent);
if ( Wnd->style & WS_CHILD &&
Wnd->spwndOwner &&
@ -1352,15 +1356,16 @@ IntUnlinkWindow(PWND Wnd)
ASSERT(Wnd != Wnd->spwndPrev);
if (Wnd->spwndNext)
Wnd->spwndNext->spwndPrev = Wnd->spwndPrev;
WndSetPrev(Wnd->spwndNext, Wnd->spwndPrev);
if (Wnd->spwndPrev)
Wnd->spwndPrev->spwndNext = Wnd->spwndNext;
WndSetNext(Wnd->spwndPrev, Wnd->spwndNext);
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
@ -1876,10 +1881,10 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
* Fill out the structure describing it.
*/
/* Remember, pWnd->head is setup in object.c ... */
pWnd->spwndParent = ParentWindow;
WndSetParent(pWnd, ParentWindow);
WndSetOwner(pWnd, OwnerWindow);
pWnd->fnid = 0;
pWnd->spwndLastActive = pWnd;
WndSetLastActive(pWnd, pWnd);
// Ramp up compatible version sets.
if ( dwVer >= WINVER_WIN31 )
{
@ -2932,7 +2937,7 @@ BOOLEAN co_UserDestroyWindow(PVOID Object)
pwndTemp = pwndTemp->spwndOwner;
if (pwndTemp->spwndLastActive == Window)
pwndTemp->spwndLastActive = Window->spwndOwner;
WndSetLastActive(pwndTemp, Window->spwndOwner);
}
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 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
VOID
WndSetOwner(_Inout_ PWND pwnd, _In_opt_ PWND pwndOwner)
{
/* First reference the new owner window */
if (pwndOwner != NULL)
{
UserReferenceObject(pwndOwner);
}
ReplaceWndPtr(&pwnd->spwndOwner, pwndOwner);
}
/* Now dereference the previous owner window */
if (pwnd->spwndOwner != NULL)
{
UserDereferenceObject(pwnd->spwndOwner);
}
static inline
VOID
WndSetParent(_Inout_ PWND pwnd, _In_opt_ PWND pwndParent)
{
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 */