mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 03:42:58 +00:00
[SHELL32] Implement the desktop folder menu for Explorer tree (#7026)
Enumerates but does not actually allow you to get CF_HDROP if the desktop PIDL is present in the dataobject.
This commit is contained in:
parent
674136bcd0
commit
63935f857f
6 changed files with 57 additions and 24 deletions
|
@ -207,6 +207,11 @@ CDefaultContextMenu::CDefaultContextMenu() :
|
|||
|
||||
CDefaultContextMenu::~CDefaultContextMenu()
|
||||
{
|
||||
for (POSITION it = m_DynamicEntries.GetHeadPosition(); it != NULL;)
|
||||
{
|
||||
const DynamicShellEntry& info = m_DynamicEntries.GetNext(it);
|
||||
IUnknown_SetSite(info.pCM.p, NULL);
|
||||
}
|
||||
m_DynamicEntries.RemoveAll();
|
||||
m_StaticEntries.RemoveAll();
|
||||
|
||||
|
@ -389,7 +394,7 @@ CDefaultContextMenu::LoadDynamicContextMenuHandler(HKEY hKey, REFCLSID clsid)
|
|||
return hr;
|
||||
}
|
||||
|
||||
hr = pExtInit->Initialize(m_pidlFolder, m_pDataObj, hKey);
|
||||
hr = pExtInit->Initialize(m_pDataObj ? NULL : m_pidlFolder, m_pDataObj, hKey);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WARN("IShellExtInit::Initialize failed.clsid %s hr 0x%x\n", wine_dbgstr_guid(&clsid), hr);
|
||||
|
@ -459,7 +464,7 @@ CDefaultContextMenu::EnumerateDynamicContextHandlerForKey(HKEY hRootKey)
|
|||
}
|
||||
}
|
||||
|
||||
hr = LoadDynamicContextMenuHandler(hKey, clsid);
|
||||
hr = LoadDynamicContextMenuHandler(hRootKey, clsid);
|
||||
if (FAILED(hr))
|
||||
WARN("Failed to get context menu entires from shell extension! clsid: %S\n", pwszClsid);
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ private:
|
|||
CSimpleArray<STGMEDIUM> m_Storage;
|
||||
UINT m_cfShellIDList;
|
||||
BOOL m_doasync;
|
||||
bool m_FailGetHDrop;
|
||||
public:
|
||||
CIDLDataObj();
|
||||
~CIDLDataObj();
|
||||
|
@ -173,6 +174,7 @@ CIDLDataObj::CIDLDataObj()
|
|||
{
|
||||
m_cfShellIDList = 0;
|
||||
m_doasync = FALSE;
|
||||
m_FailGetHDrop = false;
|
||||
}
|
||||
|
||||
CIDLDataObj::~CIDLDataObj()
|
||||
|
@ -205,6 +207,15 @@ HRESULT WINAPI CIDLDataObj::Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl
|
|||
HRESULT hr = SetData(&Format, &medium, TRUE);
|
||||
if (!FAILED_UNEXPECTEDLY(hr) && bAddAdditionalFormats)
|
||||
{
|
||||
/* The Windows default shell IDataObject::GetData fails with DV_E_CLIPFORMAT if the desktop is present.
|
||||
* Windows does return HDROP in EnumFormatEtc and does not fail until GetData is called.
|
||||
* Failing GetData causes 7-Zip 23.01 to not add its menu to the desktop folder. */
|
||||
for (UINT i = 0; i < cidlx; ++i)
|
||||
{
|
||||
if (ILIsEmpty(apidlx[i]) && ILIsEmpty(pMyPidl))
|
||||
m_FailGetHDrop = true;
|
||||
}
|
||||
|
||||
Format.cfFormat = CF_HDROP;
|
||||
medium.hGlobal = RenderHDROP((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
|
||||
hr = SetData(&Format, &medium, TRUE);
|
||||
|
@ -245,6 +256,9 @@ HRESULT WINAPI CIDLDataObj::GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium
|
|||
fmt.dwAspect == pformatetcIn->dwAspect &&
|
||||
fmt.tymed == pformatetcIn->tymed)
|
||||
{
|
||||
if (m_FailGetHDrop && fmt.cfFormat == CF_HDROP)
|
||||
return DV_E_CLIPFORMAT;
|
||||
|
||||
if (pformatetcIn->tymed != TYMED_HGLOBAL)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
|
|
|
@ -945,7 +945,7 @@ BrFolder_OnContextMenu(BrFolder &info, LPARAM lParam)
|
|||
return;
|
||||
info.pContextMenu = pcm;
|
||||
UINT cmf = ((GetKeyState(VK_SHIFT) < 0) ? CMF_EXTENDEDVERBS : 0) | CMF_CANRENAME;
|
||||
hr = pcm->QueryContextMenu(hMenu, 0, ID_FIRSTCMD, ID_LASTCMD, CMF_NODEFAULT | cmf);
|
||||
hr = pcm->QueryContextMenu(hMenu, 0, ID_FIRSTCMD, ID_LASTCMD, CMF_EXPLORE | cmf);
|
||||
if (hr > 0)
|
||||
_InsertMenuItemW(hMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, 0);
|
||||
_InsertMenuItemW(hMenu, 0, TRUE, IDC_TOGGLE, MFT_STRING,
|
||||
|
@ -961,8 +961,7 @@ BrFolder_OnContextMenu(BrFolder &info, LPARAM lParam)
|
|||
}
|
||||
else if (cmd != 0 && GetDfmCmd(pcm, ici.lpVerb) == DFM_CMD_RENAME)
|
||||
{
|
||||
TreeView_SelectItem(info.hwndTreeView, hSelected);
|
||||
TreeView_EditLabel(info.hwndTreeView, hSelected);
|
||||
BrFolder_Rename(&info, hSelected);
|
||||
}
|
||||
else if (cmd != 0)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
static BOOL IsSelf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
||||
{
|
||||
return cidl == 0 || (cidl == 1 && apidl && _ILIsEmpty(apidl[0]));
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CDesktopFolder::ShellUrlParseDisplayName(
|
||||
HWND hwndOwner,
|
||||
|
@ -810,10 +815,10 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
|
|||
|
||||
if (!ppvOut)
|
||||
return hr;
|
||||
|
||||
*ppvOut = NULL;
|
||||
|
||||
if (cidl == 1 && !_ILIsSpecialFolder(apidl[0]))
|
||||
BOOL self = IsSelf(cidl, apidl);
|
||||
if (cidl == 1 && !_ILIsSpecialFolder(apidl[0]) && !self)
|
||||
{
|
||||
CComPtr<IShellFolder2> psf;
|
||||
HRESULT hr = _GetSFFromPidl(apidl[0], &psf);
|
||||
|
@ -825,7 +830,8 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
|
|||
|
||||
if (IsEqualIID (riid, IID_IContextMenu))
|
||||
{
|
||||
if (cidl > 0 && _ILIsSpecialFolder(apidl[0]))
|
||||
// FIXME: m_regFolder vs AddFSClassKeysToArray is incorrect when the selection includes both regitems and FS items
|
||||
if (!self && cidl > 0 && _ILIsSpecialFolder(apidl[0]))
|
||||
{
|
||||
hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
|
||||
}
|
||||
|
@ -836,7 +842,12 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
|
|||
/* Otherwise operations like that involve items from both user and shared desktop will not work */
|
||||
HKEY hKeys[16];
|
||||
UINT cKeys = 0;
|
||||
if (cidl > 0)
|
||||
if (self)
|
||||
{
|
||||
AddClsidKeyToArray(CLSID_ShellDesktop, hKeys, &cKeys);
|
||||
AddClassKeyToArray(L"Folder", hKeys, &cKeys);
|
||||
}
|
||||
else if (cidl > 0)
|
||||
{
|
||||
AddFSClassKeysToArray(cidl, apidl, hKeys, &cKeys);
|
||||
}
|
||||
|
@ -1075,22 +1086,18 @@ HRESULT WINAPI CDesktopFolder::GetCurFolder(PIDLIST_ABSOLUTE * pidl)
|
|||
HRESULT WINAPI CDesktopFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
enum { IDC_PROPERTIES };
|
||||
/* no data object means no selection */
|
||||
if (!pdtobj)
|
||||
if (uMsg == DFM_INVOKECOMMAND && wParam == (pdtobj ? DFM_CMD_PROPERTIES : IDC_PROPERTIES))
|
||||
{
|
||||
if (uMsg == DFM_INVOKECOMMAND && wParam == IDC_PROPERTIES)
|
||||
{
|
||||
return SHELL_ExecuteControlPanelCPL(hwndOwner, L"desk.cpl") ? S_OK : E_FAIL;
|
||||
}
|
||||
else if (uMsg == DFM_MERGECONTEXTMENU)
|
||||
{
|
||||
QCMINFO *pqcminfo = (QCMINFO *)lParam;
|
||||
HMENU hpopup = CreatePopupMenu();
|
||||
_InsertMenuItemW(hpopup, 0, TRUE, IDC_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
|
||||
pqcminfo->idCmdFirst = Shell_MergeMenus(pqcminfo->hmenu, hpopup, pqcminfo->indexMenu, pqcminfo->idCmdFirst, pqcminfo->idCmdLast, MM_ADDSEPARATOR);
|
||||
DestroyMenu(hpopup);
|
||||
return S_OK;
|
||||
}
|
||||
return SHELL_ExecuteControlPanelCPL(hwndOwner, L"desk.cpl") ? S_OK : E_FAIL;
|
||||
}
|
||||
else if (uMsg == DFM_MERGECONTEXTMENU && !pdtobj) // Add Properties item when called for directory background
|
||||
{
|
||||
QCMINFO *pqcminfo = (QCMINFO *)lParam;
|
||||
HMENU hpopup = CreatePopupMenu();
|
||||
_InsertMenuItemW(hpopup, 0, TRUE, IDC_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
|
||||
pqcminfo->idCmdFirst = Shell_MergeMenus(pqcminfo->hmenu, hpopup, pqcminfo->indexMenu, pqcminfo->idCmdFirst, pqcminfo->idCmdLast, MM_ADDSEPARATOR);
|
||||
DestroyMenu(hpopup);
|
||||
return S_OK;
|
||||
}
|
||||
return SHELL32_DefaultContextMenuCallBack(psf, pdtobj, uMsg);
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags);
|
|||
BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath);
|
||||
|
||||
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys);
|
||||
LSTATUS AddClsidKeyToArray(REFCLSID clsid, HKEY* array, UINT* cKeys);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
|
|
|
@ -289,6 +289,13 @@ LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys)
|
|||
return result;
|
||||
}
|
||||
|
||||
LSTATUS AddClsidKeyToArray(REFCLSID clsid, HKEY* array, UINT* cKeys)
|
||||
{
|
||||
WCHAR path[6 + 38 + 1] = L"CLSID\\";
|
||||
StringFromGUID2(clsid, path + 6, 38 + 1);
|
||||
return AddClassKeyToArray(path, array, cKeys);
|
||||
}
|
||||
|
||||
void AddFSClassKeysToArray(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, HKEY* array, UINT* cKeys)
|
||||
{
|
||||
// This function opens the association array keys in canonical order for filesystem items.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue