Reactos

[SHELL32][SHDOCVW] Only forward menu messages to the correct shell extension (#7968)

Folder Marker 1.4 fails if it gets a WM_INITPOPUPMENU it does not expect.

CORE-17811

authored by

Whindmar Saksit and committed by
GitHub
53685ada 6bfb7924

+76 -80
+19 -1
dll/win32/shdocvw/CNSCBand.cpp
··· 973 973 } 974 974 }; 975 975 976 + static LRESULT CALLBACK MenuMessageForwarderWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 977 + { 978 + LRESULT ret = 0; 979 + IContextMenu *pCM = (IContextMenu*)GetWindowLongPtrW(hWnd, 0); 980 + if (uMsg == WM_DESTROY) 981 + SetWindowLongPtrW(hWnd, 0, 0); 982 + else if (pCM && SHForwardContextMenuMsg(pCM, uMsg, wParam, lParam, &ret, TRUE) == S_OK) 983 + return ret; 984 + return DefWindowProcW(hWnd, uMsg, wParam, lParam); 985 + } 986 + 976 987 // *** ATL event handlers *** 977 988 LRESULT CNSCBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 978 989 { ··· 1033 1044 return 0; 1034 1045 SHELL_RemoveVerb(contextMenu, idCmdFirst, menuTemp, L"link"); 1035 1046 1047 + HWND hWndWorker = SHCreateWorkerWindowW(MenuMessageForwarderWndProc, m_hWnd, 0, 1048 + WS_CHILD | WS_VISIBLE, NULL, 1049 + (LONG_PTR)static_cast<IContextMenu*>(contextMenu)); 1050 + HWND hWndMenuOwner = hWndWorker ? hWndWorker : m_hWnd; 1051 + 1036 1052 enum { flags = TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON }; 1037 - UINT uCommand = ::TrackPopupMenu(menuTemp, flags, pt.x, pt.y, 0, m_hWnd, NULL); 1053 + UINT uCommand = ::TrackPopupMenu(menuTemp, flags, pt.x, pt.y, 0, hWndMenuOwner, NULL); 1038 1054 if (uCommand) 1039 1055 { 1040 1056 uCommand -= idCmdFirst; ··· 1050 1066 1051 1067 hr = _ExecuteCommand(contextMenu, uCommand); 1052 1068 } 1069 + if (hWndWorker) 1070 + ::DestroyWindow(hWndWorker); 1053 1071 1054 1072 return TRUE; 1055 1073 }
+16 -27
dll/win32/shell32/CDefView.cpp
··· 141 141 } 142 142 ~MenuCleanup() 143 143 { 144 - if (m_hMenu) 145 - { 146 - DestroyMenu(m_hMenu); 147 - m_hMenu = NULL; 148 - } 149 144 if (m_pCM) 150 145 { 151 146 IUnknown_SetSite(m_pCM, NULL); 152 147 m_pCM.Release(); 148 + } 149 + if (m_hMenu) 150 + { 151 + DestroyMenu(m_hMenu); 152 + m_hMenu = NULL; 153 153 } 154 154 } 155 155 }; ··· 497 497 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 498 498 LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 499 499 LRESULT OnUpdateStatusbar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 500 - LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 500 + LRESULT OnMenuMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 501 501 LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 502 502 LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 503 503 LRESULT OnChangeCBChain(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); ··· 548 548 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify) 549 549 MESSAGE_HANDLER(SHV_UPDATESTATUSBAR, OnUpdateStatusbar) 550 550 MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) 551 - MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem) 552 - MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem) 551 + MESSAGE_HANDLER(WM_DRAWITEM, OnMenuMessage) 552 + MESSAGE_HANDLER(WM_MEASUREITEM, OnMenuMessage) 553 553 MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow) 554 554 MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) 555 555 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) ··· 3009 3009 return TRUE; 3010 3010 } 3011 3011 3012 - HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId); 3013 - HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId); 3014 - 3015 - LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 3012 + LRESULT CDefView::OnMenuMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 3016 3013 { 3017 3014 if (!m_pCM) 3018 3015 { ··· 3020 3017 ERR("no context menu\n"); 3021 3018 return FALSE; 3022 3019 } 3023 - 3024 - // lParam of WM_DRAWITEM WM_MEASUREITEM contains a menu id and 3025 - // this also needs to be changed to a menu identifier offset 3026 - UINT CmdID; 3027 - HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID); 3028 - if (SUCCEEDED(hres)) 3029 - SHSetMenuIdInMenuMsg(uMsg, lParam, CmdID - CONTEXT_MENU_BASE_ID); 3030 - 3031 - /* Forward the message to the IContextMenu2 */ 3032 - LRESULT result; 3033 - hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE); 3034 - 3035 - return (SUCCEEDED(hres)); 3020 + LRESULT result = 0; 3021 + HRESULT hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE); 3022 + return SUCCEEDED(hres); 3036 3023 } 3037 3024 3038 3025 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) ··· 3049 3036 { 3050 3037 HMENU hmenu = (HMENU) wParam; 3051 3038 int nPos = LOWORD(lParam); 3052 - UINT menuItemId; 3039 + UINT menuItemId; 3053 3040 3041 + if (m_isEditing) 3042 + ListView_CancelEditLabel(m_ListView); 3054 3043 if (m_pCM) 3055 - OnCustomItem(uMsg, wParam, lParam, bHandled); 3044 + OnMenuMessage(uMsg, wParam, lParam, bHandled); 3056 3045 3057 3046 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW); 3058 3047
+23 -45
dll/win32/shell32/CDefaultContextMenu.cpp
··· 157 157 UINT m_cKeys; 158 158 PIDLIST_ABSOLUTE m_pidlFolder; 159 159 DWORD m_bGroupPolicyActive; 160 + UINT m_iIdQCMFirst; /* The first id passed to us in QueryContextMenu */ 160 161 CAtlList<DynamicShellEntry> m_DynamicEntries; 161 162 UINT m_iIdSHEFirst; /* first used id */ 162 163 UINT m_iIdSHELast; /* last used id */ ··· 244 245 m_cKeys(NULL), 245 246 m_pidlFolder(NULL), 246 247 m_bGroupPolicyActive(0), 248 + m_iIdQCMFirst(0), 247 249 m_iIdSHEFirst(0), 248 250 m_iIdSHELast(0), 249 251 m_iIdSCMFirst(0), ··· 841 843 UINT uFlags) 842 844 { 843 845 HRESULT hr; 844 - UINT idCmdNext = idCmdFirst; 846 + UINT idCmdNext = m_iIdQCMFirst = idCmdFirst; 845 847 UINT cIds = 0; 846 848 847 849 TRACE("BuildShellItemContextMenu entered\n"); ··· 1536 1538 else 1537 1539 return E_INVALIDARG; 1538 1540 } 1539 - 1540 1541 CmdId = LOWORD(LocalInvokeInfo.lpVerb); 1541 1542 1542 1543 if (!m_DynamicEntries.IsEmpty() && CmdId >= m_iIdSHEFirst && CmdId < m_iIdSHELast) ··· 1726 1727 WPARAM wParam, 1727 1728 LPARAM lParam) 1728 1729 { 1729 - /* FIXME: Should we implement this as well? */ 1730 - return S_OK; 1730 + return HandleMenuMsg2(uMsg, wParam, lParam, NULL); 1731 1731 } 1732 1732 1733 1733 HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId) ··· 1744 1744 *CmdId = pMeasureStruct->itemID; 1745 1745 return S_OK; 1746 1746 } 1747 - 1748 - return E_FAIL; 1749 - } 1750 - 1751 - HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId) 1752 - { 1753 - if (uMsg == WM_DRAWITEM) 1754 - { 1755 - DRAWITEMSTRUCT* pDrawStruct = reinterpret_cast<DRAWITEMSTRUCT*>(lParam); 1756 - pDrawStruct->itemID = CmdId; 1757 - return S_OK; 1758 - } 1759 - else if (uMsg == WM_MEASUREITEM) 1760 - { 1761 - MEASUREITEMSTRUCT* pMeasureStruct = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam); 1762 - pMeasureStruct->itemID = CmdId; 1763 - return S_OK; 1764 - } 1765 - 1766 1747 return E_FAIL; 1767 1748 } 1768 1749 ··· 1774 1755 LPARAM lParam, 1775 1756 LRESULT *plResult) 1776 1757 { 1758 + if (!SHELL_IsContextMenuMsg(uMsg)) 1759 + return E_FAIL; 1760 + 1761 + UINT CmdId; 1777 1762 if (uMsg == WM_INITMENUPOPUP) 1778 1763 { 1779 - POSITION it = m_DynamicEntries.GetHeadPosition(); 1780 - while (it != NULL) 1781 - { 1782 - DynamicShellEntry& info = m_DynamicEntries.GetNext(it); 1783 - SHForwardContextMenuMsg(info.pCM, uMsg, wParam, lParam, plResult, TRUE); 1784 - } 1785 - return S_OK; 1764 + CmdId = GetMenuItemID((HMENU)wParam, 0); 1765 + if (CmdId == ~0ul) 1766 + return E_FAIL; 1786 1767 } 1787 - 1788 - UINT CmdId; 1789 - HRESULT hr = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdId); 1790 - if (FAILED(hr)) 1791 - return S_FALSE; 1792 - 1793 - if (CmdId < m_iIdSHEFirst || CmdId >= m_iIdSHELast) 1794 - return S_FALSE; 1795 - 1796 - CmdId -= m_iIdSHEFirst; 1797 - PDynamicShellEntry pEntry = GetDynamicEntry(CmdId); 1798 - if (pEntry) 1768 + else 1799 1769 { 1800 - SHSetMenuIdInMenuMsg(uMsg, lParam, CmdId - pEntry->iIdCmdFirst); 1801 - SHForwardContextMenuMsg(pEntry->pCM, uMsg, wParam, lParam, plResult, TRUE); 1770 + HRESULT hr = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdId); 1771 + if (FAILED(hr)) 1772 + return S_FALSE; 1802 1773 } 1774 + CmdId -= m_iIdQCMFirst; // Convert from Win32 id to our base 1803 1775 1804 - return S_OK; 1776 + if (CmdId >= m_iIdSHEFirst && CmdId < m_iIdSHELast) 1777 + { 1778 + if (PDynamicShellEntry pEntry = GetDynamicEntry(CmdId - m_iIdSHEFirst)) 1779 + return SHForwardContextMenuMsg(pEntry->pCM, uMsg, wParam, lParam, plResult, TRUE); 1780 + } 1781 + // TODO: _DoCallback(DFM_WM_*, ...) 1782 + return E_FAIL; 1805 1783 } 1806 1784 1807 1785 HRESULT
+5 -5
dll/win32/shell32/CNewMenu.cpp
··· 704 704 WINAPI 705 705 CNewMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) 706 706 { 707 - return S_OK; 707 + return HandleMenuMsg2(uMsg, wParam, lParam, NULL); 708 708 } 709 709 710 710 HRESULT ··· 734 734 if (!lpdis || lpdis->CtlType != ODT_MENU) 735 735 break; 736 736 737 - DWORD id = LOWORD(lpdis->itemID); 737 + DWORD id = lpdis->itemID; 738 738 HICON hIcon = NULL; 739 - if (m_idCmdFirst + id == m_idCmdFolder) 739 + if (id == m_idCmdFolder) 740 740 { 741 741 hIcon = m_hIconFolder; 742 742 } 743 - else if (m_idCmdFirst + id == m_idCmdLink) 743 + else if (id == m_idCmdLink) 744 744 { 745 745 hIcon = m_hIconLink; 746 746 } 747 747 else 748 748 { 749 - SHELLNEW_ITEM *pItem = FindItemFromIdOffset(id); 749 + SHELLNEW_ITEM *pItem = FindItemFromIdOffset(id - m_idCmdFirst); 750 750 if (pItem) 751 751 hIcon = pItem->hIcon; 752 752 }
+1 -1
dll/win32/shell32/brfolder.cpp
··· 1337 1337 if (!info) 1338 1338 return 0; 1339 1339 1340 - if (info->pContextMenu) 1340 + if (info->pContextMenu && SHELL_IsContextMenuMsg(uMsg)) 1341 1341 { 1342 1342 LRESULT result; 1343 1343 if (SHForwardContextMenuMsg(info->pContextMenu, uMsg, wParam,
+6 -1
dll/win32/shlwapi/rosordinal.c
··· 15 15 IContextMenu3* pcmenu3; 16 16 IContextMenu2* pcmenu2; 17 17 18 + if (!pUnk) 19 + return E_FAIL; 20 + 18 21 /* First try to use the IContextMenu3 interface */ 19 22 hr = IUnknown_QueryInterface(pUnk, &IID_IContextMenu3, (void**)&pcmenu3); 20 23 if (SUCCEEDED(hr)) ··· 35 38 36 39 hr = IContextMenu2_HandleMenuMsg(pcmenu2, uMsg, wParam, lParam); 37 40 IContextMenu2_Release(pcmenu2); 38 - return hr; 41 + if (pResult) 42 + *pResult = 0; 43 + return hr == S_OK ? S_FALSE : hr; 39 44 } 40 45 41 46 /* http://undoc.airesoft.co.uk/shlwapi.dll/SHAreIconsEqual.php */
+6
sdk/include/reactos/shellutils.h
··· 635 635 #define SEE_CMIC_COMMON_FLAGS (SEE_CMIC_COMMON_BASICFLAGS | SEE_MASK_HOTKEY | SEE_MASK_ICON | \ 636 636 SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE) 637 637 638 + static inline BOOL SHELL_IsContextMenuMsg(UINT uMsg) 639 + { 640 + return uMsg == WM_MEASUREITEM || uMsg == WM_DRAWITEM || 641 + uMsg == WM_INITMENUPOPUP || uMsg == WM_MENUSELECT || uMsg == WM_MENUCHAR; 642 + } 643 + 638 644 static inline BOOL ILIsSingle(LPCITEMIDLIST pidl) 639 645 { 640 646 return pidl == ILFindLastID(pidl);