From 9e1f2b035ff68781d62e1ab14d31168a957e37bb Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Fri, 16 May 2025 19:41:01 +0900 Subject: [PATCH] [NTUSER][USER32] Rewrite GetAncestor (#7978) JIRA issue: N/A - Set the last error. - Check message window. - Modify user32.spec. --- win32ss/include/ntuser.h | 4 +- win32ss/user/ntuser/window.c | 145 +++++++++++++-------------- win32ss/user/user32/user32.spec | 2 +- win32ss/user/user32/windows/window.c | 56 ++++------- 4 files changed, 97 insertions(+), 110 deletions(-) diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index 783d4e0c32a..fab334c37f2 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -2138,8 +2138,8 @@ NtUserGetAltTabInfo( HWND NTAPI NtUserGetAncestor( - HWND hWnd, - UINT Flags); + _In_ HWND hWnd, + _In_ UINT uType); DWORD NTAPI diff --git a/win32ss/user/ntuser/window.c b/win32ss/user/ntuser/window.c index fe9c8fc2a61..798ff977391 100644 --- a/win32ss/user/ntuser/window.c +++ b/win32ss/user/ntuser/window.c @@ -3351,99 +3351,98 @@ Exit: return Ret; } - -/* - * @implemented - */ -PWND FASTCALL UserGetAncestor(PWND Wnd, UINT Type) +/* @implemented */ +PWND FASTCALL +UserGetAncestor(_In_ PWND pWnd, _In_ UINT uType) { - PWND WndAncestor, Parent; + PWND WndAncestor, Parent, pwndMessage; + PDESKTOP pDesktop; + PWND pwndDesktop; - if (UserHMGetHandle(Wnd) == IntGetDesktopWindow()) - { - return NULL; - } + pDesktop = pWnd->head.rpdesk; + ASSERT(pDesktop); + ASSERT(pDesktop->pDeskInfo); - switch (Type) - { - case GA_PARENT: - { - WndAncestor = Wnd->spwndParent; - break; - } + pwndDesktop = pDesktop->pDeskInfo->spwnd; + if (pWnd == pwndDesktop) + return NULL; - case GA_ROOT: - { - WndAncestor = Wnd; - Parent = NULL; + pwndMessage = pDesktop->spwndMessage; + if (pWnd == pwndMessage) + return NULL; - for(;;) + Parent = pWnd->spwndParent; + if (!Parent) + return NULL; + + switch (uType) + { + case GA_PARENT: + return Parent; + + case GA_ROOT: + WndAncestor = pWnd; + if (Parent == pwndDesktop) + break; + + do { - if(!(Parent = WndAncestor->spwndParent)) - { - break; - } - if(IntIsDesktopWindow(Parent)) - { - break; - } + if (Parent == pwndMessage) + break; - WndAncestor = Parent; + WndAncestor = Parent; + + pDesktop = Parent->head.rpdesk; + ASSERT(pDesktop); + ASSERT(pDesktop->pDeskInfo); + + Parent = Parent->spwndParent; + } while (Parent != pDesktop->pDeskInfo->spwnd); + break; + + case GA_ROOTOWNER: + WndAncestor = pWnd; + for (PWND pwndNode = IntGetParent(pWnd); pwndNode; pwndNode = IntGetParent(pwndNode)) + { + WndAncestor = pwndNode; } break; - } - case GA_ROOTOWNER: - { - WndAncestor = Wnd; - - for (;;) - { - Parent = IntGetParent(WndAncestor); - - if (!Parent) - { - break; - } - - WndAncestor = Parent; - } - break; - } - - default: - { + default: return NULL; - } - } + } - return WndAncestor; + return WndAncestor; } -/* - * @implemented - */ +/* @implemented */ HWND APIENTRY -NtUserGetAncestor(HWND hWnd, UINT Type) +NtUserGetAncestor(_In_ HWND hWnd, _In_ UINT uType) { - PWND Window, Ancestor; - HWND Ret = NULL; + PWND Window, pwndAncestor; + HWND hwndAncestor = NULL; - TRACE("Enter NtUserGetAncestor\n"); - UserEnterExclusive(); + TRACE("Enter NtUserGetAncestor\n"); + UserEnterShared(); - Window = UserGetWindowObject(hWnd); - if (Window) - { - Ancestor = UserGetAncestor(Window, Type); - /* fixme: can UserGetAncestor ever return NULL for a valid window? */ + Window = UserGetWindowObject(hWnd); + if (!Window) + goto Quit; - Ret = (Ancestor ? UserHMGetHandle(Ancestor) : NULL); - } + if (!uType || uType > GA_ROOTOWNER) + { + EngSetLastError(ERROR_INVALID_PARAMETER); + goto Quit; + } - TRACE("Leave NtUserGetAncestor, ret=%p\n", Ret); - UserLeave(); - return Ret; + pwndAncestor = UserGetAncestor(Window, uType); + if (pwndAncestor) + hwndAncestor = UserHMGetHandle(pwndAncestor); + +Quit: + UserLeave(); + TRACE("Leave NtUserGetAncestor returning %p\n", hwndAncestor); + return hwndAncestor; } //// diff --git a/win32ss/user/user32/user32.spec b/win32ss/user/user32/user32.spec index 5b52db15f55..4423f96312b 100644 --- a/win32ss/user/user32/user32.spec +++ b/win32ss/user/user32/user32.spec @@ -249,7 +249,7 @@ @ stdcall GetAltTabInfo(long long ptr ptr long) GetAltTabInfoA @ stdcall GetAltTabInfoA(long long ptr ptr long) @ stdcall GetAltTabInfoW(long long ptr ptr long) -@ stdcall GetAncestor(long long) ; Direct call NtUserGetAncestor +@ stdcall GetAncestor(ptr long) ; Direct call NtUserGetAncestor @ stdcall GetAppCompatFlags(long) @ stdcall GetAppCompatFlags2(long) @ stdcall GetAsyncKeyState(long) diff --git a/win32ss/user/user32/windows/window.c b/win32ss/user/user32/windows/window.c index e7468f8a91c..e57838dbd09 100644 --- a/win32ss/user/user32/windows/window.c +++ b/win32ss/user/user32/windows/window.c @@ -924,52 +924,40 @@ GetAltTabInfoW(HWND hwnd, return NtUserGetAltTabInfo(hwnd,iItem,pati,pszItemText,cchItemText,FALSE); } - -/* - * @implemented - */ +/* @implemented */ HWND WINAPI -GetAncestor(HWND hwnd, UINT gaFlags) +GetAncestor(_In_ HWND hwnd, _In_ UINT uType) { - HWND Ret = NULL; - PWND Ancestor, Wnd; - - Wnd = ValidateHwnd(hwnd); - if (!Wnd) + PWND pWnd = ValidateHwnd(hwnd); + if (!pWnd || pWnd == GetThreadDesktopWnd()) return NULL; - _SEH2_TRY + /* Special handling optimized for speed */ + if (uType == GA_PARENT) { - Ancestor = NULL; - switch (gaFlags) + HWND hwndAncestor = NULL; + + _SEH2_TRY { - case GA_PARENT: - if (Wnd->spwndParent != NULL) - Ancestor = DesktopPtrToUser(Wnd->spwndParent); - break; - - default: - /* FIXME: Call win32k for now */ - Wnd = NULL; - break; + if (pWnd->spwndParent && pWnd->fnid != FNID_MESSAGEWND) + { + PWND pwndAncestor = DesktopPtrToUser(pWnd->spwndParent); + if (pwndAncestor) + hwndAncestor = UserHMGetHandle(pwndAncestor); + } } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Do nothing */ + } + _SEH2_END; - if (Ancestor != NULL) - Ret = UserHMGetHandle(Ancestor); + return hwndAncestor; } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* Do nothing */ - } - _SEH2_END; - if (!Wnd) /* Fall back */ - Ret = NtUserGetAncestor(hwnd, gaFlags); - - return Ret; + return NtUserGetAncestor(hwnd, uType); } - /* * @implemented */