[SHELL32] CDefaultContextMenu: Implement GetCommandString
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Tue, 20 Feb 2018 11:05:59 +0000 (13:05 +0200)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Tue, 20 Feb 2018 11:05:59 +0000 (13:05 +0200)
dll/win32/shell32/CDefaultContextMenu.cpp

index 0834995..fac9b50 100644 (file)
@@ -13,6 +13,7 @@ extern "C"
     //fixme: this isn't in wine's shlwapi header, and the definition doesnt match the
     // windows headers. When wine's header and lib are fixed this can be removed.
     DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen);
+    INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen);
 };
 
 WINE_DEFAULT_DEBUG_CHANNEL(dmenu);
@@ -47,7 +48,14 @@ struct _StaticInvokeCommandMap_
     { "Print", 0 },  // Unimplemented
     { "Preview", 0 }, // Unimplemented
     { "Open", FCIDM_SHVIEW_OPEN },
-    { CMDSTR_NEWFOLDERA, FCIDM_SHVIEW_NEWFOLDER }
+    { CMDSTR_NEWFOLDERA, FCIDM_SHVIEW_NEWFOLDER },
+    { "cut", FCIDM_SHVIEW_CUT},
+    { "copy", FCIDM_SHVIEW_COPY},
+    { "paste", FCIDM_SHVIEW_INSERT},
+    { "link", FCIDM_SHVIEW_CREATELINK},
+    { "delete", FCIDM_SHVIEW_DELETE},
+    { "properties", FCIDM_SHVIEW_PROPERTIES},
+    { "rename", FCIDM_SHVIEW_RENAME},
 };
 
 
@@ -1237,7 +1245,7 @@ CDefaultContextMenu::InvokeCommand(
         Result = DoCreateNewFolder(&LocalInvokeInfo);
         break;
     default:
-        Result = E_UNEXPECTED;
+        Result = E_INVALIDARG;
         ERR("Unhandled Verb %xl\n", LOWORD(LocalInvokeInfo.lpVerb));
         break;
     }
@@ -1256,15 +1264,68 @@ CDefaultContextMenu::GetCommandString(
 {
     /* We don't handle the help text yet */
     if (uFlags == GCS_HELPTEXTA ||
-        uFlags == GCS_HELPTEXTW)
+        uFlags == GCS_HELPTEXTW ||
+        HIWORD(idCommand) != 0)
     {
         return E_NOTIMPL;
     }
 
+    UINT CmdId = LOWORD(idCommand);
+
+    if (m_pDynamicEntries && CmdId >= m_iIdSHEFirst && CmdId < m_iIdSHELast)
+    {
+        idCommand -= m_iIdSHEFirst;
+        PDynamicShellEntry pEntry = GetDynamicEntry(idCommand);
+        if (!pEntry)
+            return E_FAIL;
+
+        idCommand -= pEntry->iIdCmdFirst;
+        return pEntry->pCM->GetCommandString(idCommand,
+                                             uFlags,
+                                             lpReserved,
+                                             lpszName,
+                                             uMaxNameLen);
+    }
+
+    if (m_pStaticEntries && CmdId >= m_iIdSCMFirst && CmdId < m_iIdSCMLast)
+    {
+        /* Validation just returns S_OK on a match. The id exists. */
+        if (uFlags == GCS_VALIDATEA || uFlags == GCS_VALIDATEW)
+            return S_OK;
+
+        CmdId -= m_iIdSCMFirst;
+
+        PStaticShellEntry pEntry = m_pStaticEntries;
+        while (pEntry && (CmdId--) > 0)
+            pEntry = pEntry->pNext;
+
+        if (!pEntry)
+            return E_INVALIDARG;
+
+        if (uFlags == GCS_VERBW)
+            return StringCchCopyW((LPWSTR)lpszName, uMaxNameLen, pEntry->szVerb);
+
+        if (uFlags == GCS_VERBA)
+        {
+            if (SHUnicodeToAnsi(pEntry->szVerb, lpszName, uMaxNameLen))
+                return S_OK;
+        }
+
+        return E_INVALIDARG;
+    }
+
+    //FIXME: Should we handle callbacks here?
+    if (m_iIdDfltFirst != m_iIdDfltLast && CmdId >= m_iIdDfltFirst && CmdId < m_iIdDfltLast)
+    {
+        CmdId -= m_iIdDfltFirst;
+        /* See the definitions of IDM_CUT and co to see how this works */
+        CmdId += 0x7000;
+    }
+
     /* Loop looking for a matching Id */
     for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); i++)
     {
-        if (g_StaticInvokeCmdMap[i].IntVerb == idCommand)
+        if (g_StaticInvokeCmdMap[i].IntVerb == CmdId)
         {
             /* Validation just returns S_OK on a match */
             if (uFlags == GCS_VALIDATEA || uFlags == GCS_VALIDATEW)