Skip to content

Commit 53685ad

Browse files
authored
[SHELL32][SHDOCVW] Only forward menu messages to the correct shell extension (reactos#7968)
Folder Marker 1.4 fails if it gets a WM_INITPOPUPMENU it does not expect. CORE-17811
1 parent 6bfb792 commit 53685ad

File tree

7 files changed

+76
-80
lines changed

7 files changed

+76
-80
lines changed

dll/win32/shdocvw/CNSCBand.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,17 @@ struct CMenuTemp
973973
}
974974
};
975975

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+
976987
// *** ATL event handlers ***
977988
LRESULT CNSCBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
978989
{
@@ -1033,8 +1044,13 @@ LRESULT CNSCBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
10331044
return 0;
10341045
SHELL_RemoveVerb(contextMenu, idCmdFirst, menuTemp, L"link");
10351046

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+
10361052
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);
10381054
if (uCommand)
10391055
{
10401056
uCommand -= idCmdFirst;
@@ -1050,6 +1066,8 @@ LRESULT CNSCBand::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
10501066

10511067
hr = _ExecuteCommand(contextMenu, uCommand);
10521068
}
1069+
if (hWndWorker)
1070+
::DestroyWindow(hWndWorker);
10531071

10541072
return TRUE;
10551073
}

dll/win32/shell32/CDefView.cpp

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,16 @@ struct MenuCleanup
141141
}
142142
~MenuCleanup()
143143
{
144-
if (m_hMenu)
145-
{
146-
DestroyMenu(m_hMenu);
147-
m_hMenu = NULL;
148-
}
149144
if (m_pCM)
150145
{
151146
IUnknown_SetSite(m_pCM, NULL);
152147
m_pCM.Release();
153148
}
149+
if (m_hMenu)
150+
{
151+
DestroyMenu(m_hMenu);
152+
m_hMenu = NULL;
153+
}
154154
}
155155
};
156156

@@ -497,7 +497,7 @@ class CDefView :
497497
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
498498
LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
499499
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);
501501
LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
502502
LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
503503
LRESULT OnChangeCBChain(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
@@ -548,8 +548,8 @@ class CDefView :
548548
MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify)
549549
MESSAGE_HANDLER(SHV_UPDATESTATUSBAR, OnUpdateStatusbar)
550550
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)
553553
MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow)
554554
MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
555555
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
@@ -3009,30 +3009,17 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &
30093009
return TRUE;
30103010
}
30113011

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)
30163013
{
30173014
if (!m_pCM)
30183015
{
30193016
/* no menu */
30203017
ERR("no context menu\n");
30213018
return FALSE;
30223019
}
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);
30363023
}
30373024

30383025
LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
@@ -3049,10 +3036,12 @@ LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
30493036
{
30503037
HMENU hmenu = (HMENU) wParam;
30513038
int nPos = LOWORD(lParam);
3052-
UINT menuItemId;
3039+
UINT menuItemId;
30533040

3041+
if (m_isEditing)
3042+
ListView_CancelEditLabel(m_ListView);
30543043
if (m_pCM)
3055-
OnCustomItem(uMsg, wParam, lParam, bHandled);
3044+
OnMenuMessage(uMsg, wParam, lParam, bHandled);
30563045

30573046
HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
30583047

dll/win32/shell32/CDefaultContextMenu.cpp

Lines changed: 23 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ class CDefaultContextMenu :
157157
UINT m_cKeys;
158158
PIDLIST_ABSOLUTE m_pidlFolder;
159159
DWORD m_bGroupPolicyActive;
160+
UINT m_iIdQCMFirst; /* The first id passed to us in QueryContextMenu */
160161
CAtlList<DynamicShellEntry> m_DynamicEntries;
161162
UINT m_iIdSHEFirst; /* first used id */
162163
UINT m_iIdSHELast; /* last used id */
@@ -244,6 +245,7 @@ CDefaultContextMenu::CDefaultContextMenu() :
244245
m_cKeys(NULL),
245246
m_pidlFolder(NULL),
246247
m_bGroupPolicyActive(0),
248+
m_iIdQCMFirst(0),
247249
m_iIdSHEFirst(0),
248250
m_iIdSHELast(0),
249251
m_iIdSCMFirst(0),
@@ -841,7 +843,7 @@ CDefaultContextMenu::QueryContextMenu(
841843
UINT uFlags)
842844
{
843845
HRESULT hr;
844-
UINT idCmdNext = idCmdFirst;
846+
UINT idCmdNext = m_iIdQCMFirst = idCmdFirst;
845847
UINT cIds = 0;
846848

847849
TRACE("BuildShellItemContextMenu entered\n");
@@ -1536,7 +1538,6 @@ CDefaultContextMenu::InvokeCommand(
15361538
else
15371539
return E_INVALIDARG;
15381540
}
1539-
15401541
CmdId = LOWORD(LocalInvokeInfo.lpVerb);
15411542

15421543
if (!m_DynamicEntries.IsEmpty() && CmdId >= m_iIdSHEFirst && CmdId < m_iIdSHELast)
@@ -1726,8 +1727,7 @@ CDefaultContextMenu::HandleMenuMsg(
17261727
WPARAM wParam,
17271728
LPARAM lParam)
17281729
{
1729-
/* FIXME: Should we implement this as well? */
1730-
return S_OK;
1730+
return HandleMenuMsg2(uMsg, wParam, lParam, NULL);
17311731
}
17321732

17331733
HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId)
@@ -1744,25 +1744,6 @@ HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId)
17441744
*CmdId = pMeasureStruct->itemID;
17451745
return S_OK;
17461746
}
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-
17661747
return E_FAIL;
17671748
}
17681749

