Index: CDefaultContextMenu.cpp =================================================================== --- CDefaultContextMenu.cpp (revision 70115) +++ CDefaultContextMenu.cpp (working copy) @@ -14,6 +14,12 @@ #include "precomp.h" +extern "C" +{ + //fixme: this isn't in wine's shlwapi header, and the definition doesnt match windows + DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen); +}; + WINE_DEFAULT_DEBUG_CHANNEL(dmenu); typedef struct _DynamicShellEntry_ @@ -32,6 +38,23 @@ struct _StaticShellEntry_ *pNext; } StaticShellEntry, *PStaticShellEntry; + +struct _StaticInvokeCommandMap_ +{ + LPCSTR szStringVerb; + UINT IntVerb; +} g_StaticInvokeCmdMap[] = +{ + { "RunAs", 0 }, // Unimplemented + { "Print", 0 }, // Unimplemented + { "Preview", 0 }, // Unimplemented + { "Open", FCIDM_SHVIEW_OPEN }, + { CMDSTR_NEWFOLDERA, FCIDM_SHVIEW_NEWFOLDER }, + { CMDSTR_VIEWLISTA, FCIDM_SHVIEW_LISTVIEW }, + { CMDSTR_VIEWDETAILSA, FCIDM_SHVIEW_REPORTVIEW } +}; + + class CDefaultContextMenu : public CComObjectRootEx, public IContextMenu3 @@ -69,6 +92,7 @@ HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoProperties(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoFormat(LPCMINVOKECOMMANDINFO lpcmi); + HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFO lpici); HRESULT DoDynamicShellExtensions(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoStaticShellExtensions(LPCMINVOKECOMMANDINFO lpcmi); DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry); @@ -75,7 +99,9 @@ HRESULT TryToBrowse(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags); HRESULT InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry); PDynamicShellEntry GetDynamicEntry(UINT idCmd); + BOOL MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode); + public: CDefaultContextMenu(); ~CDefaultContextMenu(); @@ -1367,6 +1393,67 @@ return S_OK; } +// This code is taken from CNewMenu and should be shared between the 2 classes +HRESULT +CDefaultContextMenu::DoCreateNewFolder( + LPCMINVOKECOMMANDINFO lpici) +{ + WCHAR wszPath[MAX_PATH]; + WCHAR wszName[MAX_PATH]; + WCHAR wszNewFolder[25]; + HRESULT hr; + + /* Get folder path */ + hr = SHGetPathFromIDListW(m_pidlFolder, wszPath); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + if (!LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, _countof(wszNewFolder))) + return E_FAIL; + + /* Create the name of the new directory */ + if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFolder)) + return E_FAIL; + + /* Create the new directory and show the appropriate dialog in case of error */ + if (SHCreateDirectory(lpici->hwnd, wszName) != ERROR_SUCCESS) + return E_FAIL; + + /* Show and select the new item in the def view */ + CComPtr lpSB; + CComPtr lpSV; + LPITEMIDLIST pidl; + PITEMID_CHILD pidlNewItem; + + /* Notify the view object about the new item */ + SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, (LPCVOID)wszName, NULL); + + /* FIXME: I think that this can be implemented using callbacks to the shell folder */ + + /* Note: CWM_GETISHELLBROWSER returns shell browser without adding reference */ + lpSB = (LPSHELLBROWSER)SendMessageA(lpici->hwnd, CWM_GETISHELLBROWSER, 0, 0); + if (!lpSB) + return E_FAIL; + + hr = lpSB->QueryActiveShellView(&lpSV); + if (FAILED(hr)) + return hr; + + /* Attempt to get the pidl of the new item */ + hr = SHILCreateFromPathW(wszName, &pidl, NULL); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + pidlNewItem = ILFindLastID(pidl); + + hr = lpSV->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | + SVSI_FOCUSED | SVSI_SELECT); + + SHFree(pidl); + + return hr; +} + PDynamicShellEntry CDefaultContextMenu::GetDynamicEntry(UINT idCmd) { PDynamicShellEntry pEntry = m_pDynamicEntries; @@ -1383,6 +1470,38 @@ return pEntry; } +//FIXME: 260 is correct, but should this be part of the SDK or just MAX_PATH? +#define MAX_VERB 260 + +BOOL +CDefaultContextMenu::MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode) +{ + WCHAR UnicodeStr[MAX_VERB]; + + for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); i++) + { + if (IsUnicode) + { + SHAnsiToUnicode(g_StaticInvokeCmdMap[i].szStringVerb, UnicodeStr, MAX_VERB); + if (!wcscmp(UnicodeStr, (LPWSTR)Verb)) + { + *idCmd = g_StaticInvokeCmdMap[i].IntVerb; + return TRUE; + } + } + else + { + if (!strcmp(g_StaticInvokeCmdMap[i].szStringVerb, (LPSTR)Verb)) + { + *idCmd = g_StaticInvokeCmdMap[i].IntVerb; + return TRUE; + } + } + } + + return FALSE; +} + HRESULT CDefaultContextMenu::DoDynamicShellExtensions( LPCMINVOKECOMMANDINFO lpcmi) @@ -1549,57 +1668,93 @@ CDefaultContextMenu::InvokeCommand( LPCMINVOKECOMMANDINFO lpcmi) { - switch(LOWORD(lpcmi->lpVerb)) + HRESULT Result; + LPCSTR Switcheroo = NULL; + UINT CmdId; + + if (HIWORD(lpcmi->lpVerb)) { - case FCIDM_SHVIEW_BIGICON: - case FCIDM_SHVIEW_SMALLICON: - case FCIDM_SHVIEW_LISTVIEW: - case FCIDM_SHVIEW_REPORTVIEW: - case 0x30: /* FIX IDS in resource files */ - case 0x31: - case 0x32: - case 0x33: - case FCIDM_SHVIEW_AUTOARRANGE: - case FCIDM_SHVIEW_SNAPTOGRID: - return NotifyShellViewWindow(lpcmi, FALSE); - case FCIDM_SHVIEW_REFRESH: - return DoRefresh(lpcmi); - case FCIDM_SHVIEW_INSERT: - return DoPaste(lpcmi, FALSE); - case FCIDM_SHVIEW_INSERTLINK: - return DoPaste(lpcmi, TRUE); - case FCIDM_SHVIEW_OPEN: - case FCIDM_SHVIEW_EXPLORE: - return DoOpenOrExplore(lpcmi); - case FCIDM_SHVIEW_COPY: - case FCIDM_SHVIEW_CUT: - return DoCopyOrCut(lpcmi, LOWORD(lpcmi->lpVerb) == FCIDM_SHVIEW_COPY); - case FCIDM_SHVIEW_CREATELINK: - return DoCreateLink(lpcmi); - case FCIDM_SHVIEW_DELETE: - return DoDelete(lpcmi); - case FCIDM_SHVIEW_RENAME: - return DoRename(lpcmi); - case FCIDM_SHVIEW_PROPERTIES: - return DoProperties(lpcmi); - case 0x7ABC: - return DoFormat(lpcmi); + Switcheroo = lpcmi->lpVerb; + if (MapVerbToCmdId((LPVOID)lpcmi->lpVerb, &CmdId, FALSE)) + lpcmi->lpVerb = MAKEINTRESOURCEA(CmdId); } - if (m_iIdSHEFirst && m_iIdSHELast) + switch (LOWORD(lpcmi->lpVerb)) { - if (LOWORD(lpcmi->lpVerb) >= m_iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSHELast) - return DoDynamicShellExtensions(lpcmi); + case FCIDM_SHVIEW_BIGICON: + case FCIDM_SHVIEW_SMALLICON: + case FCIDM_SHVIEW_LISTVIEW: + case FCIDM_SHVIEW_REPORTVIEW: + case 0x30: /* FIX IDS in resource files */ + case 0x31: + case 0x32: + case 0x33: + case FCIDM_SHVIEW_AUTOARRANGE: + case FCIDM_SHVIEW_SNAPTOGRID: + Result = NotifyShellViewWindow(lpcmi, FALSE); + break; + case FCIDM_SHVIEW_REFRESH: + Result = DoRefresh(lpcmi); + break; + case FCIDM_SHVIEW_INSERT: + Result = DoPaste(lpcmi, FALSE); + break; + case FCIDM_SHVIEW_INSERTLINK: + Result = DoPaste(lpcmi, TRUE); + break; + case FCIDM_SHVIEW_OPEN: + case FCIDM_SHVIEW_EXPLORE: + Result = DoOpenOrExplore(lpcmi); + break; + case FCIDM_SHVIEW_COPY: + case FCIDM_SHVIEW_CUT: + Result = DoCopyOrCut(lpcmi, LOWORD(lpcmi->lpVerb) == FCIDM_SHVIEW_COPY); + break; + case FCIDM_SHVIEW_CREATELINK: + Result = DoCreateLink(lpcmi); + break; + case FCIDM_SHVIEW_DELETE: + Result = DoDelete(lpcmi); + break; + case FCIDM_SHVIEW_RENAME: + Result = DoRename(lpcmi); + break; + case FCIDM_SHVIEW_PROPERTIES: + Result = DoProperties(lpcmi); + break; + case 0x7ABC: + Result = DoFormat(lpcmi); + break; + case FCIDM_SHVIEW_NEWFOLDER: + Result = DoCreateNewFolder(lpcmi); + break; + default: + Result = E_UNEXPECTED; + break; } - if (m_iIdSCMFirst && m_iIdSCMLast) + if (Result == E_UNEXPECTED) { - if (LOWORD(lpcmi->lpVerb) >= m_iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSCMLast) - return DoStaticShellExtensions(lpcmi); + if (m_iIdSHEFirst && m_iIdSHELast) + { + if (LOWORD(lpcmi->lpVerb) >= m_iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSHELast) + Result = DoDynamicShellExtensions(lpcmi); + } + + if (m_iIdSCMFirst && m_iIdSCMLast) + { + if (LOWORD(lpcmi->lpVerb) >= m_iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSCMLast) + Result = DoStaticShellExtensions(lpcmi); + } } - FIXME("Unhandled Verb %xl\n", LOWORD(lpcmi->lpVerb)); - return E_UNEXPECTED; + if (Result == E_UNEXPECTED) + FIXME("Unhandled Verb %xl\n", LOWORD(lpcmi->lpVerb)); + + if (Switcheroo) + lpcmi->lpVerb = Switcheroo; + + return Result; } HRESULT @@ -1611,7 +1766,32 @@ LPSTR lpszName, UINT uMaxNameLen) { - return S_OK; + + if (uFlags == GCS_HELPTEXTA || + uFlags == GCS_HELPTEXTW) + { + return E_NOTIMPL; + } + + for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); i++) + { + if (g_StaticInvokeCmdMap[i].IntVerb == idCommand) + { + if (uFlags == GCS_VALIDATEA || uFlags == GCS_VALIDATEA) + return S_OK; + + if (uFlags == GCS_VERBA) + return StringCchCopyA(lpszName, uMaxNameLen, g_StaticInvokeCmdMap[i].szStringVerb); + + if (uFlags == GCS_VERBW) + { + if (SHAnsiToUnicode(g_StaticInvokeCmdMap[i].szStringVerb, (LPWSTR)lpszName, uMaxNameLen)) + return S_OK; + } + } + } + + return E_INVALIDARG; } HRESULT Index: CNewMenu.cpp =================================================================== --- CNewMenu.cpp (revision 70115) +++ CNewMenu.cpp (working copy) @@ -337,6 +337,7 @@ return hr; } +// Code is duplicated in CDefaultContextMenu HRESULT CNewMenu::CreateNewFolder(LPCMINVOKECOMMANDINFO lpici) { WCHAR wszPath[MAX_PATH]; Index: precomp.h =================================================================== --- precomp.h (revision 70115) +++ precomp.h (working copy) @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include