[NTUSER] Always reference a window when using it as parent/child etc.
authorJérôme Gardou <jerome.gardou@reactos.org>
Mon, 24 Jul 2023 20:20:29 +0000 (22:20 +0200)
committerJérôme Gardou <zefklop@users.noreply.github.com>
Mon, 24 Jul 2023 21:29:38 +0000 (23:29 +0200)
CORE-18811

win32ss/user/ntuser/focus.c
win32ss/user/ntuser/window.c
win32ss/user/ntuser/window.h

index 07cc78c..3b11d47 100644 (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) )
       {
index e587c73..fe05baf 100644 (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)))
index fa0387f..a6c60a6 100644 (file)
@@ -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 */