* PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
*/
-/*
-TODO:
- The code in NotifyShellViewWindow to deliver commands to the view is broken. It is an excellent
- example of the wrong way to do it.
-*/
-
#include "precomp.h"
+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);
+};
+
WINE_DEFAULT_DEBUG_CHANNEL(dmenu);
typedef struct _DynamicShellEntry_
typedef struct _StaticShellEntry_
{
LPWSTR szVerb;
- LPWSTR szClass;
+ HKEY hkClass;
struct _StaticShellEntry_ *pNext;
} StaticShellEntry, *PStaticShellEntry;
+
+//
+// verbs for InvokeCommandInfo
+//
+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<CComMultiThreadModelNoCS>,
- public IContextMenu2
+ public IContextMenu3,
+ public IObjectWithSite
{
private:
+ CComPtr<IUnknown> m_site;
CComPtr<IShellFolder> m_psf;
+ CComPtr<IContextMenuCB> m_pmcb;
+ LPFNDFMCALLBACK m_pfnmcb;
UINT m_cidl;
PCUITEMID_CHILD_ARRAY m_apidl;
CComPtr<IDataObject> m_pDataObj;
+ HKEY* m_aKeys;
+ UINT m_cKeys;
PIDLIST_ABSOLUTE m_pidlFolder;
DWORD m_bGroupPolicyActive;
PDynamicShellEntry m_pDynamicEntries; /* first dynamic shell extension entry */
PStaticShellEntry m_pStaticEntries; /* first static shell extension entry */
UINT m_iIdSCMFirst; /* first static used id */
UINT m_iIdSCMLast; /* last static used id */
+ UINT m_iIdCBFirst; /* first callback used id */
+ UINT m_iIdCBLast; /* last callback used id */
- void AddStaticEntry(LPCWSTR pwszVerb, LPCWSTR pwszClass);
- void AddStaticEntryForKey(HKEY hKey, LPCWSTR pwszClass);
- void AddStaticEntryForFileClass(LPCWSTR pwszExt);
+ HRESULT _DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam);
+ void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb);
+ void AddStaticEntriesForKey(HKEY hKey);
BOOL IsShellExtensionAlreadyLoaded(const CLSID *pclsid);
HRESULT LoadDynamicContextMenuHandler(HKEY hKey, const CLSID *pclsid);
BOOL EnumerateDynamicContextHandlerForKey(HKEY hRootKey);
UINT InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, UINT IndexMenu, UINT idCmdFirst, UINT idCmdLast);
- UINT BuildBackgroundContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
- UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu);
- UINT BuildShellItemContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
+ UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu, UINT iIdCmdFirst, UINT iIdCmdLast);
HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink);
HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi);
- HRESULT DoRefresh(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoDelete(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy);
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);
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();
- HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm);
+ HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn);
// IContextMenu
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
// IContextMenu2
virtual HRESULT WINAPI HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ // IContextMenu3
+ virtual HRESULT WINAPI HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
+
+ // IObjectWithSite
+ virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
+ virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, void **ppvSite);
+
BEGIN_COM_MAP(CDefaultContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
+ COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
+ COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
END_COM_MAP()
};
CDefaultContextMenu::CDefaultContextMenu() :
m_psf(NULL),
+ m_pmcb(NULL),
+ m_pfnmcb(NULL),
m_cidl(0),
m_apidl(NULL),
m_pDataObj(NULL),
+ m_aKeys(NULL),
+ m_cKeys(NULL),
m_pidlFolder(NULL),
m_bGroupPolicyActive(0),
m_pDynamicEntries(NULL),
m_iIdSHELast(0),
m_pStaticEntries(NULL),
m_iIdSCMFirst(0),
- m_iIdSCMLast(0)
+ m_iIdSCMLast(0),
+ m_iIdCBFirst(0),
+ m_iIdCBLast(0)
{
}
while (pStaticEntry)
{
pNextStatic = pStaticEntry->pNext;
- HeapFree(GetProcessHeap(), 0, pStaticEntry->szClass);
HeapFree(GetProcessHeap(), 0, pStaticEntry->szVerb);
HeapFree(GetProcessHeap(), 0, pStaticEntry);
pStaticEntry = pNextStatic;
}
+ for (UINT i = 0; i < m_cKeys; i++)
+ RegCloseKey(m_aKeys[i]);
+ HeapFree(GetProcessHeap(), 0, m_aKeys);
+
if (m_pidlFolder)
CoTaskMemFree(m_pidlFolder);
_ILFreeaPidl(const_cast<PITEMID_CHILD *>(m_apidl), m_cidl);
}
-HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
+HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn)
{
- CComPtr<IDataObject> pDataObj;
-
TRACE("cidl %u\n", pdcm->cidl);
+ if (!pdcm->pcmcb && !lpfn)
+ {
+ ERR("CDefaultContextMenu needs a callback!\n");
+ return E_INVALIDARG;
+ }
+
m_cidl = pdcm->cidl;
m_apidl = const_cast<PCUITEMID_CHILD_ARRAY>(_ILCopyaPidl(pdcm->apidl, m_cidl));
if (m_cidl && !m_apidl)
return E_OUTOFMEMORY;
m_psf = pdcm->psf;
+ m_pmcb = pdcm->pcmcb;
+ m_pfnmcb = lpfn;
+
+ m_cKeys = pdcm->cKeys;
+ if (pdcm->cKeys)
+ {
+ m_aKeys = (HKEY*)HeapAlloc(GetProcessHeap(), 0, sizeof(HKEY) * pdcm->cKeys);
+ if (!m_aKeys)
+ return E_OUTOFMEMORY;
+ memcpy(m_aKeys, pdcm->aKeys, sizeof(HKEY) * pdcm->cKeys);
+ }
- if (SUCCEEDED(SHCreateDataObject(pdcm->pidlFolder, pdcm->cidl, pdcm->apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
- m_pDataObj = pDataObj;
+ m_psf->GetUIObjectOf(pdcm->hwnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &m_pDataObj));
if (pdcm->pidlFolder)
{
return S_OK;
}
-void
-CDefaultContextMenu::AddStaticEntry(const WCHAR *szVerb, const WCHAR *szClass)
+HRESULT CDefaultContextMenu::_DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam)
+{
+ if (m_pmcb)
+ {
+ return m_pmcb->CallBack(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam);
+ }
+ else if(m_pfnmcb)
+ {
+ return m_pfnmcb(m_psf, NULL, m_pDataObj, uMsg, wParam, (LPARAM)lParam);
+ }
+
+ return E_FAIL;
+}
+
+void CDefaultContextMenu::AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb)
{
PStaticShellEntry pEntry = m_pStaticEntries, pLastEntry = NULL;
while(pEntry)
pEntry = pEntry->pNext;
}
- TRACE("adding verb %s szClass %s\n", debugstr_w(szVerb), debugstr_w(szClass));
+ TRACE("adding verb %s\n", debugstr_w(szVerb));
pEntry = (StaticShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(StaticShellEntry));
if (pEntry)
pEntry->szVerb = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(szVerb) + 1) * sizeof(WCHAR));
if (pEntry->szVerb)
wcscpy(pEntry->szVerb, szVerb);
- pEntry->szClass = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(szClass) + 1) * sizeof(WCHAR));
- if (pEntry->szClass)
- wcscpy(pEntry->szClass, szClass);
+ pEntry->hkClass = hkeyClass;
}
if (!wcsicmp(szVerb, L"open"))
m_pStaticEntries = pEntry;
}
-void
-CDefaultContextMenu::AddStaticEntryForKey(HKEY hKey, const WCHAR *pwszClass)
+void CDefaultContextMenu::AddStaticEntriesForKey(HKEY hKey)
{
WCHAR wszName[40];
DWORD cchName, dwIndex = 0;
+ HKEY hShellKey;
- TRACE("AddStaticEntryForKey %x %ls\n", hKey, pwszClass);
+ LRESULT lres = RegOpenKeyExW(hKey, L"shell", 0, KEY_READ, &hShellKey);
+ if (lres != STATUS_SUCCESS)
+ return;
while(TRUE)
{
cchName = _countof(wszName);
- if (RegEnumKeyExW(hKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
+ if (RegEnumKeyExW(hShellKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
break;
- AddStaticEntry(wszName, pwszClass);
+ AddStaticEntry(hKey, wszName);
}
-}
-
-void
-CDefaultContextMenu::AddStaticEntryForFileClass(const WCHAR * szExt)
-{
- WCHAR szBuffer[100];
- HKEY hKey;
- LONG result;
- DWORD dwBuffer;
- UINT Length;
- static WCHAR szShell[] = L"\\shell";
- static WCHAR szShellAssoc[] = L"SystemFileAssociations\\";
-
- TRACE("AddStaticEntryForFileClass entered with %s\n", debugstr_w(szExt));
-
- Length = wcslen(szExt);
- if (Length + (sizeof(szShell) / sizeof(WCHAR)) + 1 < sizeof(szBuffer) / sizeof(WCHAR))
- {
- wcscpy(szBuffer, szExt);
- wcscpy(&szBuffer[Length], szShell);
- result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
- if (result == ERROR_SUCCESS)
- {
- szBuffer[Length] = 0;
- AddStaticEntryForKey(hKey, szExt);
- RegCloseKey(hKey);
- }
- }
-
- dwBuffer = sizeof(szBuffer);
- result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, (LPBYTE)szBuffer, &dwBuffer);
- if (result == ERROR_SUCCESS)
- {
- Length = wcslen(szBuffer);
- if (Length + (sizeof(szShell) / sizeof(WCHAR)) + 1 < sizeof(szBuffer) / sizeof(WCHAR))
- {
- wcscpy(&szBuffer[Length], szShell);
- TRACE("szBuffer %s\n", debugstr_w(szBuffer));
- result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
- if (result == ERROR_SUCCESS)
- {
- szBuffer[Length] = 0;
- AddStaticEntryForKey(hKey, szBuffer);
- RegCloseKey(hKey);
- }
- }
- }
-
- wcscpy(szBuffer, szShellAssoc);
- dwBuffer = sizeof(szBuffer) - sizeof(szShellAssoc) - sizeof(WCHAR);
- result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, L"PerceivedType", RRF_RT_REG_SZ, NULL, (LPBYTE)&szBuffer[_countof(szShellAssoc) - 1], &dwBuffer);
- if (result == ERROR_SUCCESS)
- {
- Length = wcslen(&szBuffer[_countof(szShellAssoc)]) + _countof(szShellAssoc);
- wcscat(szBuffer, L"\\shell");
- TRACE("szBuffer %s\n", debugstr_w(szBuffer));
-
- result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
- if (result == ERROR_SUCCESS)
- {
- szBuffer[Length] = 0;
- AddStaticEntryForKey(hKey, szBuffer);
- RegCloseKey(hKey);
- }
- }
+ RegCloseKey(hShellKey);
}
static
BOOL bRet = FALSE;
CComPtr<IDataObject> pDataObj;
- if(SUCCEEDED(OleGetClipboard(&pDataObj)))
+ if (SUCCEEDED(OleGetClipboard(&pDataObj)))
{
STGMEDIUM medium;
FORMATETC formatetc;
/* Set the FORMATETC structure*/
InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
- if(SUCCEEDED(pDataObj->GetData(&formatetc, &medium)))
+ if (SUCCEEDED(pDataObj->GetData(&formatetc, &medium)))
{
bRet = TRUE;
ReleaseStgMedium(&medium);
return bRet;
}
-static
-VOID
-DisablePasteOptions(HMENU hMenu)
-{
- MENUITEMINFOW mii;
-
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_STATE;
- mii.fState = MFS_DISABLED;
-
- TRACE("result %d\n", SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERT, FALSE, &mii));
- TRACE("result %d\n", SetMenuItemInfoW(hMenu, FCIDM_SHVIEW_INSERTLINK, FALSE, &mii));
-}
-
BOOL
CDefaultContextMenu::IsShellExtensionAlreadyLoaded(const CLSID *pclsid)
{
CComPtr<IContextMenu> pcm;
hr = SHCoCreateInstance(NULL, pclsid, NULL, IID_PPV_ARG(IContextMenu, &pcm));
- if (hr != S_OK)
- {
- ERR("SHCoCreateInstance failed %x\n", GetLastError());
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- }
CComPtr<IShellExtInit> pExtInit;
hr = pcm->QueryInterface(IID_PPV_ARG(IShellExtInit, &pExtInit));
- if (hr != S_OK)
- {
- ERR("Failed to query for interface IID_IShellExtInit hr %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid));
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- }
hr = pExtInit->Initialize(m_pidlFolder, m_pDataObj, hKey);
- if (hr != S_OK)
+ if (FAILED(hr))
{
- TRACE("Failed to initialize shell extension error %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid));
+ WARN("IShellExtInit::Initialize failed.clsid %s hr 0x%x\n", wine_dbgstr_guid(pclsid), hr);
return hr;
}
PDynamicShellEntry pEntry = (DynamicShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(DynamicShellEntry));
if (!pEntry)
- {
return E_OUTOFMEMORY;
- }
pEntry->iIdCmdFirst = 0;
pEntry->pNext = NULL;
BOOL
CDefaultContextMenu::EnumerateDynamicContextHandlerForKey(HKEY hRootKey)
{
-
WCHAR wszName[MAX_PATH], wszBuf[MAX_PATH], *pwszClsid;
DWORD cchName;
HRESULT hr;
hr = CLSIDFromString(wszBuf, &clsid);
pwszClsid = wszBuf;
}
- if (SUCCEEDED(hr))
+
+ if (FAILED(hr))
+ {
+ ERR("CLSIDFromString failed for clsid %S hr 0x%x\n", pwszClsid, hr);
+ continue;
+ }
+
+ if (m_bGroupPolicyActive)
{
- if (m_bGroupPolicyActive)
+ if (RegGetValueW(HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
+ pwszClsid,
+ RRF_RT_REG_SZ,
+ NULL,
+ NULL,
+ NULL) != ERROR_SUCCESS)
{
- if (RegGetValueW(HKEY_LOCAL_MACHINE,
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
- pwszClsid,
- RRF_RT_REG_SZ,
- NULL,
- NULL,
- NULL) == ERROR_SUCCESS)
- {
- LoadDynamicContextMenuHandler(hKey, &clsid);
- }
+ ERR("Shell extension %s not approved!\n", pwszClsid);
+ continue;
}
- else
- LoadDynamicContextMenuHandler(hKey, &clsid);
}
+
+ hr = LoadDynamicContextMenuHandler(hKey, &clsid);
+ if (FAILED(hr))
+ WARN("Failed to get context menu entires from shell extension! clsid: %S\n", pwszClsid);
}
RegCloseKey(hKey);
}
PDynamicShellEntry pEntry = m_pDynamicEntries;
- idCmdFirst = 0x5000;
- idCmdLast = 0x6000;
m_iIdSHEFirst = idCmdFirst;
do
{
pEntry->NumIds = LOWORD(hr);
IndexMenu += pEntry->NumIds;
idCmdFirst += pEntry->NumIds + 0x10;
+
+ if(idCmdFirst >= idCmdLast)
+ {
+ /* There is no more room for items */
+ idCmdFirst = idCmdLast;
+ break;
+ }
}
TRACE("pEntry %p hr %x contextmenu %p cmdfirst %x num ids %x\n", pEntry, hr, pEntry->pCM, pEntry->iIdCmdFirst, pEntry->NumIds);
pEntry = pEntry->pNext;
return IndexMenu;
}
-UINT
-CDefaultContextMenu::BuildBackgroundContextMenu(
- HMENU hMenu,
- UINT iIdCmdFirst,
- UINT iIdCmdLast,
- UINT uFlags)
-{
- UINT IndexMenu = 0;
- HMENU hSubMenu;
-
- TRACE("BuildBackgroundContextMenu entered\n");
-
- if (!_ILIsDesktop(m_pidlFolder))
- {
- WCHAR wszBuf[MAX_PATH];
-
- /* view option is only available in browsing mode */
- hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_001");
- if (hSubMenu && LoadStringW(shell32_hInstance, FCIDM_SHVIEW_VIEW, wszBuf, _countof(wszBuf)))
- {
- TRACE("wszBuf %s\n", debugstr_w(wszBuf));
-
- MENUITEMINFOW mii;
- ZeroMemory(&mii, sizeof(mii));
- mii.cbSize = sizeof(mii);
- mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMENU | MIIM_ID;
- mii.fType = MFT_STRING;
- mii.wID = iIdCmdFirst++;
- mii.dwTypeData = wszBuf;
- mii.cch = wcslen(mii.dwTypeData);
- mii.fState = MFS_ENABLED;
- mii.hSubMenu = hSubMenu;
- InsertMenuItemW(hMenu, IndexMenu++, TRUE, &mii);
- DestroyMenu(hSubMenu);
- }
- }
-
- hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_002");
- if (hSubMenu)
- {
- /* merge general background context menu in */
- iIdCmdFirst = Shell_MergeMenus(hMenu, GetSubMenu(hSubMenu, 0), IndexMenu, 0, 0xFFFF, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS) + 1;
- DestroyMenu(hSubMenu);
- }
-
- if (!HasClipboardData())
- {
- TRACE("disabling paste options\n");
- DisablePasteOptions(hMenu);
- }
-
- /* Directory is progid of filesystem folders only */
- LPITEMIDLIST pidlFolderLast = ILFindLastID(m_pidlFolder);
- if (_ILIsDesktop(pidlFolderLast) || _ILIsDrive(pidlFolderLast) || _ILIsFolder(pidlFolderLast))
- {
- /* Load context menu handlers */
- TRACE("Add background handlers: %p\n", m_pidlFolder);
- HKEY hKey;
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Directory\\Background", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
-
- if (InsertMenuItemsOfDynamicContextMenuExtension(hMenu, GetMenuItemCount(hMenu) - 1, iIdCmdFirst, iIdCmdLast))
- {
- /* seperate dynamic context menu items */
- _InsertMenuItemW(hMenu, GetMenuItemCount(hMenu) - 1, TRUE, -1, MFT_SEPARATOR, NULL, MFS_ENABLED);
- }
- }
-
- return iIdCmdLast;
-}
-
UINT
CDefaultContextMenu::AddStaticContextMenusToMenu(
HMENU hMenu,
- UINT IndexMenu)
+ UINT IndexMenu,
+ UINT iIdCmdFirst,
+ UINT iIdCmdLast)
{
MENUITEMINFOW mii;
UINT idResource;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
mii.fType = MFT_STRING;
- mii.wID = 0x4000;
+ mii.wID = iIdCmdFirst;
mii.dwTypeData = NULL;
m_iIdSCMFirst = mii.wID;
else
{
WCHAR wszKey[256];
- HRESULT hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"%s\\shell\\%s", pEntry->szClass, pEntry->szVerb);
+ HRESULT hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", pEntry->szVerb);
if (SUCCEEDED(hr))
{
+ HKEY hkVerb;
DWORD cbVerb = sizeof(wszVerb);
+ LONG res = RegOpenKeyW(pEntry->hkClass, wszKey, &hkVerb);
+ if (res == ERROR_SUCCESS)
+ {
+ res = RegLoadMUIStringW(hkVerb,
+ NULL,
+ wszVerb,
+ cbVerb,
+ NULL,
+ 0,
+ NULL);
+ if (res == ERROR_SUCCESS)
+ {
+ /* use description for the menu entry */
+ mii.dwTypeData = wszVerb;
+ }
- if (RegGetValueW(HKEY_CLASSES_ROOT, wszKey, NULL, RRF_RT_REG_SZ, NULL, wszVerb, &cbVerb) == ERROR_SUCCESS)
- mii.dwTypeData = wszVerb; /* use description for the menu entry */
+ RegCloseKey(hkVerb);
+ }
}
}
mii.wID++;
pEntry = pEntry->pNext;
+
+ if (mii.wID >= iIdCmdLast)
+ break;
}
m_iIdSCMLast = mii.wID - 1;
InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
}
-UINT
-CDefaultContextMenu::BuildShellItemContextMenu(
+HRESULT
+WINAPI
+CDefaultContextMenu::QueryContextMenu(
HMENU hMenu,
- UINT iIdCmdFirst,
- UINT iIdCmdLast,
+ UINT IndexMenu,
+ UINT idCmdFirst,
+ UINT idCmdLast,
UINT uFlags)
{
- HKEY hKey;
HRESULT hr;
+ UINT idCmdNext = idCmdFirst;
- TRACE("BuildShellItemContextMenu entered\n");
- ASSERT(m_cidl >= 1);
-
- STRRET strFile;
- hr = m_psf->GetDisplayNameOf(m_apidl[0], SHGDN_FORPARSING, &strFile);
- if (hr == S_OK)
- {
- WCHAR wszPath[MAX_PATH];
- hr = StrRetToBufW(&strFile, m_apidl[0], wszPath, _countof(wszPath));
- if (hr == S_OK)
- {
- LPCWSTR pwszExt = PathFindExtensionW(wszPath);
- if (pwszExt[0])
- {
- /* enumerate dynamic/static for a given file class */
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- /* add static verbs */
- AddStaticEntryForFileClass(pwszExt);
-
- /* load dynamic extensions from file extension key */
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
+ /* Add a tiny hack to make all the shell happy until we understand how we should handle 0 ids */
+ if (!idCmdNext)
+ idCmdNext = 1;
- WCHAR wszTemp[40];
- DWORD dwSize = sizeof(wszTemp);
- if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, NULL, RRF_RT_REG_SZ, NULL, wszTemp, &dwSize) == ERROR_SUCCESS)
- {
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTemp, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- /* add static verbs from progid key */
- AddStaticEntryForFileClass(wszTemp);
-
- /* load dynamic extensions from progid key */
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
- }
- }
-
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"*", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- /* load default extensions */
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
- }
- }
- else
- ERR("GetDisplayNameOf failed: %x\n", hr);
+ TRACE("BuildShellItemContextMenu entered\n");
- GUID *pGuid = _ILGetGUIDPointer(m_apidl[0]);
- if (pGuid)
+ /* Load static verbs and shell extensions from registry */
+ for (UINT i = 0; i < m_cKeys; i++)
{
- LPOLESTR pwszCLSID;
- WCHAR buffer[60];
-
- wcscpy(buffer, L"CLSID\\");
- hr = StringFromCLSID(*pGuid, &pwszCLSID);
- if (hr == S_OK)
- {
- wcscpy(&buffer[6], pwszCLSID);
- TRACE("buffer %s\n", debugstr_w(buffer));
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- EnumerateDynamicContextHandlerForKey(hKey);
- AddStaticEntryForFileClass(buffer);
- RegCloseKey(hKey);
- }
- CoTaskMemFree(pwszCLSID);
- }
+ AddStaticEntriesForKey(m_aKeys[i]);
+ EnumerateDynamicContextHandlerForKey(m_aKeys[i]);
}
- if (_ILIsDrive(m_apidl[0]))
- {
- AddStaticEntryForFileClass(L"Drive");
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Drive", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
+ /* Add static context menu handlers */
+ IndexMenu = AddStaticContextMenusToMenu(hMenu, IndexMenu, idCmdNext, idCmdLast);
+ if (m_iIdSCMLast && m_iIdSCMFirst > m_iIdSCMLast)
+ m_iIdSCMLast = m_iIdSCMFirst = 0;
+ else if (m_iIdSCMLast)
+ idCmdNext = m_iIdSCMLast + 1;
- }
+ /* Add dynamic context menu handlers */
+ BOOL bAddSep = FALSE;
+ IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, idCmdNext, idCmdLast);
+ if (m_iIdSHELast && m_iIdSHELast != m_iIdSHEFirst)
+ idCmdNext = m_iIdSHELast + 1;
- /* add static actions */
- SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
- hr = m_psf->GetAttributesOf(m_cidl, m_apidl, &rfg);
- if (FAILED(hr))
+ /* Now let the callback add its own items */
+ QCMINFO qcminfo = {hMenu, IndexMenu, idCmdNext, idCmdLast, NULL};
+ if (SUCCEEDED(_DoCallback(DFM_MERGECONTEXTMENU, uFlags, &qcminfo)))
{
- ERR("GetAttributesOf failed: %x\n", hr);
- rfg = 0;
+ m_iIdCBFirst = idCmdNext;
+ m_iIdCBLast = qcminfo.idCmdFirst;
+ idCmdNext = m_iIdCBLast + 1;
}
- if (rfg & SFGAO_FOLDER)
- {
- /* add the default verbs open / explore */
- AddStaticEntryForFileClass(L"Folder");
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Folder", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
+ /* The rest of the items will be added in the end of the menu */
+ IndexMenu = GetMenuItemCount(hMenu);
- /* Directory is only loaded for real filesystem directories */
- if (_ILIsFolder(m_apidl[0]))
- {
- AddStaticEntryForFileClass(L"Directory");
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Directory", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
- }
- }
-
- /* AllFilesystemObjects class is loaded only for files and directories */
- if (_ILIsFolder(m_apidl[0]) || _ILIsValue(m_apidl[0]))
- {
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"AllFilesystemObjects", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- /* sendto service is registered here */
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
- }
+ if (uFlags & CMF_VERBSONLY)
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdNext - idCmdFirst);
- /* add static context menu handlers */
- UINT IndexMenu = AddStaticContextMenusToMenu(hMenu, 0);
+ /* If this is a background context menu we are done */
+ if (!m_cidl)
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdNext - idCmdFirst);
- /* now process dynamic context menu handlers */
- BOOL bAddSep = FALSE;
- IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, iIdCmdFirst, iIdCmdLast);
- TRACE("IndexMenu %d\n", IndexMenu);
-
- if (_ILIsDrive(m_apidl[0]))
- {
- /* The 'Format' option must be always available,
- * thus it is not registered as a static shell extension */
- _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
- _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0x7ABC, MFT_STRING, MAKEINTRESOURCEW(IDS_FORMATDRIVE), MFS_ENABLED);
- bAddSep = TRUE;
- }
+ /* Get the attributes of the items */
+ SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
+ hr = m_psf->GetAttributesOf(m_cidl, m_apidl, &rfg);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmdNext - idCmdFirst);
+ /* Add the standard menu entries based on the attributes of the items */
BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM));
if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData)
{
if (rfg & SFGAO_CANCOPY)
_InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, MAKEINTRESOURCEW(IDS_COPY), MFS_ENABLED);
if (bClipboardData)
- _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_INSERT, MFT_STRING, MAKEINTRESOURCEW(IDS_INSERT), MFS_ENABLED);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_INSERT, MFT_STRING, MAKEINTRESOURCEW(IDS_PASTE), MFS_ENABLED);
bAddSep = TRUE;
}
_InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
}
- return iIdCmdLast;
-}
-
-HRESULT
-WINAPI
-CDefaultContextMenu::QueryContextMenu(
- HMENU hMenu,
- UINT IndexMenu,
- UINT idCmdFirst,
- UINT idCmdLast,
- UINT uFlags)
-{
- if (m_cidl)
- idCmdFirst = BuildShellItemContextMenu(hMenu, idCmdFirst, idCmdLast, uFlags);
- else
- idCmdFirst = BuildBackgroundContextMenu(hMenu, idCmdFirst, idCmdLast, uFlags);
-
return S_OK;
}
-static
-HRESULT
-NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh)
-{
- /* Note: CWM_GETISHELLBROWSER returns not referenced object */
- LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
- if (!lpSB)
- return E_FAIL;
-
- CComPtr<IShellView> lpSV;
- if (FAILED(lpSB->QueryActiveShellView(&lpSV)))
- return E_FAIL;
-
- HWND hwndSV = NULL;
- if (SUCCEEDED(lpSV->GetWindow(&hwndSV)))
- SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
- return S_OK;
-}
-
-HRESULT
-CDefaultContextMenu::DoRefresh(
- LPCMINVOKECOMMANDINFO lpcmi)
-{
- CComPtr<IPersistFolder2> ppf2 = NULL;
- LPITEMIDLIST pidl;
- HRESULT hr = m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
- if (SUCCEEDED(hr))
- {
- hr = ppf2->GetCurFolder(&pidl);
- if (SUCCEEDED(hr))
- {
- SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL);
- ILFree(pidl);
- }
- }
- return hr;
-}
-
-HRESULT
-CDefaultContextMenu::DoPaste(
- LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink)
+HRESULT CDefaultContextMenu::DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink)
{
HRESULT hr;
CComPtr<IDataObject> pda;
hr = OleGetClipboard(&pda);
- if (FAILED(hr))
- return hr;
-
- CComPtr<IShellFolder> psfDesktop;
- CComPtr<IShellFolder> psfTarget = NULL;
-
- hr = SHGetDesktopFolder(&psfDesktop);
- if (FAILED(hr))
- return hr;
-
- /* Find target folder */
- if (m_cidl)
- {
- hr = m_psf->BindToObject(m_apidl[0], NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
- }
- else
- {
- CComPtr<IPersistFolder2> ppf2 = NULL;
- LPITEMIDLIST pidl;
-
- /* cidl is zero due to explorer view */
- hr = m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
- if (SUCCEEDED(hr))
- {
- hr = ppf2->GetCurFolder(&pidl);
- if (SUCCEEDED(hr))
- {
- if (_ILIsDesktop(pidl))
- {
- /* use desktop shellfolder */
- psfTarget = psfDesktop;
- }
- else
- {
- /* retrieve target desktop folder */
- hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
- }
- TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget.p, _ILIsDesktop(pidl));
- ILFree(pidl);
- }
- }
- }
-
- if (FAILED(hr))
- {
- ERR("no IShellFolder\n");
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- }
FORMATETC formatetc2;
STGMEDIUM medium2;
}
CComPtr<IDropTarget> pdrop;
- hr = psfTarget->QueryInterface(IID_PPV_ARG(IDropTarget, &pdrop));
- if (FAILED(hr))
- {
- ERR("Error getting IDropTarget interface\n");
+ if (m_cidl)
+ hr = m_psf->GetUIObjectOf(NULL, 1, &m_apidl[0], IID_NULL_PPV_ARG(IDropTarget, &pdrop));
+ else
+ hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdrop));
+
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- }
SHSimulateDrop(pdrop, pda, dwKey, NULL, NULL);
}
HRESULT
-CDefaultContextMenu::DoOpenOrExplore(
- LPCMINVOKECOMMANDINFO lpcmi)
+CDefaultContextMenu::DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi)
{
UNIMPLEMENTED;
return E_FAIL;
}
-HRESULT
-CDefaultContextMenu::DoCreateLink(
- LPCMINVOKECOMMANDINFO lpcmi)
+HRESULT CDefaultContextMenu::DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi)
{
- CComPtr<IDataObject> pDataObj;
- CComPtr<IDropTarget> pDT;
- HRESULT hr;
- CComPtr<IPersistFolder2> ppf2 = NULL;
- LPITEMIDLIST pidl;
- CComPtr<IShellFolder> psfDesktop;
- CComPtr<IShellFolder> psfTarget = NULL;
+ if (!m_cidl || !m_pDataObj)
+ return E_FAIL;
- hr = SHGetDesktopFolder(&psfDesktop);
- if (FAILED(hr))
+ CComPtr<IDropTarget> pDT;
+ HRESULT hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pDT));
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- if (SUCCEEDED(hr = SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
- {
- hr = m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
- if (SUCCEEDED(hr))
- {
- hr = ppf2->GetCurFolder(&pidl);
- if (SUCCEEDED(hr))
- {
- if (_ILIsDesktop(pidl))
- {
- /* use desktop shellfolder */
- psfTarget = psfDesktop;
- }
- else
- {
- /* retrieve target desktop folder */
- hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
- }
- TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget.p, _ILIsDesktop(pidl));
- ILFree(pidl);
- }
- }
-
- }
+ SHSimulateDrop(pDT, m_pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL);
- if (FAILED(hr))
- {
- ERR("no IShellFolder\n");
- return hr;
- }
+ return S_OK;
+}
- hr = psfTarget->QueryInterface(IID_PPV_ARG(IDropTarget, &pDT));
- if (FAILED(hr))
- {
- ERR("no IDropTarget Interface\n");
- return hr;
- }
- SHSimulateDrop(pDT, pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL);
+HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi)
+{
+ if (!m_cidl || !m_pDataObj)
+ return E_FAIL;
+ DoDeleteAsync(m_pDataObj, lpcmi->fMask);
return S_OK;
}
-HRESULT CDefaultContextMenu::DoDelete(LPCMINVOKECOMMANDINFO lpcmi) {
- TRACE("(%p) Deleting\n", this);
-
- CComPtr<IDataObject> pDataObject;
+HRESULT CDefaultContextMenu::DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy)
+{
+ if (!m_cidl || !m_pDataObj)
+ return E_FAIL;
- if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObject))))
+ if (!bCopy)
{
- IStream *s;
- CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObject, &s);
- SHCreateThread(DoDeleteThreadProc, s, NULL, NULL);
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+ InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
+ m_pDataObj->GetData(&formatetc, &medium);
+ DWORD * pdwFlag = (DWORD*)GlobalLock(medium.hGlobal);
+ if (pdwFlag)
+ *pdwFlag = DROPEFFECT_MOVE;
+ GlobalUnlock(medium.hGlobal);
+ m_pDataObj->SetData(&formatetc, &medium, TRUE);
}
- else
- return E_FAIL;
+
+ HRESULT hr = OleSetClipboard(m_pDataObj);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
return S_OK;
}
-HRESULT
-CDefaultContextMenu::DoCopyOrCut(
- LPCMINVOKECOMMANDINFO lpcmi,
- BOOL bCopy)
+HRESULT CDefaultContextMenu::DoRename(LPCMINVOKECOMMANDINFO lpcmi)
{
- CComPtr<IDataObject> pDataObj;
+ CComPtr<IShellBrowser> psb;
HRESULT hr;
- if (SUCCEEDED(SHCreateDataObject(m_pidlFolder, m_cidl, m_apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
- {
- if (!bCopy)
- {
- FORMATETC formatetc;
- STGMEDIUM medium;
- InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
- pDataObj->GetData(&formatetc, &medium);
- DWORD * pdwFlag = (DWORD*)GlobalLock(medium.hGlobal);
- if (pdwFlag)
- *pdwFlag = DROPEFFECT_MOVE;
- GlobalUnlock(medium.hGlobal);
- pDataObj->SetData(&formatetc, &medium, TRUE);
- }
+ if (!m_site || !m_cidl)
+ return E_FAIL;
- hr = OleSetClipboard(pDataObj);
+ /* Get a pointer to the shell browser */
+ hr = IUnknown_QueryService(m_site, SID_IShellBrowser, IID_PPV_ARG(IShellBrowser, &psb));
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- }
-
- /* Note: CWM_GETISHELLBROWSER returns not referenced object */
- LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
- if (!lpSB)
- {
- ERR("failed to get shellbrowser\n");
- return E_FAIL;
- }
CComPtr<IShellView> lpSV;
- hr = lpSB->QueryActiveShellView(&lpSV);
- if (FAILED(hr))
- {
- ERR("failed to query the active shellview\n");
+ hr = psb->QueryActiveShellView(&lpSV);
+ if (FAILED_UNEXPECTEDLY(hr))
return hr;
- }
- hr = lpSV->GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IDataObject, &pDataObj));
- if (SUCCEEDED(hr))
- {
- hr = OleSetClipboard(pDataObj);
- if (FAILED(hr))
- ERR("OleSetClipboard failed");
- pDataObj->Release();
- } else
- ERR("failed to get item object\n");
+ SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
+ hr = lpSV->SelectItem(m_apidl[0], selFlags);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
- return hr;
+ return S_OK;
}
HRESULT
-CDefaultContextMenu::DoRename(
+CDefaultContextMenu::DoProperties(
LPCMINVOKECOMMANDINFO lpcmi)
{
- /* get the active IShellView. Note: CWM_GETISHELLBROWSER returns not referenced object */
- LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
- if (!lpSB)
- {
- ERR("CWM_GETISHELLBROWSER failed\n");
- return E_FAIL;
- }
+ _DoCallback(DFM_INVOKECOMMAND, DFM_CMD_PROPERTIES, NULL);
- /* is the treeview focused */
- HWND hwnd;
- if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwnd)))
- {
- HTREEITEM hItem = TreeView_GetSelection(hwnd);
- if (hItem)
- (void)TreeView_EditLabel(hwnd, hItem);
- }
-
- CComPtr<IShellView> lpSV;
- HRESULT hr = lpSB->QueryActiveShellView(&lpSV);
- if (FAILED(hr))
- {
- ERR("CWM_GETISHELLBROWSER failed\n");
- return hr;
- }
-
- SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
- lpSV->SelectItem(m_apidl[0], selFlags);
return S_OK;
}
+// This code is taken from CNewMenu and should be shared between the 2 classes
HRESULT
-CDefaultContextMenu::DoProperties(
- LPCMINVOKECOMMANDINFO lpcmi)
+CDefaultContextMenu::DoCreateNewFolder(
+ LPCMINVOKECOMMANDINFO lpici)
{
- HRESULT hr = S_OK;
- const ITEMIDLIST *pidlParent = m_pidlFolder, *pidlChild;
+ WCHAR wszPath[MAX_PATH];
+ WCHAR wszName[MAX_PATH];
+ WCHAR wszNewFolder[25];
+ HRESULT hr;
- if (!pidlParent)
- {
- CComPtr<IPersistFolder2> pf;
+ /* Get folder path */
+ hr = SHGetPathFromIDListW(m_pidlFolder, wszPath);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
- /* pidlFolder is optional */
- if (SUCCEEDED(m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
- {
- pf->GetCurFolder((_ITEMIDLIST**)&pidlParent);
- }
- }
+ if (!LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, _countof(wszNewFolder)))
+ return E_FAIL;
- if (m_cidl > 0)
- pidlChild = m_apidl[0];
- else
- {
- /* Set pidlChild to last pidl of current folder */
- if (pidlParent == m_pidlFolder)
- pidlParent = (ITEMIDLIST*)ILClone(pidlParent);
+ /* Create the name of the new directory */
+ if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFolder))
+ return E_FAIL;
- pidlChild = (ITEMIDLIST*)ILClone(ILFindLastID(pidlParent));
- ILRemoveLastID((ITEMIDLIST*)pidlParent);
- }
+ /* Create the new directory and show the appropriate dialog in case of error */
+ if (SHCreateDirectory(lpici->hwnd, wszName) != ERROR_SUCCESS)
+ return E_FAIL;
- if (_ILIsMyComputer(pidlChild))
- {
- if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL))
- hr = E_FAIL;
- }
- else if (_ILIsDesktop(pidlChild))
- {
- if (32 >= (UINT)ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL))
- hr = E_FAIL;
- }
- else if (_ILIsDrive(pidlChild))
- {
- WCHAR wszBuf[MAX_PATH];
- ILGetDisplayName(pidlChild, wszBuf);
- if (!SH_ShowDriveProperties(wszBuf, pidlParent, &pidlChild))
- hr = E_FAIL;
- }
- else if (_ILIsNetHood(pidlChild))
- {
- // FIXME path!
- if (32 >= (UINT)ShellExecuteW(NULL, L"open", L"explorer.exe",
- L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
- NULL, SW_SHOWDEFAULT))
- hr = E_FAIL;
- }
- else if (_ILIsBitBucket(pidlChild))
- {
- /* FIXME: detect the drive path of bitbucket if appropiate */
- if(!SH_ShowRecycleBinProperties(L'C'))
- hr = E_FAIL;
- }
- else
- {
- if (m_cidl > 1)
- WARN("SHMultiFileProperties is not yet implemented\n");
+ /* Show and select the new item in the def view */
+ LPITEMIDLIST pidl;
+ PITEMID_CHILD pidlNewItem;
+ CComPtr<IShellView> psv;
- STRRET strFile;
- hr = m_psf->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strFile);
- if (SUCCEEDED(hr))
- {
- WCHAR wszBuf[MAX_PATH];
- hr = StrRetToBufW(&strFile, pidlChild, wszBuf, _countof(wszBuf));
- if (SUCCEEDED(hr))
- hr = SH_ShowPropertiesDialog(wszBuf, pidlParent, &pidlChild);
- else
- ERR("StrRetToBufW failed\n");
- }
- else
- ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
- }
+ /* Notify the view object about the new item */
+ SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW, (LPCVOID)wszName, NULL);
- /* Free allocated PIDLs */
- if (pidlParent != m_pidlFolder)
- ILFree((ITEMIDLIST*)pidlParent);
- if (m_cidl < 1 || pidlChild != m_apidl[0])
- ILFree((ITEMIDLIST*)pidlChild);
+ if (!m_site)
+ return S_OK;
+
+ /* Get a pointer to the shell view */
+ hr = IUnknown_QueryService(m_site, SID_IFolderView, IID_PPV_ARG(IShellView, &psv));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return S_OK;
+
+ /* Attempt to get the pidl of the new item */
+ hr = SHILCreateFromPathW(wszName, &pidl, NULL);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ pidlNewItem = ILFindLastID(pidl);
+
+ hr = psv->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE |
+ SVSI_FOCUSED | SVSI_SELECT);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
- return hr;
+ SHFree(pidl);
+
+ return S_OK;
}
-HRESULT
-CDefaultContextMenu::DoFormat(
- LPCMINVOKECOMMANDINFO lpcmi)
+PDynamicShellEntry CDefaultContextMenu::GetDynamicEntry(UINT idCmd)
{
- char szDrive[8] = {0};
+ PDynamicShellEntry pEntry = m_pDynamicEntries;
+
+ while(pEntry && idCmd > pEntry->iIdCmdFirst + pEntry->NumIds)
+ pEntry = pEntry->pNext;
- if (!_ILGetDrive(m_apidl[0], szDrive, sizeof(szDrive)))
+ if (!pEntry)
+ return NULL;
+
+ if (idCmd < pEntry->iIdCmdFirst || idCmd > pEntry->iIdCmdFirst + pEntry->NumIds)
+ return NULL;
+
+ 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];
+
+ /* Loop through all the static verbs looking for a match */
+ for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); i++)
{
- ERR("pidl is not a drive\n");
- return E_FAIL;
+ /* We can match both ANSI and unicode strings */
+ if (IsUnicode)
+ {
+ /* The static verbs are ANSI, get a unicode version before doing the compare */
+ SHAnsiToUnicode(g_StaticInvokeCmdMap[i].szStringVerb, UnicodeStr, MAX_VERB);
+ if (!wcscmp(UnicodeStr, (LPWSTR)Verb))
+ {
+ /* Return the Corresponding Id */
+ *idCmd = g_StaticInvokeCmdMap[i].IntVerb;
+ return TRUE;
+ }
+ }
+ else
+ {
+ if (!strcmp(g_StaticInvokeCmdMap[i].szStringVerb, (LPSTR)Verb))
+ {
+ *idCmd = g_StaticInvokeCmdMap[i].IntVerb;
+ return TRUE;
+ }
+ }
}
- SHFormatDrive(lpcmi->hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
- return S_OK;
+ return FALSE;
}
HRESULT
CDefaultContextMenu::DoDynamicShellExtensions(
LPCMINVOKECOMMANDINFO lpcmi)
{
- UINT idCmd = LOWORD(lpcmi->lpVerb);
- PDynamicShellEntry pEntry = m_pDynamicEntries;
-
TRACE("verb %p first %x last %x", lpcmi->lpVerb, m_iIdSHEFirst, m_iIdSHELast);
- while(pEntry && idCmd > pEntry->iIdCmdFirst + pEntry->NumIds)
- pEntry = pEntry->pNext;
-
+ UINT idCmd = LOWORD(lpcmi->lpVerb);
+ PDynamicShellEntry pEntry = GetDynamicEntry(idCmd);
if (!pEntry)
return E_FAIL;
- if (idCmd >= pEntry->iIdCmdFirst && idCmd <= pEntry->iIdCmdFirst + pEntry->NumIds)
- {
- /* invoke the dynamic context menu */
- lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst);
- return pEntry->pCM->InvokeCommand(lpcmi);
- }
-
- return E_FAIL;
+ /* invoke the dynamic context menu */
+ lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst);
+ return pEntry->pCM->InvokeCommand(lpcmi);
}
DWORD
CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry)
{
- LPSHELLBROWSER lpSB;
+ CComPtr<IShellBrowser> psb;
HWND hwndTree;
LPCWSTR FlagsName;
WCHAR wszKey[256];
DWORD wFlags;
DWORD cbVerb;
+ if (!m_site)
+ return 0;
+
/* Get a pointer to the shell browser */
- lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
- if (lpSB == NULL)
+ hr = IUnknown_QueryService(m_site, SID_IShellBrowser, IID_PPV_ARG(IShellBrowser, &psb));
+ if (FAILED_UNEXPECTEDLY(hr))
return 0;
/* See if we are in Explore or Browse mode. If the browser's tree is present, we are in Explore mode.*/
- if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
+ if (SUCCEEDED(psb->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
FlagsName = L"ExplorerFlags";
else
FlagsName = L"BrowserFlags";
/* Try to get the flag from the verb */
- hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"%s\\shell\\%s", pEntry->szClass, pEntry->szVerb);
- if (!SUCCEEDED(hr))
+ hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", pEntry->szVerb);
+ if (FAILED_UNEXPECTEDLY(hr))
return 0;
cbVerb = sizeof(wFlags);
- if (RegGetValueW(HKEY_CLASSES_ROOT, wszKey, FlagsName, RRF_RT_REG_DWORD, NULL, &wFlags, &cbVerb) == ERROR_SUCCESS)
+ if (RegGetValueW(pEntry->hkClass, wszKey, FlagsName, RRF_RT_REG_DWORD, NULL, &wFlags, &cbVerb) == ERROR_SUCCESS)
{
return wFlags;
}
CDefaultContextMenu::TryToBrowse(
LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
{
- LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageW(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+ CComPtr<IShellBrowser> psb;
HRESULT hr;
- if (lpSB == NULL)
+ if (!m_site)
return E_FAIL;
- hr = lpSB->BrowseObject(ILCombine(m_pidlFolder, pidl), wFlags);
+ /* Get a pointer to the shell browser */
+ hr = IUnknown_QueryService(m_site, SID_IShellBrowser, IID_PPV_ARG(IShellBrowser, &psb));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return 0;
- return hr;
+ return psb->BrowseObject(ILCombine(m_pidlFolder, pidl), wFlags);
}
HRESULT
BOOL bHasPath = SHGetPathFromIDListW(pidlFull, wszPath);
WCHAR wszDir[MAX_PATH];
- if(bHasPath)
+ if (bHasPath)
{
wcscpy(wszDir, wszPath);
PathRemoveFileSpec(wszDir);
SHGetPathFromIDListW(m_pidlFolder, wszDir);
}
- HKEY hkeyClass;
- RegOpenKeyExW(HKEY_CLASSES_ROOT, pEntry->szClass, 0, KEY_READ, &hkeyClass);
-
SHELLEXECUTEINFOW sei;
ZeroMemory(&sei, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.lpVerb = pEntry->szVerb;
sei.lpDirectory = wszDir;
sei.lpIDList = pidlFull;
- sei.hkeyClass = hkeyClass;
+ sei.hkeyClass = pEntry->hkClass;
sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST;
if (bHasPath)
{
ShellExecuteExW(&sei);
- RegCloseKey(hkeyClass);
-
ILFree(pidlFull);
return S_OK;
/* Check if we need to browse */
if (wFlags > 0)
{
- /* In xp if we have browsed, we don't open any more folders .
+ /* In xp if we have browsed, we don't open any more folders.
* In win7 we browse to the first folder we find and
- * open new windows fo for each of the rest of the folders */
+ * open new windows for each of the rest of the folders */
if (bBrowsed)
continue;
CDefaultContextMenu::InvokeCommand(
LPCMINVOKECOMMANDINFO lpcmi)
{
- switch(LOWORD(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);
- }
+ CMINVOKECOMMANDINFO LocalInvokeInfo;
+ HRESULT Result;
+ UINT CmdId;
+
+ /* Take a local copy of the fixed members of the
+ struct as we might need to modify the verb */
+ LocalInvokeInfo = *lpcmi;
+
+ /* Check if this is a string verb */
+ if (HIWORD(LocalInvokeInfo.lpVerb))
+ {
+ /* Get the ID which corresponds to this verb, and update our local copy */
+ if (MapVerbToCmdId((LPVOID)LocalInvokeInfo.lpVerb, &CmdId, FALSE))
+ LocalInvokeInfo.lpVerb = MAKEINTRESOURCEA(CmdId);
+ }
+
+ /* Check if this is a Id */
+ switch (LOWORD(LocalInvokeInfo.lpVerb))
+ {
+ case FCIDM_SHVIEW_INSERT:
+ Result = DoPaste(&LocalInvokeInfo, FALSE);
+ break;
+ case FCIDM_SHVIEW_INSERTLINK:
+ Result = DoPaste(&LocalInvokeInfo, TRUE);
+ break;
+ case FCIDM_SHVIEW_OPEN:
+ case FCIDM_SHVIEW_EXPLORE:
+ Result = DoOpenOrExplore(&LocalInvokeInfo);
+ break;
+ case FCIDM_SHVIEW_COPY:
+ case FCIDM_SHVIEW_CUT:
+ Result = DoCopyOrCut(&LocalInvokeInfo, LOWORD(LocalInvokeInfo.lpVerb) == FCIDM_SHVIEW_COPY);
+ break;
+ case FCIDM_SHVIEW_CREATELINK:
+ Result = DoCreateLink(&LocalInvokeInfo);
+ break;
+ case FCIDM_SHVIEW_DELETE:
+ Result = DoDelete(&LocalInvokeInfo);
+ break;
+ case FCIDM_SHVIEW_RENAME:
+ Result = DoRename(&LocalInvokeInfo);
+ break;
+ case FCIDM_SHVIEW_PROPERTIES:
+ Result = DoProperties(&LocalInvokeInfo);
+ break;
+ case FCIDM_SHVIEW_NEWFOLDER:
+ Result = DoCreateNewFolder(&LocalInvokeInfo);
+ break;
+ default:
+ Result = E_UNEXPECTED;
+ break;
+ }
+
+ /* Check for ID's we didn't find a handler for */
+ if (Result == E_UNEXPECTED)
+ {
+ if (m_pDynamicEntries)
+ {
+ if (LOWORD(LocalInvokeInfo.lpVerb) >= m_iIdSHEFirst && LOWORD(LocalInvokeInfo.lpVerb) <= m_iIdSHELast)
+ Result = DoDynamicShellExtensions(&LocalInvokeInfo);
+ }
- if (m_iIdSHEFirst && m_iIdSHELast)
- {
- if (LOWORD(lpcmi->lpVerb) >= m_iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSHELast)
- return DoDynamicShellExtensions(lpcmi);
- }
+ if (m_pStaticEntries)
+ {
+ if (LOWORD(LocalInvokeInfo.lpVerb) >= m_iIdSCMFirst && LOWORD(LocalInvokeInfo.lpVerb) <= m_iIdSCMLast)
+ Result = DoStaticShellExtensions(&LocalInvokeInfo);
+ }
- if (m_iIdSCMFirst && m_iIdSCMLast)
- {
- if (LOWORD(lpcmi->lpVerb) >= m_iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSCMLast)
- return DoStaticShellExtensions(lpcmi);
+ if (m_iIdCBFirst != m_iIdCBLast)
+ {
+ if (LOWORD(LocalInvokeInfo.lpVerb) >= m_iIdCBFirst && LOWORD(LocalInvokeInfo.lpVerb) <= m_iIdCBLast)
+ Result = _DoCallback(DFM_INVOKECOMMAND, LOWORD(LocalInvokeInfo.lpVerb), NULL);
+ }
}
- FIXME("Unhandled Verb %xl\n", LOWORD(lpcmi->lpVerb));
- return E_UNEXPECTED;
+ if (Result == E_UNEXPECTED)
+ ERR("Unhandled Verb %xl\n", LOWORD(LocalInvokeInfo.lpVerb));
+
+ return Result;
}
HRESULT
LPSTR lpszName,
UINT uMaxNameLen)
{
- return S_OK;
+ /* We don't handle the help text yet */
+ if (uFlags == GCS_HELPTEXTA ||
+ uFlags == GCS_HELPTEXTW)
+ {
+ return E_NOTIMPL;
+ }
+
+ /* Loop looking for a matching Id */
+ for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); i++)
+ {
+ if (g_StaticInvokeCmdMap[i].IntVerb == idCommand)
+ {
+ /* Validation just returns S_OK on a match */
+ if (uFlags == GCS_VALIDATEA || uFlags == GCS_VALIDATEW)
+ return S_OK;
+
+ /* Return a copy of the ANSI verb */
+ if (uFlags == GCS_VERBA)
+ return StringCchCopyA(lpszName, uMaxNameLen, g_StaticInvokeCmdMap[i].szStringVerb);
+
+ /* Convert the ANSI verb to unicode and return that */
+ if (uFlags == GCS_VERBW)
+ {
+ if (SHAnsiToUnicode(g_StaticInvokeCmdMap[i].szStringVerb, (LPWSTR)lpszName, uMaxNameLen))
+ return S_OK;
+ }
+ }
+ }
+
+ return E_INVALIDARG;
}
HRESULT
WPARAM wParam,
LPARAM lParam)
{
+ /* FIXME: Should we implement this as well? */
return S_OK;
}
-static
HRESULT
-IDefaultContextMenu_Constructor(
- const DEFCONTEXTMENU *pdcm,
- REFIID riid,
- void **ppv)
+WINAPI
+CDefaultContextMenu::HandleMenuMsg2(
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam,
+ LRESULT *plResult)
{
- if (ppv == NULL)
- return E_POINTER;
- *ppv = NULL;
-
- CComObject<CDefaultContextMenu> *pCM;
- HRESULT hr = CComObject<CDefaultContextMenu>::CreateInstance(&pCM);
- if (FAILED(hr))
- return hr;
- pCM->AddRef(); // CreateInstance returns object with 0 ref count */
-
- CComPtr<IUnknown> pResult;
- hr = pCM->QueryInterface(riid, (void **)&pResult);
- if (FAILED(hr))
+ switch (uMsg)
{
- pCM->Release();
- return hr;
+ case WM_INITMENUPOPUP:
+ {
+ PDynamicShellEntry pEntry = m_pDynamicEntries;
+ while (pEntry)
+ {
+ SHForwardContextMenuMsg(pEntry->pCM, uMsg, wParam, lParam, plResult, TRUE);
+ pEntry = pEntry->pNext;
+ }
+ break;
}
-
- hr = pCM->Initialize(pdcm);
- if (FAILED(hr))
+ case WM_DRAWITEM:
{
- pCM->Release();
- return hr;
+ DRAWITEMSTRUCT* pDrawStruct = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
+ PDynamicShellEntry pEntry = GetDynamicEntry(pDrawStruct->itemID);
+ if (pEntry)
+ SHForwardContextMenuMsg(pEntry->pCM, uMsg, wParam, lParam, plResult, TRUE);
+ break;
}
+ case WM_MEASUREITEM:
+ {
+ MEASUREITEMSTRUCT* pMeasureStruct = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam);
+ PDynamicShellEntry pEntry = GetDynamicEntry(pMeasureStruct->itemID);
+ if (pEntry)
+ SHForwardContextMenuMsg(pEntry->pCM, uMsg, wParam, lParam, plResult, TRUE);
+ break;
+ }
+ case WM_MENUCHAR :
+ /* FIXME */
+ break;
+ default:
+ ERR("Got unknown message:%d\n", uMsg);
+ }
+ return S_OK;
+}
- *ppv = pResult.Detach();
- pCM->Release();
- TRACE("This(%p) cidl %u\n", *ppv, pdcm->cidl);
+HRESULT
+WINAPI
+CDefaultContextMenu::SetSite(IUnknown *pUnkSite)
+{
+ m_site = pUnkSite;
return S_OK;
}
+HRESULT
+WINAPI
+CDefaultContextMenu::GetSite(REFIID riid, void **ppvSite)
+{
+ if (!m_site)
+ return E_FAIL;
+
+ return m_site->QueryInterface(riid, ppvSite);
+}
+
+static
+HRESULT
+CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn, REFIID riid, void **ppv)
+{
+ return ShellObjectCreatorInit<CDefaultContextMenu>(pdcm, lpfn, riid, ppv);
+}
+
/*************************************************************************
* SHCreateDefaultContextMenu [SHELL32.325] Vista API
*
HRESULT
WINAPI
-SHCreateDefaultContextMenu(
- const DEFCONTEXTMENU *pdcm,
- REFIID riid,
- void **ppv)
+SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
{
- *ppv = NULL;
- HRESULT hr = IDefaultContextMenu_Constructor(pdcm, riid, ppv);
- if (FAILED(hr))
- ERR("IDefaultContextMenu_Constructor failed: %x\n", hr);
- TRACE("pcm %p hr %x\n", pdcm, hr);
- return hr;
+ HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, NULL, riid, ppv);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ return S_OK;
}
/*************************************************************************
HRESULT
WINAPI
CDefFolderMenu_Create2(
- LPCITEMIDLIST pidlFolder,
+ PCIDLIST_ABSOLUTE pidlFolder,
HWND hwnd,
UINT cidl,
- LPCITEMIDLIST *apidl,
+ PCUITEMID_CHILD_ARRAY apidl,
IShellFolder *psf,
LPFNDFMCALLBACK lpfn,
UINT nKeys,
const HKEY *ahkeyClsKeys,
IContextMenu **ppcm)
{
- DEFCONTEXTMENU pdcm;
- pdcm.hwnd = hwnd;
- pdcm.pcmcb = NULL;
- pdcm.pidlFolder = pidlFolder;
- pdcm.psf = psf;
- pdcm.cidl = cidl;
- pdcm.apidl = apidl;
- pdcm.punkAssociationInfo = NULL;
- pdcm.cKeys = nKeys;
- pdcm.aKeys = ahkeyClsKeys;
-
- HRESULT hr = SHCreateDefaultContextMenu(&pdcm, IID_PPV_ARG(IContextMenu, ppcm));
- return hr;
-}
+ DEFCONTEXTMENU dcm;
+ dcm.hwnd = hwnd;
+ dcm.pcmcb = NULL;
+ dcm.pidlFolder = pidlFolder;
+ dcm.psf = psf;
+ dcm.cidl = cidl;
+ dcm.apidl = apidl;
+ dcm.punkAssociationInfo = NULL;
+ dcm.cKeys = nKeys;
+ dcm.aKeys = ahkeyClsKeys;
+
+ HRESULT hr = CDefaultContextMenu_CreateInstance(&dcm, lpfn, IID_PPV_ARG(IContextMenu, ppcm));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+ return S_OK;
+}