https://git.reactos.org/?p=reactos.git;a=commitdiff;h=22577aed85f91b33a25c89ad857951ddb8e1a988

commit 22577aed85f91b33a25c89ad857951ddb8e1a988
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Fri Feb 7 07:31:08 2025 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Fri Feb 7 07:31:08 2025 +0900

    [NTUSER][USER32] Support GetWindow.GW_ENABLEDPOPUP (#7700)
    
    JIRA issue: CORE-6920
    - Make the return value of
      NtUserCallHwnd a DWORD_PTR.
    - Add DWP_GetEnabledPopup
      helper function in
      win32ss/user/ntuser/defwnd.c.
    - Add code to NtUserCallHwnd for
      HWND_ROUTINE_DWP_GETENABLEDPOPUP.
    - Add code to GetWindow for
      GW_ENABLEDPOPUP.
    - Set last error in GetWindow and
      IntGetWindow.
---
 win32ss/include/ntuser.h                |  2 +-
 win32ss/user/ntuser/defwnd.c            | 52 +++++++++++++++++++++++++++++++++
 win32ss/user/ntuser/simplecall.c        | 13 ++++++++-
 win32ss/user/ntuser/userfuncs.h         |  1 +
 win32ss/user/ntuser/window.c            |  2 +-
 win32ss/user/user32/include/ntwrapper.h |  8 ++---
 win32ss/user/user32/windows/window.c    | 12 +++++++-
 7 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index 7e09af4896f..783d4e0c32a 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -1670,7 +1670,7 @@ enum SimpleCallRoutines
     TWOPARAM_ROUTINE_WOWCLEANUP
 };
 
-DWORD
+DWORD_PTR
 NTAPI
 NtUserCallHwnd(
     HWND hWnd,
diff --git a/win32ss/user/ntuser/defwnd.c b/win32ss/user/ntuser/defwnd.c
index 368105afc42..dba5c7b567b 100644
--- a/win32ss/user/ntuser/defwnd.c
+++ b/win32ss/user/ntuser/defwnd.c
@@ -495,6 +495,58 @@ DefWndGetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
     return (LRESULT)hIconRet;
 }
 
