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

Alexandre Julliard julliard at winehq.org
Fri Apr 30 16:03:28 CDT 2021


Module: wine
Branch: master
Commit: 2b6458b75713cedc6cd28d2980298d6ac844757e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=2b6458b75713cedc6cd28d2980298d6ac844757e

Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date:   Fri Apr 30 07:39:24 2021 +0200

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 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/shell32/shlview_cmenu.c   | 57 ++++++++++++++++++++++++++++++++++--------
 dlls/shell32/tests/shlfolder.c |  8 ++++++
 2 files changed, 54 insertions(+), 11 deletions(-)

diff --git a/dlls/shell32/shlview_cmenu.c b/dlls/shell32/shlview_cmenu.c
index 351d1e5d141..e7c1cf16e10 100644
--- a/dlls/shell32/shlview_cmenu.c
+++ b/dlls/shell32/shlview_cmenu.c
@@ -45,6 +45,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
+#define FCIDM_BASE 0x7000
+
 typedef struct
 {
     IContextMenu3 IContextMenu3_iface;
@@ -142,6 +144,37 @@ static ULONG WINAPI ContextMenu_Release(IContextMenu3 *iface)
     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(
 	IContextMenu3 *iface,
 	HMENU hmenu,
@@ -162,7 +195,8 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
         if(uFlags & CMF_EXPLORE)
             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);
 
@@ -174,14 +208,14 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
             mi.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE;
             mi.dwTypeData = str;
             mi.cch = 255;
-            GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE + idCmdFirst, MF_BYCOMMAND, &mi);
-            RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE + idCmdFirst, MF_BYCOMMAND);
+            GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND, &mi);
+            RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND);
 
             mi.cbSize = sizeof(mi);
             mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_STRING;
             mi.dwTypeData = str;
             mi.fState = MFS_ENABLED;
-            mi.wID = FCIDM_SHVIEW_EXPLORE + idCmdFirst;
+            mi.wID = FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst;
             mi.fType = MFT_STRING;
             InsertMenuItemW(hmenu, (uFlags & CMF_EXPLORE) ? 1 : 2, MF_BYPOSITION, &mi);
         }
@@ -189,7 +223,7 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
         SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION);
 
         if(uFlags & ~CMF_CANRENAME)
-            RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME + idCmdFirst, MF_BYCOMMAND);
+            RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND);
         else
         {
             UINT enable = MF_BYCOMMAND;
@@ -205,7 +239,7 @@ static HRESULT WINAPI ItemMenu_QueryContextMenu(
                 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);
@@ -738,7 +772,7 @@ static HRESULT WINAPI ItemMenu_InvokeCommand(
 
     if (IS_INTRESOURCE(lpcmi->lpVerb))
     {
-        switch(LOWORD(lpcmi->lpVerb))
+        switch(LOWORD(lpcmi->lpVerb) + FCIDM_BASE)
         {
         case FCIDM_SHVIEW_EXPLORE:
             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_VERBW:
-        switch (cmdid)
+        switch (cmdid + FCIDM_BASE)
         {
         case FCIDM_SHVIEW_OPEN:
             cmdW = openW;
@@ -1059,8 +1093,9 @@ static HRESULT WINAPI BackgroundMenu_QueryContextMenu(
     }
     else
     {
-        idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
-                                  idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
+        Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
+                          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);
     }
     DestroyMenu(hMyMenu);
@@ -1228,7 +1263,7 @@ static HRESULT WINAPI BackgroundMenu_InvokeCommand(
     }
     else
     {
-        switch (LOWORD(lpcmi->lpVerb))
+        switch (LOWORD(lpcmi->lpVerb) + FCIDM_BASE)
         {
 	    case FCIDM_SHVIEW_REFRESH:
 	        if (view) IShellView_Refresh(view);
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index e724448c7a0..a2c15d9f40e 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -4385,7 +4385,15 @@ static void test_contextmenu(IContextMenu *menu, BOOL background)
             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));
             if (hr == S_OK)
+            {
                 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
                 trace("Got ID %d, hr %#x, string %s.\n", mii.wID, hr, debugstr_a(mii.dwTypeData));
         }




More information about the wine-cvs mailing list