@@ -1774,34 +1755,31 @@ CDefaultContextMenu::HandleMenuMsg2(
17741755
LPARAM lParam,
17751756
LRESULT *plResult)
17761757
{
1758+
if (!SHELL_IsContextMenuMsg(uMsg))
1759+
return E_FAIL;
1760+
1761+
UINT CmdId;
17771762
if (uMsg == WM_INITMENUPOPUP)
17781763
{
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;
17861767
}
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
17991769
{
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;
18021773
}
1774+
CmdId -= m_iIdQCMFirst; // Convert from Win32 id to our base
18031775

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;
18051783
}
18061784

18071785
HRESULT

dll/win32/shell32/CNewMenu.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ HRESULT
704704
WINAPI
705705
CNewMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
706706
{
707-
return S_OK;
707+
return HandleMenuMsg2(uMsg, wParam, lParam, NULL);
708708
}
709709

710710
HRESULT
@@ -734,19 +734,19 @@ CNewMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plRes
734734
if (!lpdis || lpdis->CtlType != ODT_MENU)
735735
break;
736736

737-
DWORD id = LOWORD(lpdis->itemID);
737+
DWORD id = lpdis->itemID;
738738
HICON hIcon = NULL;
739-
if (m_idCmdFirst + id == m_idCmdFolder)
739+
if (id == m_idCmdFolder)
740740
{
741741
hIcon = m_hIconFolder;
742742
}
743-
else if (m_idCmdFirst + id == m_idCmdLink)
743+
else if (id == m_idCmdLink)
744744
{
745745
hIcon = m_hIconLink;
746746
}
747747
else
748748
{
749-
SHELLNEW_ITEM *pItem = FindItemFromIdOffset(id);
749+
SHELLNEW_ITEM *pItem = FindItemFromIdOffset(id - m_idCmdFirst);
750750
if (pItem)
751751
hIcon = pItem->hIcon;
752752
}

dll/win32/shell32/brfolder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,7 @@ BrFolderDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
13371337
if (!info)
13381338
return 0;
13391339

1340-
if (info->pContextMenu)
1340+
if (info->pContextMenu && SHELL_IsContextMenuMsg(uMsg))
13411341
{
13421342
LRESULT result;
13431343
if (SHForwardContextMenuMsg(info->pContextMenu, uMsg, wParam,

dll/win32/shlwapi/rosordinal.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ HRESULT WINAPI SHForwardContextMenuMsg(IUnknown* pUnk, UINT uMsg, WPARAM wParam,
1515
IContextMenu3* pcmenu3;
1616
IContextMenu2* pcmenu2;
1717

18+
if (!pUnk)
19+
return E_FAIL;
20+
1821
/* First try to use the IContextMenu3 interface */
1922
hr = IUnknown_QueryInterface(pUnk, &IID_IContextMenu3, (void**)&pcmenu3);
2023
if (SUCCEEDED(hr))
@@ -35,7 +38,9 @@ HRESULT WINAPI SHForwardContextMenuMsg(IUnknown* pUnk, UINT uMsg, WPARAM wParam,
3538

3639
hr = IContextMenu2_HandleMenuMsg(pcmenu2, uMsg, wParam, lParam);
3740
IContextMenu2_Release(pcmenu2);
38-
return hr;
41+
if (pResult)
42+
*pResult = 0;
43+
return hr == S_OK ? S_FALSE : hr;
3944
}
4045

4146
/* http://undoc.airesoft.co.uk/shlwapi.dll/SHAreIconsEqual.php */

sdk/include/reactos/shellutils.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,12 @@ typedef CCoInitBase<OleInitialize, OleUninitialize> COleInit;
635635
#define SEE_CMIC_COMMON_FLAGS (SEE_CMIC_COMMON_BASICFLAGS | SEE_MASK_HOTKEY | SEE_MASK_ICON | \
636636
SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE)
637637

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+
638644
static inline BOOL ILIsSingle(LPCITEMIDLIST pidl)
639645
{
640646
return pidl == ILFindLastID(pidl);

0 commit comments

Comments
 (0)