From 3a96c90c54aa49136ac0f3bae81a497ffc6da8c0 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Thu, 19 Jun 2025 22:59:27 +0900 Subject: [PATCH] [NTUSER][USER32] Re-implement WM_POPUPSYSTEMMENU message (#8144) This PR resolves a bug of #8094. #8094 correctly validates the flags. TPM_SYSTEM_MENU is an internal flag and not a valid flag for TrackPopupMenu. Thus, calling TrackPopupMenu.TPM_SYSTEM_MENU in User32DefWindowProc was wrong. This caused failure of taskbar context menu. JIRA issue: CORE-20238 - Move WM_POPUPSYSTEMMENU message handling of user32 into win32k.sys!IntDefWindowProc. - Use win32k.sys!IntTrackPopupMenuEx instead of user32!TrackPopupMenu in handling of WM_POPUPSYSTEMMENU. --- win32ss/user/ntuser/defwnd.c | 57 ++++++++++++++++++++++++++++ win32ss/user/user32/windows/defwnd.c | 16 +------- 2 files changed, 58 insertions(+), 15 deletions(-) diff --git a/win32ss/user/ntuser/defwnd.c b/win32ss/user/ntuser/defwnd.c index dba5c7b567b..77b8235b005 100644 --- a/win32ss/user/ntuser/defwnd.c +++ b/win32ss/user/ntuser/defwnd.c @@ -580,6 +580,57 @@ DefWndScreenshot(PWND pWnd) UserCloseClipboard(); } +// WM_POPUPSYSTEMMENU +static BOOL +co_UserTrackSystemMenu(_In_ PWND pWnd, _In_ LONG nClickPos, _In_opt_ PUINT puCmdType) +{ + USER_REFERENCE_ENTRY MenuRef, WndRef; + PMENU pMenu; + UINT uDefaultCmd; + + FIXME("co_UserTrackSystemMenu() called\n"); // Useful trace, while working on CORE-3247 + + UserRefObjectCo(pWnd, &WndRef); + + // Check style and make window foreground + if ((pWnd->style & WS_DISABLED) || + (pWnd->state2 & WNDS2_INDESTROY) || + (pWnd->head.pti->MessageQueue != gpqForeground && !co_IntSetForegroundWindow(pWnd))) + { + UserDerefObjectCo(pWnd); + return FALSE; + } + + // Get the window's system menu + pMenu = IntGetSystemMenu(pWnd, FALSE); + if (!pMenu) + { + UserDerefObjectCo(pWnd); + return FALSE; + } + UserRefObjectCo(pMenu, &MenuRef); + + // Set default menu item + if (puCmdType) + uDefaultCmd = *puCmdType; + else if (pWnd->style & (WS_MINIMIZE | WS_MAXIMIZE)) + uDefaultCmd = SC_RESTORE; + else + uDefaultCmd = SC_MAXIMIZE; + UserSetMenuDefaultItem(pMenu, uDefaultCmd, FALSE); + + if (nClickPos == -1) // Input from keyboard? + FIXME("Use WM_KLUDGEMINRECT and TPM_VERTICAL\n"); + + // Show the menu and wait for menu tracking ending + IntTrackPopupMenuEx(pMenu, TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_SYSTEM_MENU, + LOWORD(nClickPos), HIWORD(nClickPos), pWnd, NULL); + + UserDerefObjectCo(pMenu); + UserDerefObjectCo(pWnd); + return TRUE; +} + /* Win32k counterpart of User DefWindowProc */ @@ -697,6 +748,12 @@ IntDefWindowProc( UserDerefObjectCo(Wnd->spwndParent); break; + case WM_POPUPSYSTEMMENU: + /* This is an undocumented message used by the windows taskbar to + display the system menu of windows that belong to other processes. */ + co_UserTrackSystemMenu(Wnd, (LONG)lParam, NULL); + break; + case WM_KEYF1: { HELPINFO hi; diff --git a/win32ss/user/user32/windows/defwnd.c b/win32ss/user/user32/windows/defwnd.c index 70dad210604..f7a68fd84bb 100644 --- a/win32ss/user/user32/windows/defwnd.c +++ b/win32ss/user/user32/windows/defwnd.c @@ -327,21 +327,6 @@ User32DefWindowProc(HWND hWnd, case WM_DEVICECHANGE: return TRUE; - case WM_POPUPSYSTEMMENU: - { - /* This is an undocumented message used by the windows taskbar to - display the system menu of windows that belong to other processes. */ - HMENU menu = GetSystemMenu(hWnd, FALSE); - ERR("WM_POPUPSYSTEMMENU\n"); - if (menu) - { - SetForegroundWindow(hWnd); - TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_SYSTEM_MENU, - LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL); - } - return 0; - } - case WM_RBUTTONUP: { POINT Pt; @@ -798,6 +783,7 @@ User32DefWindowProc(HWND hWnd, case WM_WINDOWPOSCHANGED: case WM_APPCOMMAND: case WM_SETCURSOR: + case WM_POPUPSYSTEMMENU: GoSS: { LRESULT lResult;