mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 00:53:03 +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()
|
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_DynamicEntries.RemoveAll();
|
||||||
m_StaticEntries.RemoveAll();
|
m_StaticEntries.RemoveAll();
|
||||||
|
|
||||||
|
@ -389,7 +394,7 @@ CDefaultContextMenu::LoadDynamicContextMenuHandler(HKEY hKey, REFCLSID clsid)
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = pExtInit->Initialize(m_pidlFolder, m_pDataObj, hKey);
|
hr = pExtInit->Initialize(m_pDataObj ? NULL : m_pidlFolder, m_pDataObj, hKey);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
WARN("IShellExtInit::Initialize failed.clsid %s hr 0x%x\n", wine_dbgstr_guid(&clsid), 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))
|
if (FAILED(hr))
|
||||||
WARN("Failed to get context menu entires from shell extension! clsid: %S\n", pwszClsid);
|
WARN("Failed to get context menu entires from shell extension! clsid: %S\n", pwszClsid);
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,6 +140,7 @@ private:
|
||||||
CSimpleArray<STGMEDIUM> m_Storage;
|
CSimpleArray<STGMEDIUM> m_Storage;
|
||||||
UINT m_cfShellIDList;
|
UINT m_cfShellIDList;
|
||||||
BOOL m_doasync;
|
BOOL m_doasync;
|
||||||
|
bool m_FailGetHDrop;
|
||||||
public:
|
public:
|
||||||
CIDLDataObj();
|
CIDLDataObj();
|
||||||
~CIDLDataObj();
|
~CIDLDataObj();
|
||||||
|
@ -173,6 +174,7 @@ CIDLDataObj::CIDLDataObj()
|
||||||
{
|
{
|
||||||
m_cfShellIDList = 0;
|
m_cfShellIDList = 0;
|
||||||
m_doasync = FALSE;
|
m_doasync = FALSE;
|
||||||
|
m_FailGetHDrop = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CIDLDataObj::~CIDLDataObj()
|
CIDLDataObj::~CIDLDataObj()
|
||||||
|
@ -205,6 +207,15 @@ HRESULT WINAPI CIDLDataObj::Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl
|
||||||
HRESULT hr = SetData(&Format, &medium, TRUE);
|
HRESULT hr = SetData(&Format, &medium, TRUE);
|
||||||
if (!FAILED_UNEXPECTEDLY(hr) && bAddAdditionalFormats)
|
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;
|
Format.cfFormat = CF_HDROP;
|
||||||
medium.hGlobal = RenderHDROP((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
|
medium.hGlobal = RenderHDROP((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
|
||||||
hr = SetData(&Format, &medium, TRUE);
|
hr = SetData(&Format, &medium, TRUE);
|
||||||
|
@ -245,6 +256,9 @@ HRESULT WINAPI CIDLDataObj::GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium
|
||||||
fmt.dwAspect == pformatetcIn->dwAspect &&
|
fmt.dwAspect == pformatetcIn->dwAspect &&
|
||||||
fmt.tymed == pformatetcIn->tymed)
|
fmt.tymed == pformatetcIn->tymed)
|
||||||
{
|
{
|
||||||
|
if (m_FailGetHDrop && fmt.cfFormat == CF_HDROP)
|
||||||
|
return DV_E_CLIPFORMAT;
|
||||||
|
|
||||||
if (pformatetcIn->tymed != TYMED_HGLOBAL)
|
if (pformatetcIn->tymed != TYMED_HGLOBAL)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
|
|
@ -945,7 +945,7 @@ BrFolder_OnContextMenu(BrFolder &info, LPARAM lParam)
|
||||||
return;
|
return;
|
||||||
info.pContextMenu = pcm;
|
info.pContextMenu = pcm;
|
||||||
UINT cmf = ((GetKeyState(VK_SHIFT) < 0) ? CMF_EXTENDEDVERBS : 0) | CMF_CANRENAME;
|
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)
|
if (hr > 0)
|
||||||
_InsertMenuItemW(hMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, 0);
|
_InsertMenuItemW(hMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, 0);
|
||||||
_InsertMenuItemW(hMenu, 0, TRUE, IDC_TOGGLE, MFT_STRING,
|
_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)
|
else if (cmd != 0 && GetDfmCmd(pcm, ici.lpVerb) == DFM_CMD_RENAME)
|
||||||
{
|
{
|
||||||
TreeView_SelectItem(info.hwndTreeView, hSelected);
|
BrFolder_Rename(&info, hSelected);
|
||||||
TreeView_EditLabel(info.hwndTreeView, hSelected);
|
|
||||||
}
|
}
|
||||||
else if (cmd != 0)
|
else if (cmd != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,11 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||||
|
|
||||||
|
static BOOL IsSelf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
||||||
|
{
|
||||||
|
return cidl == 0 || (cidl == 1 && apidl && _ILIsEmpty(apidl[0]));
|
||||||
|
}
|
||||||
|
|
||||||
STDMETHODIMP
|
STDMETHODIMP
|
||||||
CDesktopFolder::ShellUrlParseDisplayName(
|
CDesktopFolder::ShellUrlParseDisplayName(
|
||||||
HWND hwndOwner,
|
HWND hwndOwner,
|
||||||
|
@ -810,10 +815,10 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
|
||||||
|
|
||||||
if (!ppvOut)
|
if (!ppvOut)
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
*ppvOut = NULL;
|
*ppvOut = NULL;
|
||||||
|
|
||||||
if (cidl == 1 && !_ILIsSpecialFolder(apidl[0]))
|
BOOL self = IsSelf(cidl, apidl);
|
||||||
|
if (cidl == 1 && !_ILIsSpecialFolder(apidl[0]) && !self)
|
||||||
{
|
{
|
||||||
CComPtr<IShellFolder2> psf;
|
CComPtr<IShellFolder2> psf;
|
||||||
HRESULT hr = _GetSFFromPidl(apidl[0], &psf);
|
HRESULT hr = _GetSFFromPidl(apidl[0], &psf);
|
||||||
|
@ -825,7 +830,8 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
|
||||||
|
|
||||||
if (IsEqualIID (riid, IID_IContextMenu))
|
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);
|
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 */
|
/* Otherwise operations like that involve items from both user and shared desktop will not work */
|
||||||
HKEY hKeys[16];
|
HKEY hKeys[16];
|
||||||
UINT cKeys = 0;
|
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);
|
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)
|
HRESULT WINAPI CDesktopFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
enum { IDC_PROPERTIES };
|
enum { IDC_PROPERTIES };
|
||||||
/* no data object means no selection */
|
if (uMsg == DFM_INVOKECOMMAND && wParam == (pdtobj ? DFM_CMD_PROPERTIES : IDC_PROPERTIES))
|
||||||
if (!pdtobj)
|
|
||||||
{
|
{
|
||||||
if (uMsg == DFM_INVOKECOMMAND && wParam == IDC_PROPERTIES)
|
return SHELL_ExecuteControlPanelCPL(hwndOwner, L"desk.cpl") ? S_OK : E_FAIL;
|
||||||
{
|
}
|
||||||
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
|
||||||
}
|
{
|
||||||
else if (uMsg == DFM_MERGECONTEXTMENU)
|
QCMINFO *pqcminfo = (QCMINFO *)lParam;
|
||||||
{
|
HMENU hpopup = CreatePopupMenu();
|
||||||
QCMINFO *pqcminfo = (QCMINFO *)lParam;
|
_InsertMenuItemW(hpopup, 0, TRUE, IDC_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
|
||||||
HMENU hpopup = CreatePopupMenu();
|
pqcminfo->idCmdFirst = Shell_MergeMenus(pqcminfo->hmenu, hpopup, pqcminfo->indexMenu, pqcminfo->idCmdFirst, pqcminfo->idCmdLast, MM_ADDSEPARATOR);
|
||||||
_InsertMenuItemW(hpopup, 0, TRUE, IDC_PROPERTIES, MFT_STRING, MAKEINTRESOURCEW(IDS_PROPERTIES), MFS_ENABLED);
|
DestroyMenu(hpopup);
|
||||||
pqcminfo->idCmdFirst = Shell_MergeMenus(pqcminfo->hmenu, hpopup, pqcminfo->indexMenu, pqcminfo->idCmdFirst, pqcminfo->idCmdLast, MM_ADDSEPARATOR);
|
return S_OK;
|
||||||
DestroyMenu(hpopup);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return SHELL32_DefaultContextMenuCallBack(psf, pdtobj, uMsg);
|
return SHELL32_DefaultContextMenuCallBack(psf, pdtobj, uMsg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,7 @@ void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags);
|
||||||
BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath);
|
BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath);
|
||||||
|
|
||||||
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys);
|
LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys);
|
||||||
|
LSTATUS AddClsidKeyToArray(REFCLSID clsid, HKEY* array, UINT* cKeys);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
|
|
@ -289,6 +289,13 @@ LSTATUS AddClassKeyToArray(const WCHAR* szClass, HKEY* array, UINT* cKeys)
|
||||||
return result;
|
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)
|
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.
|
// This function opens the association array keys in canonical order for filesystem items.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue