https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1599d7b79426961f7f887…
commit 1599d7b79426961f7f887ef32d9307f2dd812d0e
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Mon Jul 24 22:20:29 2023 +0200
Commit: Jérôme Gardou <zefklop(a)users.noreply.github.com>
CommitDate: Mon Jul 24 23:29:38 2023 +0200
[NTUSER] Always reference a window when using it as parent/child etc.
CORE-18811
---
win32ss/user/ntuser/focus.c | 8 +++---
win32ss/user/ntuser/window.c | 39 ++++++++++++++++-------------
win32ss/user/ntuser/window.h | 59 ++++++++++++++++++++++++++++++++++++++------
3 files changed, 77 insertions(+), 29 deletions(-)
diff --git a/win32ss/user/ntuser/focus.c b/win32ss/user/ntuser/focus.c
index 07cc78c4f08..3b11d47d5f4 100644
--- a/win32ss/user/ntuser/focus.c
+++ b/win32ss/user/ntuser/focus.c
@@ -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) )
{
diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c
index e587c73a58d..fe05bafac66 100644
--- a/win32ss/user/ntuser/window.c
+++ b/win32ss/user/ntuser/window.c
@@ -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)))
diff --git a/win32ss/user/ntuser/window.h b/win32ss/user/ntuser/window.h
index fa0387f30d3..a6c60a6354c 100644
--- a/win32ss/user/ntuser/window.h
+++ b/win32ss/user/ntuser/window.h
@@ -127,21 +127,64 @@ VOID FASTCALL IntCheckImeShowStatusInThread(PWND pImeWnd);
static inline
VOID
-WndSetOwner(_Inout_ PWND pwnd, _In_opt_ PWND pwndOwner)
+ReplaceWndPtr(_Inout_ PWND* ppwnd, _In_opt_ PWND pwndNew)
{
- /* First reference the new owner window */
- if (pwndOwner != NULL)
+ /* First reference the new one */
+ if (pwndNew != NULL)
{
- UserReferenceObject(pwndOwner);
+ UserReferenceObject(pwndNew);
}
- /* Now dereference the previous owner window */
- if (pwnd->spwndOwner != NULL)
+ /* Then dereference the previous one */
+ if (*ppwnd != NULL)
{
- UserDereferenceObject(pwnd->spwndOwner);
+ UserDereferenceObject(*ppwnd);
}
- pwnd->spwndOwner = pwndOwner;
+ /* And set */
+ *ppwnd = pwndNew;
+}
+
+static inline
+VOID
+WndSetOwner(_Inout_ PWND pwnd, _In_opt_ PWND pwndOwner)
+{
+ ReplaceWndPtr(&pwnd->spwndOwner, pwndOwner);
+}
+
+static inline
+VOID
+WndSetParent(_Inout_ PWND pwnd, _In_opt_ PWND pwndParent)
+{
+ ReplaceWndPtr(&pwnd->spwndParent, pwndParent);
+}
+
+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 */