+PWND FASTCALL
+DWP_GetEnabledPopup(PWND pWnd)
+{
+    PWND pwndNode1;
+    PTHREADINFO pti = pWnd->head.pti, ptiNode;
+    BOOL bFoundNullNode = FALSE;
+
+    for (pwndNode1 = pWnd->spwndNext; pwndNode1 != pWnd; )
+    {
+        if (!pwndNode1) /* NULL detected? */
+        {
+            if (bFoundNullNode)
+                return NULL;
+            bFoundNullNode = TRUE;
+            /* Retry with parent's first child (once only) */
+            pwndNode1 = pWnd->spwndParent->spwndChild;
+            continue;
+        }
+
+        /*
+         * 1. We want to detect the window that owns the same input target of 
pWnd.
+         * 2. For non-16-bit apps, we need to check the two threads' input 
queues to
+         *    see whether they are the same, while for 16-bit apps it's 
sufficient to
+         *    only check the thread info pointers themselves (ptiNode and pti).
+         * See also:
+         *    https://devblogs.microsoft.com/oldnewthing/20060221-09/?p=32203
+         *    
https://github.com/reactos/reactos/pull/7700#discussion_r1939435931
+         */
+        ptiNode = pwndNode1->head.pti;
+        if ((!(pti->TIF_flags & TIF_16BIT) && ptiNode->MessageQueue == 
pti->MessageQueue) ||
+            ((pti->TIF_flags & TIF_16BIT) && ptiNode == pti))
+        {
+            DWORD style = pwndNode1->style;
+            if ((style & WS_VISIBLE) && !(style & WS_DISABLED)) /* Visible and 
enabled? */
+            {
+                /* Does pwndNode1 have a pWnd as an ancestor? */
+                PWND pwndNode2;
+                for (pwndNode2 = pwndNode1->spwndOwner; pwndNode2;
+                     pwndNode2 = pwndNode2->spwndOwner)
+                {
+                    if (pwndNode2 == pWnd)
+                        return pwndNode1;
+                }
+            }
+        }
+
+        pwndNode1 = pwndNode1->spwndNext;
+    }
+
+    return NULL;
+}
+
 VOID FASTCALL
 DefWndScreenshot(PWND pWnd)
 {
diff --git a/win32ss/user/ntuser/simplecall.c b/win32ss/user/ntuser/simplecall.c
index fa7ee28d857..6a433ed7120 100644
--- a/win32ss/user/ntuser/simplecall.c
+++ b/win32ss/user/ntuser/simplecall.c
@@ -706,7 +706,7 @@ NtUserCallHwndOpt(
     return hWnd;
 }
 
-DWORD
+DWORD_PTR
 APIENTRY
 NtUserCallHwnd(
     HWND hWnd,
@@ -755,6 +755,17 @@ NtUserCallHwnd(
             UserLeave();
             return FALSE;
         }
+
+        case HWND_ROUTINE_DWP_GETENABLEDPOPUP:
+        {
+            PWND pWnd;
+            UserEnterShared();
+            pWnd = UserGetWindowObject(hWnd);
+            if (pWnd)
+                pWnd = DWP_GetEnabledPopup(pWnd);
+            UserLeave();
+            return (DWORD_PTR)pWnd;
+        }
     }
 
     STUB;
diff --git a/win32ss/user/ntuser/userfuncs.h b/win32ss/user/ntuser/userfuncs.h
index 740607530a4..f282344ab56 100644
--- a/win32ss/user/ntuser/userfuncs.h
+++ b/win32ss/user/ntuser/userfuncs.h
@@ -161,6 +161,7 @@ LRESULT NC_HandleNCRButtonDown( PWND wnd, WPARAM wParam, 
LPARAM lParam );
 HBRUSH FASTCALL DefWndControlColor(HDC hDC,UINT ctlType);
 BOOL UserDrawSysMenuButton(PWND pWnd, HDC hDC, LPRECT Rect, BOOL Down);
 BOOL UserPaintCaption(PWND pWnd, INT Flags);
+PWND FASTCALL DWP_GetEnabledPopup(PWND pWnd);
 
 /************** LAYERED **************/
 
diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c
index 55df7d52b4c..9f8d669e3e8 100644
--- a/win32ss/user/ntuser/window.c
+++ b/win32ss/user/ntuser/window.c
@@ -428,7 +428,7 @@ IntGetWindow(HWND hWnd,
                 break;
 
             default:
-                Wnd = NULL;
+                EngSetLastError(ERROR_INVALID_GW_COMMAND);
                 break;
     }
 
diff --git a/win32ss/user/user32/include/ntwrapper.h 
b/win32ss/user/user32/include/ntwrapper.h
index 67b67de6ed9..067077890ed 100644
--- a/win32ss/user/user32/include/ntwrapper.h
+++ b/win32ss/user/user32/include/ntwrapper.h
@@ -725,22 +725,22 @@ EXTINLINE VOID NtUserxNotifyWinEvent(HWND hWnd, PVOID ne)
 
 EXTINLINE DWORD NtUserxGetWindowContextHelpId(HWND hwnd)
 {
-    return NtUserCallHwnd(hwnd, HWND_ROUTINE_GETWNDCONTEXTHLPID);
+    return (DWORD)NtUserCallHwnd(hwnd, HWND_ROUTINE_GETWNDCONTEXTHLPID);
 }
 
 EXTINLINE BOOL NtUserxDeregisterShellHookWindow(HWND hWnd)
 {
-    return NtUserCallHwnd(hWnd, HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW);
+    return (BOOL)NtUserCallHwnd(hWnd, HWND_ROUTINE_DEREGISTERSHELLHOOKWINDOW);
 }
 
 EXTINLINE BOOL NtUserxRegisterShellHookWindow(HWND hWnd)
 {
-    return NtUserCallHwnd(hWnd, HWND_ROUTINE_REGISTERSHELLHOOKWINDOW);
+    return (BOOL)NtUserCallHwnd(hWnd, HWND_ROUTINE_REGISTERSHELLHOOKWINDOW);
 }
 
 EXTINLINE BOOL NtUserxSetMessageBox(HWND hWnd)
 {
-    return NtUserCallHwnd(hWnd, HWND_ROUTINE_SETMSGBOX);
+    return (BOOL)NtUserCallHwnd(hWnd, HWND_ROUTINE_SETMSGBOX);
 }
 
 EXTINLINE VOID NtUserxClearWindowState(PWND pWnd, UINT Flag)
diff --git a/win32ss/user/user32/windows/window.c 
b/win32ss/user/user32/windows/window.c
index dfe06a349c5..e7468f8a91c 100644
--- a/win32ss/user/user32/windows/window.c
+++ b/win32ss/user/user32/windows/window.c
@@ -1141,9 +1141,19 @@ GetWindow(HWND hWnd,
                     FoundWnd = DesktopPtrToUser(FoundWnd->spwndNext);
                 break;
 
+            case GW_ENABLEDPOPUP:
+            {
+                PWND pwndPopup = (PWND)NtUserCallHwnd(hWnd, 
HWND_ROUTINE_DWP_GETENABLEDPOPUP);
+                if (pwndPopup)
+                    FoundWnd = DesktopPtrToUser(pwndPopup);
+                break;
+            }
+
             default:
-                Wnd = NULL;
+            {
+                UserSetLastError(ERROR_INVALID_GW_COMMAND);
                 break;
+            }
         }
 
         if (FoundWnd != NULL)

Reply via email to