shell32: Use a smaller range of shellview menu IDs in our IContextMenu functions.

The shellview menu IDs are very large, eg. FCIDM_SHVIEW_OPEN is 0x7102,
while applications want menu IDs to fit into a small range, eg. 1-1000 for
Explorer++. This causes our IContextMenu_QueryContextMenu() functions to
leave out most menu options. We should rebase our shellview menu ids
by -0x7000 so they occupy a smaller range.

This gets both Explorer++ and Double Commander to show the correct
right-click menus.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=24893
Signed-off-by: Damjan Jovanovic <damjan.jov@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
(cherry picked from commit 2b6458b757)
Signed-off-by: Michael Stefaniuc <mstefani@winehq.org>
This commit is contained in:
Damjan Jovanovic 2021-04-30 07:39:24 +02:00 committed by Michael Stefaniuc
parent 3b90fc2314
commit df085a31ff
2 changed files with 54 additions and 11 deletions

View File

@ -45,6 +45,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell); WINE_DEFAULT_DEBUG_CHANNEL(shell);
#define FCIDM_BASE 0x7000
typedef struct typedef struct
{ {
IContextMenu3 IContextMenu3_iface; IContextMenu3 IContextMenu3_iface;
@ -142,6 +144,37 @@ static ULONG WINAPI ContextMenu_Release(IContextMenu3 *iface)
return ref; return ref;
} }
static UINT max_menu_id(HMENU hmenu, UINT offset, UINT last)
{
int i;
UINT max_id = 0;
for (i = GetMenuItemCount(hmenu) - 1; i >= 0; i--)
{
MENUITEMINFOW item;
memset(&item, 0, sizeof(MENUITEMINFOW));
item.cbSize = sizeof(MENUITEMINFOW);
item.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_TYPE;
if (!GetMenuItemInfoW(hmenu, i, TRUE, &item))
continue;
if (!(item.fType & MFT_SEPARATOR))
{
if (item.hSubMenu)
{
UINT submenu_max_id = max_menu_id(item.hSubMenu, offset, last);
if (max_id < submenu_max_id)
max_id = submenu_max_id;
}
if (item.wID + offset <= last)
{
if (max_id <= item.wID + offset)
max_id = item.wID + offset + 1;
}
}
}
return max_id;
}
static HRESULT WINAPI ItemMenu_QueryContextMenu( static HRESULT WINAPI ItemMenu_QueryContextMenu(
IContextMenu3 *iface, IContextMenu3 *iface,
HMENU hmenu, HMENU hmenu,
@ -162,7 +195,8 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
if(uFlags & CMF_EXPLORE) if(uFlags & CMF_EXPLORE)
RemoveMenu(hmenures, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND); RemoveMenu(hmenures, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
uIDMax = Shell_MergeMenus(hmenu, GetSubMenu(hmenures, 0), indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS); Shell_MergeMenus(hmenu, GetSubMenu(hmenures, 0), indexMenu, idCmdFirst - FCIDM_BASE, idCmdLast, MM_SUBMENUSHAVEIDS);
uIDMax = max_menu_id(GetSubMenu(hmenures, 0), idCmdFirst - FCIDM_BASE, idCmdLast);
DestroyMenu(hmenures); DestroyMenu(hmenures);
@ -174,14 +208,14 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
mi.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE; mi.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE;
mi.dwTypeData = str; mi.dwTypeData = str;
mi.cch = 255; mi.cch = 255;
GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE + idCmdFirst, MF_BYCOMMAND, &mi); GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND, &mi);
RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE + idCmdFirst, MF_BYCOMMAND); RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND);
mi.cbSize = sizeof(mi); mi.cbSize = sizeof(mi);
mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_STRING; mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_STRING;
mi.dwTypeData = str; mi.dwTypeData = str;
mi.fState = MFS_ENABLED; mi.fState = MFS_ENABLED;
mi.wID = FCIDM_SHVIEW_EXPLORE + idCmdFirst; mi.wID = FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst;
mi.fType = MFT_STRING; mi.fType = MFT_STRING;
InsertMenuItemW(hmenu, (uFlags & CMF_EXPLORE) ? 1 : 2, MF_BYPOSITION, &mi); InsertMenuItemW(hmenu, (uFlags & CMF_EXPLORE) ? 1 : 2, MF_BYPOSITION, &mi);
} }
@ -189,7 +223,7 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION); SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION);
if(uFlags & ~CMF_CANRENAME) if(uFlags & ~CMF_CANRENAME)
RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME + idCmdFirst, MF_BYCOMMAND); RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND);
else else
{ {
UINT enable = MF_BYCOMMAND; UINT enable = MF_BYCOMMAND;
@ -205,7 +239,7 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
enable |= (attr & SFGAO_CANRENAME) ? MFS_ENABLED : MFS_DISABLED; enable |= (attr & SFGAO_CANRENAME) ? MFS_ENABLED : MFS_DISABLED;
} }
EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME + idCmdFirst, enable); EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME - FCIDM_BASE + idCmdFirst, enable);
} }
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, uIDMax-idCmdFirst); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, uIDMax-idCmdFirst);
@ -738,7 +772,7 @@ static HRESULT WINAPI ItemMenu_InvokeCommand(
if (IS_INTRESOURCE(lpcmi->lpVerb)) if (IS_INTRESOURCE(lpcmi->lpVerb))
{ {
switch(LOWORD(lpcmi->lpVerb)) switch(LOWORD(lpcmi->lpVerb) + FCIDM_BASE)
{ {
case FCIDM_SHVIEW_EXPLORE: case FCIDM_SHVIEW_EXPLORE:
TRACE("Verb FCIDM_SHVIEW_EXPLORE\n"); TRACE("Verb FCIDM_SHVIEW_EXPLORE\n");
@ -830,7 +864,7 @@ static HRESULT WINAPI ItemMenu_GetCommandString(IContextMenu3 *iface, UINT_PTR c
case GCS_VERBA: case GCS_VERBA:
case GCS_VERBW: case GCS_VERBW:
switch (cmdid) switch (cmdid + FCIDM_BASE)
{ {
case FCIDM_SHVIEW_OPEN: case FCIDM_SHVIEW_OPEN:
cmdW = openW; cmdW = openW;
@ -1059,8 +1093,9 @@ static HRESULT WINAPI BackgroundMenu_QueryContextMenu(
} }
else else
{ {
idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu, Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS); idCmdFirst - FCIDM_BASE, idCmdLast, MM_SUBMENUSHAVEIDS);
idMax = max_menu_id(GetSubMenu(hMyMenu, 0), idCmdFirst - FCIDM_BASE, idCmdLast);
hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst); hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst);
} }
DestroyMenu(hMyMenu); DestroyMenu(hMyMenu);
@ -1228,7 +1263,7 @@ static HRESULT WINAPI BackgroundMenu_InvokeCommand(
} }
else else
{ {
switch (LOWORD(lpcmi->lpVerb)) switch (LOWORD(lpcmi->lpVerb) + FCIDM_BASE)
{ {
case FCIDM_SHVIEW_REFRESH: case FCIDM_SHVIEW_REFRESH:
if (view) IShellView_Refresh(view); if (view) IShellView_Refresh(view);

View File

@ -4385,7 +4385,15 @@ static void test_contextmenu(IContextMenu *menu, BOOL background)
ok(hr == S_OK || hr == E_NOTIMPL || hr == E_INVALIDARG, ok(hr == S_OK || hr == E_NOTIMPL || hr == E_INVALIDARG,
"Got unexpected hr %#x for ID %d, string %s.\n", hr, mii.wID, debugstr_a(mii.dwTypeData)); "Got unexpected hr %#x for ID %d, string %s.\n", hr, mii.wID, debugstr_a(mii.dwTypeData));
if (hr == S_OK) if (hr == S_OK)
{
trace("Got ID %d, verb %s, string %s.\n", mii.wID, debugstr_a(buf), debugstr_a(mii.dwTypeData)); trace("Got ID %d, verb %s, string %s.\n", mii.wID, debugstr_a(buf), debugstr_a(mii.dwTypeData));
if (!strcmp(buf, "copy"))
ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_COPY, "wrong menu wID %d\n", mii.wID);
else if (!strcmp(buf, "paste"))
ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_INSERT, "wrong menu wID %d\n", mii.wID);
else if (!strcmp(buf, "properties"))
ok(mii.wID == 64 - 0x7000 + FCIDM_SHVIEW_PROPERTIES, "wrong menu wID %d\n", mii.wID);
}
else else
trace("Got ID %d, hr %#x, string %s.\n", mii.wID, hr, debugstr_a(mii.dwTypeData)); trace("Got ID %d, hr %#x, string %s.\n", mii.wID, hr, debugstr_a(mii.dwTypeData));
} }