https://git.reactos.org/?p=reactos.git;a=commitdiff;h=22577aed85f91b33a25c8…
commit 22577aed85f91b33a25c89ad857951ddb8e1a988
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Fri Feb 7 07:31:08 2025 +0900
Commit: GitHub <noreply(a)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)