[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.
This commit is contained in:
Katayama Hirofumi MZ 2025-02-07 07:31:08 +09:00 committed by GitHub
parent 2d8a2944ba
commit 22577aed85
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 83 additions and 9 deletions

View file

@ -1670,7 +1670,7 @@ enum SimpleCallRoutines
TWOPARAM_ROUTINE_WOWCLEANUP
};
DWORD
DWORD_PTR
NTAPI
NtUserCallHwnd(
HWND hWnd,

View file

@ -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)
{

View file

@ -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;

View file

@ -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 **************/

View file

@ -428,7 +428,7 @@ IntGetWindow(HWND hWnd,
break;
default:
Wnd = NULL;
EngSetLastError(ERROR_INVALID_GW_COMMAND);
break;
}

View file

@ -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)

View file

@ -1141,9 +1141,19 @@ GetWindow(HWND hWnd,
FoundWnd = DesktopPtrToUser(FoundWnd->spwndNext);
break;
default:
Wnd = NULL;
case GW_ENABLEDPOPUP:
{
PWND pwndPopup = (PWND)NtUserCallHwnd(hWnd, HWND_ROUTINE_DWP_GETENABLEDPOPUP);
if (pwndPopup)
FoundWnd = DesktopPtrToUser(pwndPopup);
break;
}
default:
{
UserSetLastError(ERROR_INVALID_GW_COMMAND);
break;
}
}
if (FoundWnd != NULL)