* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll/win32/shell32/shv_item_new.c
* PURPOSE: provides default context menu implementation
- * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
+ * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
*/
/*
TODO:
-1. In DoStaticShellExtensions, check for "Explore" and "Open" verbs, and for BrowserFlags or
- ExplorerFlags under those entries. These flags indicate if we should browse to the new item
- instead of attempting to open it.
-2. The code in NotifyShellViewWindow to deliver commands to the view is broken. It is an excellent
+ 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>
+#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmenu);
UINT iIdCmdFirst;
UINT NumIds;
CLSID ClassID;
- IContextMenu *CMenu;
- struct _DynamicShellEntry_ *Next;
+ IContextMenu *pCM;
+ struct _DynamicShellEntry_ *pNext;
} DynamicShellEntry, *PDynamicShellEntry;
typedef struct _StaticShellEntry_
{
LPWSTR szVerb;
LPWSTR szClass;
- struct _StaticShellEntry_ *Next;
+ struct _StaticShellEntry_ *pNext;
} StaticShellEntry, *PStaticShellEntry;
class CDefaultContextMenu :
public IContextMenu2
{
private:
- DEFCONTEXTMENU dcm;
- IDataObject *pDataObj;
- DWORD bGroupPolicyActive;
- PDynamicShellEntry dhead; /* first dynamic shell extension entry */
- UINT iIdSHEFirst; /* first used id */
- UINT iIdSHELast; /* last used id */
- PStaticShellEntry shead; /* first static shell extension entry */
- UINT iIdSCMFirst; /* first static used id */
- UINT iIdSCMLast; /* last static used id */
- public:
- CDefaultContextMenu();
- ~CDefaultContextMenu();
- HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm);
- void AddStaticEntry(const WCHAR *szVerb, const WCHAR *szClass);
- void AddStaticEntryForKey(HKEY hKey, const WCHAR *szClass);
- void AddStaticEntryForFileClass(const WCHAR *szExt);
- BOOL IsShellExtensionAlreadyLoaded(const CLSID *szClass);
- HRESULT LoadDynamicContextMenuHandler(HKEY hKey, const CLSID *szClass, BOOL bExternalInit);
- UINT EnumerateDynamicContextHandlerForKey(HKEY hRootKey);
- UINT InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast);
+ DEFCONTEXTMENU m_Dcm;
+ IDataObject *m_pDataObj;
+ LPCITEMIDLIST m_pidlFolder;
+ DWORD m_bGroupPolicyActive;
+ PDynamicShellEntry m_pDynamicEntries; /* first dynamic shell extension entry */
+ UINT m_iIdSHEFirst; /* first used id */
+ UINT m_iIdSHELast; /* last used id */
+ PStaticShellEntry m_pStaticEntries; /* first static shell extension entry */
+ UINT m_iIdSCMFirst; /* first static used id */
+ UINT m_iIdSCMLast; /* last static used id */
+
+ void AddStaticEntry(LPCWSTR pwszVerb, LPCWSTR pwszClass);
+ void AddStaticEntryForKey(HKEY hKey, LPCWSTR pwszClass);
+ void AddStaticEntryForFileClass(LPCWSTR pwszExt);
+ 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 AddStaticContextMenusToMenu(HMENU hMenu, UINT IndexMenu);
UINT BuildShellItemContextMenu(HMENU hMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
- HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi);
+ HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink);
HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoDelete(LPCMINVOKECOMMANDINFO lpcmi);
HRESULT DoFormat(LPCMINVOKECOMMANDINFO lpcmi);
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);
+
+ public:
+ CDefaultContextMenu();
+ ~CDefaultContextMenu();
+ HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm);
// IContextMenu
virtual HRESULT WINAPI QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
CDefaultContextMenu::CDefaultContextMenu()
{
- memset (&dcm, 0, sizeof(dcm));
- pDataObj = NULL;
- bGroupPolicyActive = 0;
- dhead = NULL;
- iIdSHEFirst = 0;
- iIdSHELast = 0;
- shead = NULL;
- iIdSCMFirst = 0;
- iIdSCMLast = 0;
+ memset(&m_Dcm, 0, sizeof(m_Dcm));
+ m_pDataObj = NULL;
+ m_pidlFolder = NULL;
+ m_bGroupPolicyActive = 0;
+ m_pDynamicEntries = NULL;
+ m_iIdSHEFirst = 0;
+ m_iIdSHELast = 0;
+ m_pStaticEntries = NULL;
+ m_iIdSCMFirst = 0;
+ m_iIdSCMLast = 0;
}
CDefaultContextMenu::~CDefaultContextMenu()
{
- PDynamicShellEntry dEntry, dNext;
- PStaticShellEntry sEntry, sNext;
-
- /* free dynamic shell extension entries */
- dEntry = dhead;
- while (dEntry)
+ /* Free dynamic shell extension entries */
+ PDynamicShellEntry pDynamicEntry = m_pDynamicEntries, pNextDynamic;
+ while (pDynamicEntry)
{
- dNext = dEntry->Next;
- dEntry->CMenu->Release();
- HeapFree(GetProcessHeap(), 0, dEntry);
- dEntry = dNext;
+ pNextDynamic = pDynamicEntry->pNext;
+ pDynamicEntry->pCM->Release();
+ HeapFree(GetProcessHeap(), 0, pDynamicEntry);
+ pDynamicEntry = pNextDynamic;
}
- /* free static shell extension entries */
- sEntry = shead;
- while (sEntry)
+
+ /* Free static shell extension entries */
+ PStaticShellEntry pStaticEntry = m_pStaticEntries, pNextStatic;
+ while (pStaticEntry)
{
- sNext = sEntry->Next;
- HeapFree(GetProcessHeap(), 0, sEntry->szClass);
- HeapFree(GetProcessHeap(), 0, sEntry->szVerb);
- HeapFree(GetProcessHeap(), 0, sEntry);
- sEntry = sNext;
+ pNextStatic = pStaticEntry->pNext;
+ HeapFree(GetProcessHeap(), 0, pStaticEntry->szClass);
+ HeapFree(GetProcessHeap(), 0, pStaticEntry->szVerb);
+ HeapFree(GetProcessHeap(), 0, pStaticEntry);
+ pStaticEntry = pNextStatic;
}
+
+ if (m_pidlFolder)
+ ILFree((_ITEMIDLIST*)m_pidlFolder);
+ if (m_pDataObj)
+ m_pDataObj->Release();
}
HRESULT WINAPI CDefaultContextMenu::Initialize(const DEFCONTEXTMENU *pdcm)
{
- IDataObject *newDataObj;
+ IDataObject *pDataObj;
+
+ TRACE("cidl %u\n", pdcm->cidl);
+ if (SUCCEEDED(SHCreateDataObject(pdcm->pidlFolder, pdcm->cidl, pdcm->apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
+ m_pDataObj = pDataObj;
- TRACE("cidl %u\n", dcm.cidl);
- if (SUCCEEDED(SHCreateDataObject(pdcm->pidlFolder, pdcm->cidl, pdcm->apidl, NULL, IID_IDataObject, (void**)&newDataObj)))
- pDataObj = newDataObj;
- CopyMemory(&dcm, pdcm, sizeof(DEFCONTEXTMENU));
+ if (!pdcm->cidl)
+ {
+ /* Init pidlFolder only if it is background context menu. See IShellExtInit::Initialize */
+ if (pdcm->pidlFolder)
+ m_pidlFolder = ILClone(pdcm->pidlFolder);
+ else
+ {
+ IPersistFolder2 *pf = NULL;
+ if (SUCCEEDED(pdcm->psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
+ {
+ if (FAILED(pf->GetCurFolder((_ITEMIDLIST**)&m_pidlFolder)))
+ ERR("GetCurFolder failed\n");
+ pf->Release();
+ }
+ }
+ TRACE("pidlFolder %p\n", m_pidlFolder);
+ }
+
+ CopyMemory(&m_Dcm, pdcm, sizeof(DEFCONTEXTMENU));
return S_OK;
}
void
CDefaultContextMenu::AddStaticEntry(const WCHAR *szVerb, const WCHAR *szClass)
{
- PStaticShellEntry curEntry;
- PStaticShellEntry lastEntry = NULL;
-
- curEntry = shead;
- while(curEntry)
+ PStaticShellEntry pEntry = m_pStaticEntries, pLastEntry = NULL;
+ while(pEntry)
{
- if (!wcsicmp(curEntry->szVerb, szVerb))
+ if (!wcsicmp(pEntry->szVerb, szVerb))
{
/* entry already exists */
return;
}
- lastEntry = curEntry;
- curEntry = curEntry->Next;
+ pLastEntry = pEntry;
+ pEntry = pEntry->pNext;
}
TRACE("adding verb %s szClass %s\n", debugstr_w(szVerb), debugstr_w(szClass));
- curEntry = (StaticShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(StaticShellEntry));
- if (curEntry)
+ pEntry = (StaticShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(StaticShellEntry));
+ if (pEntry)
{
- curEntry->Next = NULL;
- curEntry->szVerb = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(szVerb) + 1) * sizeof(WCHAR));
- if (curEntry->szVerb)
- wcscpy(curEntry->szVerb, szVerb);
- curEntry->szClass = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(szClass) + 1) * sizeof(WCHAR));
- if (curEntry->szClass)
- wcscpy(curEntry->szClass, szClass);
+ pEntry->pNext = NULL;
+ 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);
}
if (!wcsicmp(szVerb, L"open"))
{
/* open verb is always inserted in front */
- curEntry->Next = shead;
- shead = curEntry;
- return;
+ pEntry->pNext = m_pStaticEntries;
+ m_pStaticEntries = pEntry;
}
-
- if (lastEntry)
- lastEntry->Next = curEntry;
+ else if (pLastEntry)
+ pLastEntry->pNext = pEntry;
else
- shead = curEntry;
+ m_pStaticEntries = pEntry;
}
void
-CDefaultContextMenu::AddStaticEntryForKey(HKEY hKey, const WCHAR * szClass)
+CDefaultContextMenu::AddStaticEntryForKey(HKEY hKey, const WCHAR *pwszClass)
{
- LONG result;
- DWORD dwIndex;
- WCHAR szName[40];
- DWORD dwSize;
+ WCHAR wszName[40];
+ DWORD cchName, dwIndex = 0;
- dwIndex = 0;
- do
+ TRACE("AddStaticEntryForKey %x %ls\n", hKey, pwszClass);
+
+ while(TRUE)
{
- szName[0] = 0;
- dwSize = sizeof(szName) / sizeof(WCHAR);
- result = RegEnumKeyExW(hKey, dwIndex, szName, &dwSize, NULL, NULL, NULL, NULL);
- if (result == ERROR_SUCCESS)
- AddStaticEntry(szName, szClass);
+ cchName = _countof(wszName);
+ if (RegEnumKeyExW(hKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
+ break;
- dwIndex++;
- } while(result == ERROR_SUCCESS);
+ AddStaticEntry(wszName, pwszClass);
+ }
}
void
BOOL
HasClipboardData()
{
- BOOL ret = FALSE;
- IDataObject * pda;
+ BOOL bRet = FALSE;
+ IDataObject *pDataObj;
- if(SUCCEEDED(OleGetClipboard(&pda)))
+ if(SUCCEEDED(OleGetClipboard(&pDataObj)))
{
STGMEDIUM medium;
FORMATETC formatetc;
- TRACE("pda=%p\n", pda);
+ TRACE("pDataObj=%p\n", pDataObj);
/* Set the FORMATETC structure*/
InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
- if(SUCCEEDED(pda->GetData(&formatetc, &medium)))
+ if(SUCCEEDED(pDataObj->GetData(&formatetc, &medium)))
{
- ret = TRUE;
+ bRet = TRUE;
ReleaseStgMedium(&medium);
}
- pda->Release();
+ pDataObj->Release();
}
- return ret;
+ return bRet;
}
static
}
BOOL
-CDefaultContextMenu::IsShellExtensionAlreadyLoaded(const CLSID * szClass)
+CDefaultContextMenu::IsShellExtensionAlreadyLoaded(const CLSID *pclsid)
{
- PDynamicShellEntry curEntry = dhead;
+ PDynamicShellEntry pEntry = m_pDynamicEntries;
- while(curEntry)
+ while (pEntry)
{
- if (!memcmp(&curEntry->ClassID, szClass, sizeof(CLSID)))
+ if (!memcmp(&pEntry->ClassID, pclsid, sizeof(CLSID)))
return TRUE;
- curEntry = curEntry->Next;
+ pEntry = pEntry->pNext;
}
+
return FALSE;
}
-
HRESULT
-CDefaultContextMenu::LoadDynamicContextMenuHandler(HKEY hKey, const CLSID *pClass, BOOL bExternalInit)
+CDefaultContextMenu::LoadDynamicContextMenuHandler(HKEY hKey, const CLSID *pclsid)
{
HRESULT hr;
- IContextMenu *cmobj;
- IShellExtInit *shext;
- PDynamicShellEntry curEntry;
- LPOLESTR pstr;
- StringFromCLSID(*pClass, &pstr);
+ TRACE("LoadDynamicContextMenuHandler entered with This %p hKey %p pclsid %s\n", this, hKey, wine_dbgstr_guid(pclsid));
- TRACE("LoadDynamicContextMenuHandler entered with This %p hKey %p pClass %s bExternalInit %u\n", this, hKey, wine_dbgstr_guid(pClass), bExternalInit);
-
- if (IsShellExtensionAlreadyLoaded(pClass))
+ if (IsShellExtensionAlreadyLoaded(pclsid))
return S_OK;
- hr = SHCoCreateInstance(NULL, pClass, NULL, IID_IContextMenu, (void**)&cmobj);
+ IContextMenu *pcm;
+ hr = SHCoCreateInstance(NULL, pclsid, NULL, IID_PPV_ARG(IContextMenu, &pcm));
if (hr != S_OK)
{
ERR("SHCoCreateInstance failed %x\n", GetLastError());
return hr;
}
- if (bExternalInit)
+ IShellExtInit *pExtInit;
+ hr = pcm->QueryInterface(IID_PPV_ARG(IShellExtInit, &pExtInit));
+ if (hr != S_OK)
{
- hr = cmobj->QueryInterface(IID_IShellExtInit, (void**)&shext);
- if (hr != S_OK)
- {
- ERR("Failed to query for interface IID_IShellExtInit hr %x pClass %s\n", hr, wine_dbgstr_guid(pClass));
- cmobj->Release();
- return hr;
- }
+ ERR("Failed to query for interface IID_IShellExtInit hr %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid));
+ pcm->Release();
+ return hr;
+ }
- hr = shext->Initialize(NULL, pDataObj, hKey);
- shext->Release();
- if (hr != S_OK)
- {
- TRACE("Failed to initialize shell extension error %x pClass %s\n", hr, wine_dbgstr_guid(pClass));
- cmobj->Release();
- return hr;
- }
+ hr = pExtInit->Initialize(m_pidlFolder, m_pDataObj, hKey);
+ pExtInit->Release();
+ if (hr != S_OK)
+ {
+ TRACE("Failed to initialize shell extension error %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid));
+ pcm->Release();
+ return hr;
}
- curEntry = (DynamicShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(DynamicShellEntry));
- if(!curEntry)
+ PDynamicShellEntry pEntry = (DynamicShellEntry *)HeapAlloc(GetProcessHeap(), 0, sizeof(DynamicShellEntry));
+ if (!pEntry)
{
- cmobj->Release();
+ pcm->Release();
return E_OUTOFMEMORY;
}
- curEntry->iIdCmdFirst = 0;
- curEntry->Next = NULL;
- curEntry->NumIds = 0;
- curEntry->CMenu = cmobj;
- memcpy(&curEntry->ClassID, pClass, sizeof(CLSID));
+ pEntry->iIdCmdFirst = 0;
+ pEntry->pNext = NULL;
+ pEntry->NumIds = 0;
+ pEntry->pCM = pcm;
+ memcpy(&pEntry->ClassID, pclsid, sizeof(CLSID));
- if (dhead)
+ if (m_pDynamicEntries)
{
- PDynamicShellEntry pEntry = dhead;
+ PDynamicShellEntry pLastEntry = m_pDynamicEntries;
- while (pEntry->Next)
- pEntry = pEntry->Next;
+ while (pLastEntry->pNext)
+ pLastEntry = pLastEntry->pNext;
- pEntry->Next = curEntry;
+ pLastEntry->pNext = pEntry;
}
else
- dhead = curEntry;
+ m_pDynamicEntries = pEntry;
- return hr;
+ return S_OK;
}
-UINT
+BOOL
CDefaultContextMenu::EnumerateDynamicContextHandlerForKey(HKEY hRootKey)
{
- WCHAR szKey[MAX_PATH] = {0};
- WCHAR szName[MAX_PATH] = {0};
- DWORD dwIndex, dwName;
- LONG res;
- HRESULT hResult;
- UINT index;
- CLSID clsid;
+
+ WCHAR wszName[MAX_PATH], wszBuf[MAX_PATH], *pwszClsid;
+ DWORD cchName;
+ HRESULT hr;
HKEY hKey;
if (RegOpenKeyExW(hRootKey, L"shellex\\ContextMenuHandlers", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
- TRACE("RegOpenKeyExW failed for key %s\n", debugstr_w(szKey));
- return 0;
+ TRACE("RegOpenKeyExW failed\n");
+ return FALSE;
}
- dwIndex = 0;
- index = 0;
- do
+ DWORD dwIndex = 0;
+ while (TRUE)
{
- dwName = MAX_PATH;
- res = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL);
- if (res == ERROR_SUCCESS)
+ cchName = _countof(wszName);
+ if (RegEnumKeyExW(hKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
+ break;
+
+ /* Key name or key value is CLSID */
+ CLSID clsid;
+ hr = CLSIDFromString(wszName, &clsid);
+ if (hr == S_OK)
+ pwszClsid = wszName;
+ else
{
- hResult = CLSIDFromString(szName, &clsid);
- if (hResult != S_OK)
- {
- dwName = MAX_PATH;
- if (RegGetValueW(hKey, szName, NULL, RRF_RT_REG_SZ, NULL, szKey, &dwName) == ERROR_SUCCESS)
- {
- hResult = CLSIDFromString(szKey, &clsid);
- }
- }
- if (SUCCEEDED(hResult))
+ DWORD cchBuf = _countof(wszBuf);
+ if (RegGetValueW(hKey, wszName, NULL, RRF_RT_REG_SZ, NULL, wszBuf, &cchBuf) == ERROR_SUCCESS)
+ hr = CLSIDFromString(wszBuf, &clsid);
+ pwszClsid = wszBuf;
+ }
+ if (SUCCEEDED(hr))
+ {
+ if (m_bGroupPolicyActive)
{
- if (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",
- szKey,
- RRF_RT_REG_SZ,
- NULL,
- NULL,
- &dwName) == ERROR_SUCCESS)
- {
- LoadDynamicContextMenuHandler(hKey, &clsid, TRUE);
- }
- }
- else
- {
- LoadDynamicContextMenuHandler(hKey, &clsid, TRUE);
+ LoadDynamicContextMenuHandler(hKey, &clsid);
}
}
+ else
+ LoadDynamicContextMenuHandler(hKey, &clsid);
}
- dwIndex++;
- } while(res == ERROR_SUCCESS);
+ }
RegCloseKey(hKey);
- return index;
+ return TRUE;
}
UINT
-CDefaultContextMenu::InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast)
+CDefaultContextMenu::InsertMenuItemsOfDynamicContextMenuExtension(HMENU hMenu, UINT IndexMenu, UINT idCmdFirst, UINT idCmdLast)
{
- PDynamicShellEntry curEntry;
- HRESULT hResult;
-
- if (!dhead)
+ if (!m_pDynamicEntries)
{
- iIdSHEFirst = 0;
- iIdSHELast = 0;
- return indexMenu;
+ m_iIdSHEFirst = 0;
+ m_iIdSHELast = 0;
+ return IndexMenu;
}
- curEntry = dhead;
+ PDynamicShellEntry pEntry = m_pDynamicEntries;
idCmdFirst = 0x5000;
idCmdLast = 0x6000;
- iIdSHEFirst = idCmdFirst;
+ m_iIdSHEFirst = idCmdFirst;
do
{
- hResult = curEntry->CMenu->QueryContextMenu(hMenu, indexMenu++, idCmdFirst, idCmdLast, CMF_NORMAL);
- if (SUCCEEDED(hResult))
+ HRESULT hr = pEntry->pCM->QueryContextMenu(hMenu, IndexMenu++, idCmdFirst, idCmdLast, CMF_NORMAL);
+ if (SUCCEEDED(hr))
{
- curEntry->iIdCmdFirst = idCmdFirst;
- curEntry->NumIds = LOWORD(hResult);
- indexMenu += curEntry->NumIds;
- idCmdFirst += curEntry->NumIds + 0x10;
+ pEntry->iIdCmdFirst = idCmdFirst;
+ pEntry->NumIds = LOWORD(hr);
+ IndexMenu += pEntry->NumIds;
+ idCmdFirst += pEntry->NumIds + 0x10;
}
- TRACE("curEntry %p hresult %x contextmenu %p cmdfirst %x num ids %x\n", curEntry, hResult, curEntry->CMenu, curEntry->iIdCmdFirst, curEntry->NumIds);
- curEntry = curEntry->Next;
- } while(curEntry);
+ TRACE("pEntry %p hr %x contextmenu %p cmdfirst %x num ids %x\n", pEntry, hr, pEntry->pCM, pEntry->iIdCmdFirst, pEntry->NumIds);
+ pEntry = pEntry->pNext;
+ } while (pEntry);
- iIdSHELast = idCmdFirst;
- TRACE("SH_LoadContextMenuHandlers first %x last %x\n", iIdSHEFirst, iIdSHELast);
- return indexMenu;
+ m_iIdSHELast = idCmdFirst;
+ TRACE("SH_LoadContextMenuHandlers first %x last %x\n", m_iIdSHEFirst, m_iIdSHELast);
+ return IndexMenu;
}
UINT
UINT iIdCmdLast,
UINT uFlags)
{
- MENUITEMINFOW mii;
- WCHAR szBuffer[MAX_PATH];
- UINT indexMenu = 0;
+ UINT IndexMenu = 0;
HMENU hSubMenu;
- HKEY hKey;
-
- ZeroMemory(&mii, sizeof(mii));
TRACE("BuildBackgroundContextMenu entered\n");
- if (!_ILIsDesktop(dcm.pidlFolder))
+ if (!_ILIsDesktop(m_pidlFolder))
{
+ WCHAR wszBuf[MAX_PATH];
+
/* view option is only available in browsing mode */
- hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
- if (hSubMenu)
+ hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_001");
+ if (hSubMenu && LoadStringW(shell32_hInstance, FCIDM_SHVIEW_VIEW, wszBuf, _countof(wszBuf)))
{
- szBuffer[0] = 0;
- LoadStringW(shell32_hInstance, FCIDM_SHVIEW_VIEW, szBuffer, MAX_PATH);
- szBuffer[MAX_PATH-1] = 0;
-
- TRACE("szBuffer %s\n", debugstr_w(szBuffer));
+ 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 = szBuffer;
- mii.cch = wcslen( mii.dwTypeData );
+ mii.dwTypeData = wszBuf;
+ mii.cch = wcslen(mii.dwTypeData);
mii.fState = MFS_ENABLED;
mii.hSubMenu = hSubMenu;
- InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
+ 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;
+ iIdCmdFirst = Shell_MergeMenus(hMenu, GetSubMenu(hSubMenu, 0), IndexMenu, 0, 0xFFFF, MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS) + 1;
DestroyMenu(hSubMenu);
}
TRACE("disabling paste options\n");
DisablePasteOptions(hMenu);
}
- /* load extensions from HKCR\* key */
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT,
- L"*",
- 0,
- KEY_READ,
- &hKey) == ERROR_SUCCESS)
- {
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
- }
- /* load create new shell extension */
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT,
- L"CLSID\\{D969A300-E7FF-11d0-A93B-00A0C90F2719}",
- 0,
- KEY_READ,
- &hKey) == ERROR_SUCCESS)
+ /* Directory is progid of filesystem folders only */
+ LPITEMIDLIST pidlFolderLast = ILFindLastID(m_pidlFolder);
+ if (_ILIsDesktop(pidlFolderLast) || _ILIsDrive(pidlFolderLast) || _ILIsFolder(pidlFolderLast))
{
- LoadDynamicContextMenuHandler(hKey, &CLSID_NewMenu, TRUE);
- RegCloseKey(hKey);
- }
+ /* 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);
+ 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)
{
MENUITEMINFOW mii;
UINT idResource;
- PStaticShellEntry curEntry;
- WCHAR szVerb[40];
- DWORD dwSize;
+ WCHAR wszVerb[40];
UINT fState;
- UINT Length;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
mii.fType = MFT_STRING;
- mii.fState = MFS_ENABLED;
mii.wID = 0x4000;
mii.dwTypeData = NULL;
- iIdSCMFirst = mii.wID;
+ m_iIdSCMFirst = mii.wID;
- curEntry = shead;
+ PStaticShellEntry pEntry = m_pStaticEntries;
- while(curEntry)
+ while (pEntry)
{
fState = MFS_ENABLED;
mii.dwTypeData = NULL;
- if (!wcsicmp(curEntry->szVerb, L"open"))
+ if (!wcsicmp(pEntry->szVerb, L"open"))
{
fState |= MFS_DEFAULT;
idResource = IDS_OPEN_VERB;
}
- else if (!wcsicmp(curEntry->szVerb, L"explore"))
+ else if (!wcsicmp(pEntry->szVerb, L"explore"))
idResource = IDS_EXPLORE_VERB;
- else if (!wcsicmp(curEntry->szVerb, L"runas"))
+ else if (!wcsicmp(pEntry->szVerb, L"runas"))
idResource = IDS_RUNAS_VERB;
- else if (!wcsicmp(curEntry->szVerb, L"edit"))
+ else if (!wcsicmp(pEntry->szVerb, L"edit"))
idResource = IDS_EDIT_VERB;
- else if (!wcsicmp(curEntry->szVerb, L"find"))
+ else if (!wcsicmp(pEntry->szVerb, L"find"))
idResource = IDS_FIND_VERB;
- else if (!wcsicmp(curEntry->szVerb, L"print"))
+ else if (!wcsicmp(pEntry->szVerb, L"print"))
idResource = IDS_PRINT_VERB;
- else if (!wcsicmp(curEntry->szVerb, L"printto"))
+ else if (!wcsicmp(pEntry->szVerb, L"printto"))
{
- curEntry = curEntry->Next;
+ pEntry = pEntry->pNext;
continue;
}
else
idResource = 0;
+ /* By default use verb for menu item name */
+ mii.dwTypeData = pEntry->szVerb;
+
if (idResource > 0)
{
- if (LoadStringW(shell32_hInstance, idResource, szVerb, sizeof(szVerb) / sizeof(WCHAR)))
- mii.dwTypeData = szVerb; /* use translated verb */
+ if (LoadStringW(shell32_hInstance, idResource, wszVerb, _countof(wszVerb)))
+ mii.dwTypeData = wszVerb; /* use translated verb */
else
- ERR("Failed to load string, defaulting to NULL value for mii.dwTypeData\n");
+ ERR("Failed to load string\n");
}
else
{
WCHAR wszKey[256];
- Length = wcslen(curEntry->szClass) + wcslen(curEntry->szVerb) + 8;
- if (Length < sizeof(wszKey) / sizeof(WCHAR))
+ HRESULT hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"%s\\shell\\%s", pEntry->szClass, pEntry->szVerb);
+
+ if (SUCCEEDED(hr))
{
- wcscpy(wszKey, curEntry->szClass);
- wcscat(wszKey, L"\\shell\\");
- wcscat(wszKey, curEntry->szVerb);
- dwSize = sizeof(szVerb);
+ DWORD cbVerb = sizeof(wszVerb);
- if (RegGetValueW(HKEY_CLASSES_ROOT, wszKey, NULL, RRF_RT_REG_SZ, NULL, szVerb, &dwSize) == ERROR_SUCCESS)
- mii.dwTypeData = szVerb; /* use description for the menu entry */
- else
- mii.dwTypeData = curEntry->szVerb; /* use verb for the menu entry */
+ 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 */
}
}
mii.cch = wcslen(mii.dwTypeData);
mii.fState = fState;
- InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
+ InsertMenuItemW(hMenu, IndexMenu++, TRUE, &mii);
mii.wID++;
- curEntry = curEntry->Next;
+ pEntry = pEntry->pNext;
}
- iIdSCMLast = mii.wID - 1;
- return indexMenu;
+
+ m_iIdSCMLast = mii.wID - 1;
+ return IndexMenu;
}
void WINAPI _InsertMenuItemW(
- HMENU hmenu,
+ HMENU hMenu,
UINT indexMenu,
BOOL fByPosition,
UINT wID,
UINT fState)
{
MENUITEMINFOW mii;
- WCHAR szText[100];
+ WCHAR wszText[100];
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
if (fType == MFT_SEPARATOR)
- {
mii.fMask = MIIM_ID | MIIM_TYPE;
- }
else if (fType == MFT_STRING)
{
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
if ((ULONG_PTR)HIWORD((ULONG_PTR)dwTypeData) == 0)
{
- if (LoadStringW(shell32_hInstance, LOWORD((ULONG_PTR)dwTypeData), szText, sizeof(szText) / sizeof(WCHAR)))
- {
- szText[(sizeof(szText)/sizeof(WCHAR))-1] = 0;
- mii.dwTypeData = szText;
- }
+ if (LoadStringW(shell32_hInstance, LOWORD((ULONG_PTR)dwTypeData), wszText, _countof(wszText)))
+ mii.dwTypeData = wszText;
else
{
ERR("failed to load string %p\n", dwTypeData);
}
}
else
- {
- mii.dwTypeData = (LPWSTR) dwTypeData;
- }
+ mii.dwTypeData = (LPWSTR)dwTypeData;
mii.fState = fState;
}
mii.wID = wID;
mii.fType = fType;
- InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii);
+ InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
}
UINT
UINT iIdCmdLast,
UINT uFlags)
{
- WCHAR szPath[MAX_PATH];
- WCHAR szTemp[40];
HKEY hKey;
- UINT indexMenu;
- SFGAOF rfg;
HRESULT hr;
- BOOL bAddSep = FALSE;
- GUID * guid;
- BOOL bClipboardData;
- STRRET strFile;
- LPWSTR pOffset;
- DWORD dwSize;
TRACE("BuildShellItemContextMenu entered\n");
+ ASSERT(m_Dcm.cidl >= 1);
- hr = dcm.psf->GetDisplayNameOf(dcm.apidl[0], SHGDN_FORPARSING, &strFile);
+ STRRET strFile;
+ hr = m_Dcm.psf->GetDisplayNameOf(m_Dcm.apidl[0], SHGDN_FORPARSING, &strFile);
if (hr == S_OK)
{
- hr = StrRetToBufW(&strFile, dcm.apidl[0], szPath, MAX_PATH);
+ WCHAR wszPath[MAX_PATH];
+ hr = StrRetToBufW(&strFile, m_Dcm.apidl[0], wszPath, _countof(wszPath));
if (hr == S_OK)
{
- pOffset = wcsrchr(szPath, L'.');
- if (pOffset)
+ LPCWSTR pwszExt = PathFindExtensionW(wszPath);
+ if (pwszExt[0])
{
/* enumerate dynamic/static for a given file class */
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pOffset, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
/* add static verbs */
- AddStaticEntryForFileClass(pOffset);
+ AddStaticEntryForFileClass(pwszExt);
+
/* load dynamic extensions from file extension key */
EnumerateDynamicContextHandlerForKey(hKey);
RegCloseKey(hKey);
}
- dwSize = sizeof(szTemp);
- if (RegGetValueW(HKEY_CLASSES_ROOT, pOffset, NULL, RRF_RT_REG_SZ, NULL, szTemp, &dwSize) == ERROR_SUCCESS)
+
+ 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, szTemp, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTemp, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
/* add static verbs from progid key */
- AddStaticEntryForFileClass(szTemp);
+ 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 */
else
ERR("GetDisplayNameOf failed: %x\n", hr);
- guid = _ILGetGUIDPointer(dcm.apidl[0]);
- if (guid)
+ GUID *pGuid = _ILGetGUIDPointer(m_Dcm.apidl[0]);
+ if (pGuid)
{
LPOLESTR pwszCLSID;
WCHAR buffer[60];
wcscpy(buffer, L"CLSID\\");
- hr = StringFromCLSID(*guid, &pwszCLSID);
+ hr = StringFromCLSID(*pGuid, &pwszCLSID);
if (hr == S_OK)
{
wcscpy(&buffer[6], pwszCLSID);
}
}
- if (_ILIsDrive(dcm.apidl[0]))
+ if (_ILIsDrive(m_Dcm.apidl[0]))
{
AddStaticEntryForFileClass(L"Drive");
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Drive", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
}
/* add static actions */
- rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
- hr = dcm.psf->GetAttributesOf(dcm.cidl, dcm.apidl, &rfg);
+ SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
+ hr = m_Dcm.psf->GetAttributesOf(m_Dcm.cidl, m_Dcm.apidl, &rfg);
if (FAILED(hr))
{
ERR("GetAttributesOf failed: %x\n", hr);
rfg = 0;
}
- if ((rfg & SFGAO_FOLDER) || _ILIsControlPanel(dcm.apidl[dcm.cidl]))
+ if (rfg & SFGAO_FOLDER)
{
/* add the default verbs open / explore */
AddStaticEntryForFileClass(L"Folder");
- AddStaticEntryForFileClass(L"Directory");
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Folder", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
EnumerateDynamicContextHandlerForKey(hKey);
RegCloseKey(hKey);
}
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Directory", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+
+ /* Directory is only loaded for real filesystem directories */
+ if (_ILIsFolder(m_Dcm.apidl[0]))
{
- EnumerateDynamicContextHandlerForKey(hKey);
- RegCloseKey(hKey);
+ AddStaticEntryForFileClass(L"Directory");
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"Directory", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
+ {
+ EnumerateDynamicContextHandlerForKey(hKey);
+ RegCloseKey(hKey);
+ }
}
}
- if (rfg & SFGAO_FILESYSTEM)
+ /* AllFilesystemObjects class is loaded only for files and directories */
+ if (_ILIsFolder(m_Dcm.apidl[0]) || _ILIsValue(m_Dcm.apidl[0]))
{
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, L"AllFilesystemObjects", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
}
/* add static context menu handlers */
- indexMenu = AddStaticContextMenusToMenu(hMenu, 0);
+ UINT IndexMenu = AddStaticContextMenusToMenu(hMenu, 0);
+
/* now process dynamic context menu handlers */
- indexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, indexMenu, iIdCmdFirst, iIdCmdLast);
- TRACE("indexMenu %d\n", indexMenu);
+ BOOL bAddSep = FALSE;
+ IndexMenu = InsertMenuItemsOfDynamicContextMenuExtension(hMenu, IndexMenu, iIdCmdFirst, iIdCmdLast);
+ TRACE("IndexMenu %d\n", IndexMenu);
- if (_ILIsDrive(dcm.apidl[0]))
+ if (_ILIsDrive(m_Dcm.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);
+ * 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;
}
- bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM));
+ BOOL bClipboardData = (HasClipboardData() && (rfg & SFGAO_FILESYSTEM));
if (rfg & (SFGAO_CANCOPY | SFGAO_CANMOVE) || bClipboardData)
{
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
if (rfg & SFGAO_CANMOVE)
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, MAKEINTRESOURCEW(IDS_CUT), MFS_ENABLED);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_CUT, MFT_STRING, MAKEINTRESOURCEW(IDS_CUT), MFS_ENABLED);
if (rfg & SFGAO_CANCOPY)
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_COPY, MFT_STRING, MAKEINTRESOURCEW(IDS_COPY), MFS_ENABLED);
+ _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_INSERT), MFS_ENABLED);
bAddSep = TRUE;
}
if (rfg & SFGAO_CANLINK)
{
bAddSep = FALSE;
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_CREATELINK, MFT_STRING, MAKEINTRESOURCEW(IDS_CREATELINK), MFS_ENABLED);
}
if (rfg & SFGAO_CANDELETE)
if (bAddSep)
{
bAddSep = FALSE;
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
}
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_DELETE), MFS_ENABLED);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_DELETE, MFT_STRING, MAKEINTRESOURCEW(IDS_DELETE), MFS_ENABLED);
}
if (rfg & SFGAO_CANRENAME)
{
if (bAddSep)
{
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
}
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_RENAME), MFS_ENABLED);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_RENAME, MFT_STRING, MAKEINTRESOURCEW(IDS_RENAME), MFS_ENABLED);
bAddSep = TRUE;
}
if (rfg & SFGAO_HASPROPSHEET)
{
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
- _InsertMenuItemW(hMenu, indexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
+ _InsertMenuItemW(hMenu, IndexMenu++, TRUE, FCIDM_SHVIEW_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
}
return iIdCmdLast;
HRESULT
WINAPI
CDefaultContextMenu::QueryContextMenu(
- HMENU hmenu,
- UINT indexMenu,
+ HMENU hMenu,
+ UINT IndexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags)
{
- if (dcm.cidl)
- {
- idCmdFirst = BuildShellItemContextMenu(hmenu, idCmdFirst, idCmdLast, uFlags);
- }
+ if (m_Dcm.cidl)
+ idCmdFirst = BuildShellItemContextMenu(hMenu, idCmdFirst, idCmdLast, uFlags);
else
- {
- idCmdFirst = BuildBackgroundContextMenu(hmenu, idCmdFirst, idCmdLast, uFlags);
- }
+ idCmdFirst = BuildBackgroundContextMenu(hMenu, idCmdFirst, idCmdLast, uFlags);
return S_OK;
}
HRESULT
NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh)
{
- LPSHELLBROWSER lpSB;
- LPSHELLVIEW lpSV = NULL;
- HWND hwndSV = NULL;
+ /* Note: CWM_GETISHELLBROWSER returns not referenced object */
+ LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+ if (!lpSB)
+ return E_FAIL;
- if((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0)))
- {
- if(SUCCEEDED(lpSB->QueryActiveShellView(&lpSV)))
- {
- lpSV->GetWindow(&hwndSV);
- }
- }
+ LPSHELLVIEW lpSV = NULL;
+ if (FAILED(lpSB->QueryActiveShellView(&lpSV)))
+ return E_FAIL;
if (LOWORD(lpcmi->lpVerb) == FCIDM_SHVIEW_REFRESH || bRefresh)
+ lpSV->Refresh();
+ else
{
- if (lpSV)
- lpSV->Refresh();
-
- return S_OK;
+ HWND hwndSV = NULL;
+ if (SUCCEEDED(lpSV->GetWindow(&hwndSV)))
+ SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
}
- SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
-
+ lpSV->Release();
return S_OK;
}
HRESULT
CDefaultContextMenu::DoPaste(
- LPCMINVOKECOMMANDINFO lpcmi)
+ LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink)
{
- IDataObject * pda;
- STGMEDIUM medium;
- FORMATETC formatetc;
- LPITEMIDLIST * apidl;
- LPITEMIDLIST pidl;
- IShellFolder *psfFrom = NULL, *psfDesktop, *psfTarget = NULL;
- LPIDA lpcida;
- ISFHelper *psfhlpdst, *psfhlpsrc;
HRESULT hr;
- if (OleGetClipboard(&pda) != S_OK)
- return E_FAIL;
-
- InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
- hr = pda->GetData(&formatetc, &medium);
-
+ CComPtr<IDataObject> pda;
+ hr = OleGetClipboard(&pda);
if (FAILED(hr))
- {
- pda->Release();
- return E_FAIL;
- }
-
- /* lock the handle */
- lpcida = (LPIDA)GlobalLock(medium.hGlobal);
- if (!lpcida)
- {
- ReleaseStgMedium(&medium);
- pda->Release();
- return E_FAIL;
- }
-
- /* convert the data into pidl */
- apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
-
- if (!apidl)
- return E_FAIL;
-
- if (FAILED(SHGetDesktopFolder(&psfDesktop)))
- {
- SHFree(pidl);
- _ILFreeaPidl(apidl, lpcida->cidl);
- ReleaseStgMedium(&medium);
- pda->Release();
- return E_FAIL;
- }
-
- if (_ILIsDesktop(pidl))
- {
- /* use desktop shellfolder */
- psfFrom = psfDesktop;
- }
- else if (FAILED(psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&psfFrom)))
- {
- ERR("no IShellFolder\n");
+ return hr;
- psfDesktop->Release();
- SHFree(pidl);
- _ILFreeaPidl(apidl, lpcida->cidl);
- ReleaseStgMedium(&medium);
- pda->Release();
+ CComPtr<IShellFolder> psfDesktop;
+ CComPtr<IShellFolder> psfTarget = NULL;
- return E_FAIL;
- }
+ hr = SHGetDesktopFolder(&psfDesktop);
+ if (FAILED(hr))
+ return hr;
- if (dcm.cidl)
+ /* Find target folder */
+ if (m_Dcm.cidl)
{
- psfDesktop->Release();
- hr = dcm.psf->BindToObject(dcm.apidl[0], NULL, IID_IShellFolder, (LPVOID*)&psfTarget);
+ hr = m_Dcm.psf->BindToObject(m_Dcm.apidl[0], NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
}
else
{
- IPersistFolder2 *ppf2 = NULL;
+ CComPtr<IPersistFolder2> ppf2 = NULL;
LPITEMIDLIST pidl;
/* cidl is zero due to explorer view */
- hr = dcm.psf->QueryInterface(IID_IPersistFolder2, (LPVOID *) &ppf2);
+ hr = m_Dcm.psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
if (SUCCEEDED(hr))
{
hr = ppf2->GetCurFolder(&pidl);
- ppf2->Release();
if (SUCCEEDED(hr))
{
if (_ILIsDesktop(pidl))
else
{
/* retrieve target desktop folder */
- hr = psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&psfTarget);
+ hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, &psfTarget));
}
- TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget, _ILIsDesktop(pidl));
+ TRACE("psfTarget %x %p, Desktop %u\n", hr, psfTarget.p, _ILIsDesktop(pidl));
ILFree(pidl);
}
}
if (FAILED(hr))
{
ERR("no IShellFolder\n");
+ return hr;
+ }
- psfFrom->Release();
- SHFree(pidl);
- _ILFreeaPidl(apidl, lpcida->cidl);
- ReleaseStgMedium(&medium);
- pda->Release();
+ FORMATETC formatetc2;
+ STGMEDIUM medium2;
+ InitFormatEtc(formatetc2, RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECT), TYMED_HGLOBAL);
+
+ DWORD dwKey= 0;
- return E_FAIL;
+ if (SUCCEEDED(pda->GetData(&formatetc2, &medium2)))
+ {
+ DWORD * pdwFlag = (DWORD*)GlobalLock(medium2.hGlobal);
+ if (pdwFlag)
+ {
+ if (*pdwFlag == DROPEFFECT_COPY)
+ dwKey = MK_CONTROL;
+ else
+ dwKey = MK_SHIFT;
+ }
+ else {
+ ERR("No drop effect obtained");
+ }
+ GlobalUnlock(medium2.hGlobal);
}
- /* get source and destination shellfolder */
- if (FAILED(psfTarget->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlpdst)))
+ if (bLink)
{
- ERR("no IID_ISFHelper for destination\n");
-
- psfFrom->Release();
- psfTarget->Release();
- SHFree(pidl);
- _ILFreeaPidl(apidl, lpcida->cidl);
- ReleaseStgMedium(&medium);
- pda->Release();
-
- return E_FAIL;
+ dwKey = MK_CONTROL|MK_SHIFT;
}
- if (FAILED(psfFrom->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlpsrc)))
+ IDropTarget *pdrop;
+ hr = psfTarget->QueryInterface(IID_PPV_ARG(IDropTarget, &pdrop));
+ if (FAILED(hr))
{
- ERR("no IID_ISFHelper for source\n");
-
- psfhlpdst->Release();
- psfFrom->Release();
- psfTarget->Release();
- SHFree(pidl);
- _ILFreeaPidl(apidl, lpcida->cidl);
- ReleaseStgMedium(&medium);
- pda->Release();
- return E_FAIL;
+ ERR("Error getting IDropTarget interface\n");
+ return hr;
}
- /* FIXXME
- * do we want to perform a copy or move ???
- */
- hr = psfhlpdst->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl);
+ SHSimulateDrop(pdrop, pda, dwKey, NULL, NULL);
+ NotifyShellViewWindow(lpcmi, TRUE);
- psfhlpdst->Release();
- psfhlpsrc->Release();
- psfFrom->Release();
- psfTarget->Release();
- SHFree(pidl);
- _ILFreeaPidl(apidl, lpcida->cidl);
- ReleaseStgMedium(&medium);
- pda->Release();
TRACE("CP result %x\n", hr);
return S_OK;
}
return E_FAIL;
}
-BOOL
-GetUniqueFileName(LPWSTR szBasePath, LPWSTR szExt, LPWSTR szTarget, BOOL bShortcut)
-{
- UINT RetryCount = 0, Length;
- WCHAR szLnk[40];
- HANDLE hFile;
-
- if (!bShortcut)
- Length = LoadStringW(shell32_hInstance, IDS_LNK_FILE, szLnk, sizeof(szLnk) / sizeof(WCHAR));
-
- do
- {
- if (!bShortcut)
- {
- if (RetryCount)
- swprintf(szTarget, L"%s%s(%u).%s", szLnk, szBasePath, RetryCount, szExt);
- else
- swprintf(szTarget, L"%s%s.%s", szLnk, szBasePath, szExt);
- }
- else
- {
- if (RetryCount)
- swprintf(szTarget, L"%s(%u).%s", szBasePath, RetryCount, szExt);
- else
- swprintf(szTarget, L"%s.%s", szBasePath, szExt);
- }
-
- hFile = CreateFileW(szTarget, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile != INVALID_HANDLE_VALUE)
- {
- CloseHandle(hFile);
- return TRUE;
- }
-
- } while(RetryCount++ < 100);
-
- return FALSE;
-
-}
-
HRESULT
CDefaultContextMenu::DoCreateLink(
LPCMINVOKECOMMANDINFO lpcmi)
{
- WCHAR szPath[MAX_PATH];
- WCHAR szTarget[MAX_PATH] = {0};
- WCHAR szDirPath[MAX_PATH];
- LPWSTR pszFile;
- STRRET strFile;
- LPWSTR pszExt;
+ LPDATAOBJECT pDataObj;
+ IDropTarget *pDT;
HRESULT hr;
- IShellLinkW * nLink;
- IPersistFile * ipf;
- static WCHAR szLnk[] = L"lnk";
-
- if (dcm.psf->GetDisplayNameOf(dcm.apidl[0], SHGDN_FORPARSING, &strFile) != S_OK)
- {
- ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
- return E_FAIL;
- }
-
- if (StrRetToBufW(&strFile, dcm.apidl[0], szPath, MAX_PATH) != S_OK)
- return E_FAIL;
+ CComPtr<IPersistFolder2> ppf2 = NULL;
+ LPITEMIDLIST pidl;
+ CComPtr<IShellFolder> psfDesktop;
+ CComPtr<IShellFolder> psfTarget = NULL;
- pszExt = wcsrchr(szPath, L'.');
+ hr = SHGetDesktopFolder(&psfDesktop);
+ if (FAILED(hr))
+ return hr;
- if (pszExt && !wcsicmp(pszExt + 1, szLnk))
+ if (SUCCEEDED(hr = SHCreateDataObject(m_Dcm.pidlFolder, m_Dcm.cidl, m_Dcm.apidl, NULL, IID_PPV_ARG(IDataObject, &pDataObj))))
{
- if (!GetUniqueFileName(szPath, pszExt + 1, szTarget, TRUE))
- return E_FAIL;
+ hr = m_Dcm.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);
+ }
+ }
- hr = IShellLink_ConstructFromFile(NULL, IID_IPersistFile, dcm.apidl[0], (LPVOID*)&ipf);
- if (hr != S_OK)
- return hr;
+ }
- hr = ipf->Save(szTarget, FALSE);
- ipf->Release();
- NotifyShellViewWindow(lpcmi, TRUE);
+ if (FAILED(hr))
+ {
+ ERR("no IShellFolder\n");
return hr;
}
- else
- {
- if (!GetUniqueFileName(szPath, szLnk, szTarget, TRUE))
- return E_FAIL;
- hr = ShellLink::_CreatorClass::CreateInstance(NULL, IID_IShellLinkW, (void**)&nLink);
- if (hr != S_OK)
- return hr;
-
- GetFullPathName(szPath, MAX_PATH, szDirPath, &pszFile);
- if (pszFile) pszFile[0] = 0;
-
- if (SUCCEEDED(nLink->SetPath(szPath)) &&
- SUCCEEDED(nLink->SetWorkingDirectory(szDirPath)))
- {
- if (SUCCEEDED(nLink->QueryInterface(IID_IPersistFile, (LPVOID*)&ipf)))
- {
- hr = ipf->Save(szTarget, TRUE);
- ipf->Release();
- }
- }
- nLink->Release();
- NotifyShellViewWindow(lpcmi, TRUE);
+ psfTarget->QueryInterface(IID_PPV_ARG(IDropTarget, &pDT));
+ if (FAILED(hr))
+ {
+ ERR("no IDropTarget Interface\n");
return hr;
}
+ DWORD link = DROPEFFECT_LINK;
+ SHSimulateDrop(pDT, pDataObj, MK_CONTROL|MK_SHIFT, NULL, NULL);
+ NotifyShellViewWindow(lpcmi, TRUE);
+
+ return S_OK;
}
HRESULT
CDefaultContextMenu::DoDelete(
LPCMINVOKECOMMANDINFO lpcmi)
{
- HRESULT hr;
STRRET strTemp;
- WCHAR szPath[MAX_PATH];
- LPWSTR wszPath, wszPos;
- SHFILEOPSTRUCTW op;
- int ret;
- LPSHELLBROWSER lpSB;
- HWND hwnd;
-
-
- hr = dcm.psf->GetDisplayNameOf(dcm.apidl[0], SHGDN_FORPARSING, &strTemp);
+ HRESULT hr = m_Dcm.psf->GetDisplayNameOf(m_Dcm.apidl[0], SHGDN_FORPARSING, &strTemp);
if(hr != S_OK)
{
ERR("IShellFolder_GetDisplayNameOf failed with %x\n", hr);
return hr;
}
- ZeroMemory(szPath, sizeof(szPath));
- hr = StrRetToBufW(&strTemp, dcm.apidl[0], szPath, MAX_PATH);
+
+ WCHAR wszPath[MAX_PATH];
+ hr = StrRetToBufW(&strTemp, m_Dcm.apidl[0], wszPath, _countof(wszPath));
if (hr != S_OK)
{
ERR("StrRetToBufW failed with %x\n", hr);
}
/* Only keep the base path */
- wszPos = strrchrW(szPath, '\\');
- if (wszPos != NULL)
- {
- *(wszPos + 1) = '\0';
- }
+ LPWSTR pwszFilename = PathFindFileNameW(wszPath);
+ *pwszFilename = L'\0';
- wszPath = BuildPathsList(szPath, dcm.cidl, dcm.apidl);
+ /* Build paths list */
+ LPWSTR pwszPaths = BuildPathsList(wszPath, m_Dcm.cidl, m_Dcm.apidl);
+ if (!pwszPaths)
+ return E_FAIL;
- ZeroMemory(&op, sizeof(op));
- op.hwnd = GetActiveWindow();
- op.wFunc = FO_DELETE;
- op.pFrom = wszPath;
- op.fFlags = FOF_ALLOWUNDO;
- ret = SHFileOperationW(&op);
+ /* Delete them */
+ SHFILEOPSTRUCTW FileOp;
+ ZeroMemory(&FileOp, sizeof(FileOp));
+ FileOp.hwnd = GetActiveWindow();
+ FileOp.wFunc = FO_DELETE;
+ FileOp.pFrom = pwszPaths;
+ FileOp.fFlags = FOF_ALLOWUNDO;
- if (ret)
+ if (SHFileOperationW(&FileOp) != 0)
{
- ERR("SHFileOperation failed with 0x%x for %s\n", GetLastError(), debugstr_w(wszPath));
+ ERR("SHFileOperation failed with 0x%x for %s\n", GetLastError(), debugstr_w(pwszPaths));
return S_OK;
}
- /* get the active IShellView */
- if ((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0)))
+ /* Get the active IShellView */
+ LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageW(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+ if (lpSB)
{
- /* is the treeview focused */
+ /* Is the treeview focused */
+ HWND hwnd;
if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwnd)))
{
+ /* Remove selected items from treeview */
HTREEITEM hItem = TreeView_GetSelection(hwnd);
if (hItem)
- {
(void)TreeView_DeleteItem(hwnd, hItem);
- }
}
}
NotifyShellViewWindow(lpcmi, TRUE);
- HeapFree(GetProcessHeap(), 0, wszPath);
+ HeapFree(GetProcessHeap(), 0, pwszPaths);
return S_OK;
}
LPCMINVOKECOMMANDINFO lpcmi,
BOOL bCopy)
{
- LPSHELLBROWSER lpSB;
- LPSHELLVIEW lpSV;
LPDATAOBJECT pDataObj;
HRESULT hr;
- if (SUCCEEDED(SHCreateDataObject(dcm.pidlFolder, dcm.cidl, dcm.apidl, NULL, IID_IDataObject, (void**)&pDataObj)))
+ if (SUCCEEDED(SHCreateDataObject(m_Dcm.pidlFolder, m_Dcm.cidl, m_Dcm.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);
+ }
+
hr = OleSetClipboard(pDataObj);
pDataObj->Release();
return hr;
}
- lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+ /* Note: CWM_GETISHELLBROWSER returns not referenced object */
+ LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
if (!lpSB)
{
- TRACE("failed to get shellbrowser\n");
+ ERR("failed to get shellbrowser\n");
return E_FAIL;
}
+ LPSHELLVIEW lpSV;
hr = lpSB->QueryActiveShellView(&lpSV);
if (FAILED(hr))
{
- TRACE("failed to query the active shellview\n");
+ ERR("failed to query the active shellview\n");
return hr;
}
hr = lpSV->GetItemObject(SVGIO_SELECTION, IID_IDataObject, (LPVOID*)&pDataObj);
- if (FAILED(hr))
+ if (SUCCEEDED(hr))
{
- TRACE("failed to get item object\n");
- return hr;
- }
+ hr = OleSetClipboard(pDataObj);
+ if (FAILED(hr))
+ ERR("OleSetClipboard failed");
+ pDataObj->Release();
+ } else
+ ERR("failed to get item object\n");
- hr = OleSetClipboard(pDataObj);
- if (FAILED(hr))
- {
- WARN("OleSetClipboard failed");
- }
- pDataObj->Release();
lpSV->Release();
- return S_OK;
+ return hr;
}
HRESULT
CDefaultContextMenu::DoRename(
LPCMINVOKECOMMANDINFO lpcmi)
{
- LPSHELLBROWSER lpSB;
- LPSHELLVIEW lpSV;
- HWND hwnd;
+ /* 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;
+ }
- /* get the active IShellView */
- if ((lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0)))
+ /* is the treeview focused */
+ HWND hwnd;
+ if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwnd)))
{
- /* is the treeview focused */
- if (SUCCEEDED(lpSB->GetControlWindow(FCW_TREE, &hwnd)))
- {
- HTREEITEM hItem = TreeView_GetSelection(hwnd);
- if (hItem)
- {
- (void)TreeView_EditLabel(hwnd, hItem);
- }
- }
+ HTREEITEM hItem = TreeView_GetSelection(hwnd);
+ if (hItem)
+ (void)TreeView_EditLabel(hwnd, hItem);
+ }
- if(SUCCEEDED(lpSB->QueryActiveShellView(&lpSV)))
- {
- lpSV->SelectItem(dcm.apidl[0],
- SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT);
- lpSV->Release();
- return S_OK;
- }
+ LPSHELLVIEW lpSV;
+ HRESULT hr = lpSB->QueryActiveShellView(&lpSV);
+ if (FAILED(hr))
+ {
+ ERR("CWM_GETISHELLBROWSER failed\n");
+ return hr;
}
- return E_FAIL;
+
+ lpSV->SelectItem(m_Dcm.apidl[0],
+ SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT);
+ lpSV->Release();
+ return S_OK;
}
HRESULT
CDefaultContextMenu::DoProperties(
LPCMINVOKECOMMANDINFO lpcmi)
{
- WCHAR szDrive[MAX_PATH];
- STRRET strFile;
+ HRESULT hr = S_OK;
+ const ITEMIDLIST *pidlParent = m_Dcm.pidlFolder, *pidlChild;
- if (dcm.cidl && _ILIsMyComputer(dcm.apidl[0]))
+ if (!pidlParent)
{
- ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL, NULL, SW_SHOWNORMAL);
- return S_OK;
+ IPersistFolder2 *pf;
+
+ /* pidlFolder is optional */
+ if (SUCCEEDED(m_Dcm.psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
+ {
+ pf->GetCurFolder((_ITEMIDLIST**)&pidlParent);
+ pf->Release();
+ }
}
- else if (dcm.cidl == 0 && dcm.pidlFolder != NULL && _ILIsDesktop(dcm.pidlFolder))
+
+ if (m_Dcm.cidl > 0)
+ pidlChild = m_Dcm.apidl[0];
+ else
{
- ShellExecuteW(lpcmi->hwnd, L"open", L"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL);
- return S_OK;
+ /* Set pidlChild to last pidl of current folder */
+ if (pidlParent == m_Dcm.pidlFolder)
+ pidlParent = (ITEMIDLIST*)ILClone(pidlParent);
+
+ pidlChild = (ITEMIDLIST*)ILClone(ILFindLastID(pidlParent));
+ ILRemoveLastID((ITEMIDLIST*)pidlParent);
}
- else if (_ILIsDrive(dcm.apidl[0]))
+
+ if (_ILIsMyComputer(pidlChild))
{
- ILGetDisplayName(dcm.apidl[0], szDrive);
- SH_ShowDriveProperties(szDrive, dcm.pidlFolder, dcm.apidl);
- return S_OK;
+ 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 (_ILIsNetHood(dcm.apidl[0]))
+ else if (_ILIsDesktop(pidlChild))
{
- //FIXME path!
- ShellExecuteW(NULL, L"open", L"explorer.exe",
- L"::{7007ACC7-3202-11D1-AAD2-00805FC1270E}",
- NULL, SW_SHOWDEFAULT);
- return S_OK;
+ 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 (_ILIsBitBucket(dcm.apidl[0]))
+ else if (_ILIsDrive(pidlChild))
{
- /* FIXME
- * detect the drive path of bitbucket if appropiate
- */
-
- SH_ShowRecycleBinProperties(L'C');
- return S_OK;
+ WCHAR wszBuf[MAX_PATH];
+ ILGetDisplayName(pidlChild, wszBuf);
+ if (!SH_ShowDriveProperties(wszBuf, pidlParent, &pidlChild))
+ hr = E_FAIL;
}
-
- if (dcm.cidl > 1)
- WARN("SHMultiFileProperties is not yet implemented\n");
-
- if (dcm.psf->GetDisplayNameOf(dcm.apidl[0], SHGDN_FORPARSING, &strFile) != S_OK)
+ else if (_ILIsNetHood(pidlChild))
{
- ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
- return E_FAIL;
+ // 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_Dcm.cidl > 1)
+ WARN("SHMultiFileProperties is not yet implemented\n");
- if (StrRetToBufW(&strFile, dcm.apidl[0], szDrive, MAX_PATH) != S_OK)
- return E_FAIL;
+ STRRET strFile;
+ hr = m_Dcm.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");
+ }
- return SH_ShowPropertiesDialog(szDrive, dcm.pidlFolder, dcm.apidl);
+ /* Free allocated PIDLs */
+ if (pidlParent != m_Dcm.pidlFolder)
+ ILFree((ITEMIDLIST*)pidlParent);
+ if (m_Dcm.cidl < 1 || pidlChild != m_Dcm.apidl[0])
+ ILFree((ITEMIDLIST*)pidlChild);
+
+ return hr;
}
HRESULT
CDefaultContextMenu::DoFormat(
LPCMINVOKECOMMANDINFO lpcmi)
{
- char sDrive[5] = {0};
+ char szDrive[8] = {0};
- if (!_ILGetDrive(dcm.apidl[0], sDrive, sizeof(sDrive)))
+ if (!_ILGetDrive(m_Dcm.apidl[0], szDrive, sizeof(szDrive)))
{
ERR("pidl is not a drive\n");
return E_FAIL;
}
- SHFormatDrive(lpcmi->hwnd, sDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
+ SHFormatDrive(lpcmi->hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0);
return S_OK;
}
CDefaultContextMenu::DoDynamicShellExtensions(
LPCMINVOKECOMMANDINFO lpcmi)
{
- UINT verb = LOWORD(lpcmi->lpVerb);
- PDynamicShellEntry pCurrent = dhead;
+ UINT idCmd = LOWORD(lpcmi->lpVerb);
+ PDynamicShellEntry pEntry = m_pDynamicEntries;
- TRACE("verb %p first %x last %x", lpcmi->lpVerb, iIdSHEFirst, iIdSHELast);
+ TRACE("verb %p first %x last %x", lpcmi->lpVerb, m_iIdSHEFirst, m_iIdSHELast);
- while(pCurrent && verb > pCurrent->iIdCmdFirst + pCurrent->NumIds)
- pCurrent = pCurrent->Next;
+ while(pEntry && idCmd > pEntry->iIdCmdFirst + pEntry->NumIds)
+ pEntry = pEntry->pNext;
- if (!pCurrent)
+ if (!pEntry)
return E_FAIL;
- if (verb >= pCurrent->iIdCmdFirst && verb <= pCurrent->iIdCmdFirst + pCurrent->NumIds)
+ if (idCmd >= pEntry->iIdCmdFirst && idCmd <= pEntry->iIdCmdFirst + pEntry->NumIds)
{
/* invoke the dynamic context menu */
- lpcmi->lpVerb = MAKEINTRESOURCEA(verb - pCurrent->iIdCmdFirst);
- return pCurrent->CMenu->InvokeCommand(lpcmi);
+ lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst);
+ return pEntry->pCM->InvokeCommand(lpcmi);
}
return E_FAIL;
}
-
-HRESULT
-CDefaultContextMenu::DoStaticShellExtensions(
- LPCMINVOKECOMMANDINFO lpcmi)
+DWORD
+CDefaultContextMenu::BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFO lpcmi, PStaticShellEntry pEntry)
{
- STRRET strFile;
- WCHAR szPath[MAX_PATH];
- WCHAR szDir[MAX_PATH];
- SHELLEXECUTEINFOW sei;
- PStaticShellEntry pCurrent = shead;
- int verb = LOWORD(lpcmi->lpVerb) - iIdSCMFirst;
+ LPSHELLBROWSER lpSB;
+ HWND hwndTree;
+ LPCWSTR FlagsName;
+ WCHAR wszKey[256];
HRESULT hr;
+ DWORD wFlags;
+ DWORD cbVerb;
+
+ /* Get a pointer to the shell browser */
+ lpSB = (LPSHELLBROWSER)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+ if (lpSB == NULL)
+ 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)
+ FlagsName = L"ExplorerFlags";
+ else
+ FlagsName = L"BrowserFlags";
- while(pCurrent && verb-- > 0)
- pCurrent = pCurrent->Next;
+ /* Try to get the flag from the verb */
+ hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"%s\\shell\\%s", pEntry->szClass, pEntry->szVerb);
+ if (!SUCCEEDED(hr))
+ return 0;
+
+ cbVerb = sizeof(wFlags);
+ if (RegGetValueW(HKEY_CLASSES_ROOT, wszKey, FlagsName, RRF_RT_REG_DWORD, NULL, &wFlags, &cbVerb) == ERROR_SUCCESS)
+ {
+ return wFlags;
+ }
- if (verb > 0)
+ return 0;
+}
+
+HRESULT
+CDefaultContextMenu::TryToBrowse(
+ LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
+{
+ LPSHELLBROWSER lpSB = (LPSHELLBROWSER)SendMessageW(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
+ HRESULT hr;
+
+ if (lpSB == NULL)
return E_FAIL;
- hr = dcm.psf->GetDisplayNameOf(dcm.apidl[0], SHGDN_FORPARSING, &strFile);
- if (hr != S_OK)
+ hr = lpSB->BrowseObject(ILCombine(m_Dcm.pidlFolder, pidl), wFlags);
+
+ return hr;
+}
+
+HRESULT
+CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFO lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry)
+{
+ LPITEMIDLIST pidlFull = ILCombine(m_Dcm.pidlFolder, pidl);
+ if (pidlFull == NULL)
{
- ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
- return hr;
+ return E_FAIL;
}
- hr = StrRetToBufW(&strFile, dcm.apidl[0], szPath, MAX_PATH);
- if (hr != S_OK)
- return hr;
+ WCHAR wszPath[MAX_PATH];
+ BOOL bHasPath = SHGetPathFromIDListW(pidlFull, wszPath);
+
+ WCHAR wszDir[MAX_PATH];
+ if(bHasPath)
+ {
+ wcscpy(wszDir, wszPath);
+ PathRemoveFileSpec(wszDir);
+ }
+ else
+ {
+ SHGetPathFromIDListW(m_Dcm.pidlFolder, wszDir);
+ }
- wcscpy(szDir, szPath);
- PathRemoveFileSpec(szDir);
+ HKEY hkeyClass;
+ RegOpenKeyExW(HKEY_CLASSES_ROOT, pEntry->szClass, 0, KEY_READ, &hkeyClass);
+ SHELLEXECUTEINFOW sei;
ZeroMemory(&sei, sizeof(sei));
sei.cbSize = sizeof(sei);
- sei.fMask = SEE_MASK_CLASSNAME;
- sei.lpClass = pCurrent->szClass;
sei.hwnd = lpcmi->hwnd;
sei.nShow = SW_SHOWNORMAL;
- sei.lpVerb = pCurrent->szVerb;
- sei.lpFile = szPath;
- sei.lpDirectory = szDir;
+ sei.lpVerb = pEntry->szVerb;
+ sei.lpDirectory = wszDir;
+ sei.lpIDList = pidlFull;
+ sei.hkeyClass = hkeyClass;
+ sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST;
+ if (bHasPath)
+ {
+ sei.lpFile = wszPath;
+ }
+
ShellExecuteExW(&sei);
+
+ RegCloseKey(hkeyClass);
+
+ ILFree(pidlFull);
+
+ return S_OK;
+}
+
+HRESULT
+CDefaultContextMenu::DoStaticShellExtensions(
+ LPCMINVOKECOMMANDINFO lpcmi)
+{
+ PStaticShellEntry pEntry = m_pStaticEntries;
+ INT iCmd = LOWORD(lpcmi->lpVerb) - m_iIdSCMFirst;
+ HRESULT hr;
+ UINT i;
+
+ while (pEntry && (iCmd--) > 0)
+ pEntry = pEntry->pNext;
+
+ if (iCmd > 0)
+ return E_FAIL;
+
+ /* Get the browse flags to see if we need to browse */
+ DWORD wFlags = BrowserFlagsFromVerb(lpcmi, pEntry);
+ BOOL bBrowsed = FALSE;
+
+ for (i=0; i < m_Dcm.cidl; i++)
+ {
+ /* Check if we need to browse */
+ if (wFlags > 0)
+ {
+ /* 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 */
+ if (bBrowsed)
+ continue;
+
+ hr = TryToBrowse(lpcmi, m_Dcm.apidl[i], wFlags);
+ if (SUCCEEDED(hr))
+ {
+ bBrowsed = TRUE;
+ continue;
+ }
+ }
+
+ InvokePidl(lpcmi, m_Dcm.apidl[i], pEntry);
+ }
+
return S_OK;
}
case FCIDM_SHVIEW_REFRESH:
return NotifyShellViewWindow(lpcmi, FALSE);
case FCIDM_SHVIEW_INSERT:
+ return DoPaste(lpcmi, FALSE);
case FCIDM_SHVIEW_INSERTLINK:
- return DoPaste(lpcmi);
+ return DoPaste(lpcmi, TRUE);
case FCIDM_SHVIEW_OPEN:
case FCIDM_SHVIEW_EXPLORE:
return DoOpenOrExplore(lpcmi);
return DoFormat(lpcmi);
}
- if (iIdSHEFirst && iIdSHELast)
+ if (m_iIdSHEFirst && m_iIdSHELast)
{
- if (LOWORD(lpcmi->lpVerb) >= iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= iIdSHELast)
- {
+ if (LOWORD(lpcmi->lpVerb) >= m_iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSHELast)
return DoDynamicShellExtensions(lpcmi);
- }
}
- if (iIdSCMFirst && iIdSCMLast)
+ if (m_iIdSCMFirst && m_iIdSCMLast)
{
- if (LOWORD(lpcmi->lpVerb) >= iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= iIdSCMLast)
- {
+ if (LOWORD(lpcmi->lpVerb) >= m_iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= m_iIdSCMLast)
return DoStaticShellExtensions(lpcmi);
- }
}
FIXME("Unhandled Verb %xl\n", LOWORD(lpcmi->lpVerb));
REFIID riid,
void **ppv)
{
- CComObject<CDefaultContextMenu> *theContextMenu;
- CComPtr<IUnknown> result;
- HRESULT hResult;
-
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
- ATLTRY (theContextMenu = new CComObject<CDefaultContextMenu>);
- if (theContextMenu == NULL)
- return E_OUTOFMEMORY;
- hResult = theContextMenu->QueryInterface(riid, (void **)&result);
- if (FAILED(hResult))
+
+ 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))
{
- delete theContextMenu;
- return hResult;
+ pCM->Release();
+ return hr;
}
- hResult = theContextMenu->Initialize(pdcm);
- if (FAILED(hResult))
- return hResult;
- *ppv = result.Detach();
- TRACE("This(%p)(%x) cidl %u\n", *ppv, hResult, pdcm->cidl);
+
+ hr = pCM->Initialize(pdcm);
+ if (FAILED(hr))
+ {
+ pCM->Release();
+ return hr;
+ }
+
+ *ppv = pResult.Detach();
+ pCM->Release();
+ TRACE("This(%p) cidl %u\n", *ppv, pdcm->cidl);
return S_OK;
}
REFIID riid,
void **ppv)
{
- HRESULT hr = E_FAIL;
-
*ppv = NULL;
- hr = IDefaultContextMenu_Constructor(pdcm, riid, ppv);
+ 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);
IContextMenu **ppcm)
{
DEFCONTEXTMENU pdcm;
- HRESULT hr;
-
pdcm.hwnd = hwnd;
pdcm.pcmcb = NULL;
pdcm.pidlFolder = pidlFolder;
pdcm.cKeys = nKeys;
pdcm.aKeys = ahkeyClsKeys;
- hr = SHCreateDefaultContextMenu(&pdcm, IID_IContextMenu, (void**)ppcm);
+ HRESULT hr = SHCreateDefaultContextMenu(&pdcm, IID_PPV_ARG(IContextMenu, ppcm));
return hr;
}