From 2fdaa386d288f7c603e3c0c26c2791c95b7407f7 Mon Sep 17 00:00:00 2001 From: Brock Mammen Date: Fri, 19 Jul 2019 20:18:47 -0500 Subject: [PATCH] [SHELLFIND] Add "Open Containing Folder" to right-click menu --- dll/win32/browseui/shellfind/CFindFolder.cpp | 87 ++++++++++++++++++++ dll/win32/browseui/shellfind/CFindFolder.h | 10 ++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/dll/win32/browseui/shellfind/CFindFolder.cpp b/dll/win32/browseui/shellfind/CFindFolder.cpp index f0c2d5edebf..934abec37f8 100644 --- a/dll/win32/browseui/shellfind/CFindFolder.cpp +++ b/dll/win32/browseui/shellfind/CFindFolder.cpp @@ -9,6 +9,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(shellfind); +// FIXME: Remove this declaration after the function has been fully implemented +EXTERN_C HRESULT +WINAPI +SHOpenFolderAndSelectItems(LPITEMIDLIST pidlFolder, + UINT cidl, + PCUITEMID_CHILD_ARRAY apidl, + DWORD dwFlags); + struct FolderViewColumns { LPCWSTR wzColumnName; @@ -233,6 +241,19 @@ STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT *prgfInOut, LPVOID *ppvOut) { + if (riid == IID_IDataObject && cidl == 1) + { + WCHAR path[MAX_PATH]; + wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID); + PathRemoveFileSpecW(path); + LPITEMIDLIST rootPidl = ILCreateFromPathW(path); + if (!rootPidl) + return E_OUTOFMEMORY; + PCITEMID_CHILD aFSPidl[1]; + aFSPidl[0] = _ILGetFSPidl(apidl[0]); + return IDataObject_Constructor(hwndOwner, rootPidl, aFSPidl, cidl, (IDataObject **) ppvOut); + } + if (cidl <= 0) { return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut); @@ -244,6 +265,28 @@ STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHI aFSPidl[i] = _ILGetFSPidl(apidl[i]); } + if (riid == IID_IContextMenu) + { + HKEY hKeys[16]; + UINT cKeys = 0; + AddFSClassKeysToArray(aFSPidl[0], hKeys, &cKeys); + + DEFCONTEXTMENU dcm; + dcm.hwnd = hwndOwner; + dcm.pcmcb = this; + dcm.pidlFolder = m_pidl; + dcm.psf = this; + dcm.cidl = cidl; + dcm.apidl = apidl; + dcm.cKeys = cKeys; + dcm.aKeys = hKeys; + dcm.punkAssociationInfo = NULL; + HRESULT hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut); + delete[] aFSPidl; + + return hr; + } + HRESULT hr = m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut); delete[] aFSPidl; @@ -282,6 +325,50 @@ STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) return E_NOTIMPL; } +//// *** IContextMenuCB method *** +STDMETHODIMP CFindFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case DFM_MERGECONTEXTMENU: + { + QCMINFO *pqcminfo = (QCMINFO *) lParam; + _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0); + _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_STRING, L"Open Containing Folder", MFS_ENABLED); + _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0); + return S_OK; + } + case DFM_INVOKECOMMAND: + case DFM_INVOKECOMMANDEX: + { + if (wParam != 1) + break; + + PCUITEMID_CHILD *apidl; + UINT cidl; + HRESULT hr = m_shellFolderView->GetSelectedObjects(&apidl, &cidl); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + for (UINT i = 0; i < cidl; i++) + { + LPITEMIDLIST pidl; + DWORD attrs = 0; + hr = SHILCreateFromPathW((LPCWSTR) apidl[i]->mkid.abID, &pidl, &attrs); + if (SUCCEEDED(hr)) + { + SHOpenFolderAndSelectItems(NULL, 1, &pidl, 0); + } + } + + return S_OK; + } + case DFM_GETDEFSTATICID: + return S_FALSE; + } + return Shell_DefaultContextMenuCallBack(m_pisfInner, pdtobj); +} + //// *** IPersistFolder2 methods *** STDMETHODIMP CFindFolder::GetCurFolder(LPITEMIDLIST *pidl) { diff --git a/dll/win32/browseui/shellfind/CFindFolder.h b/dll/win32/browseui/shellfind/CFindFolder.h index a63efbc60cc..5c95ae6b011 100644 --- a/dll/win32/browseui/shellfind/CFindFolder.h +++ b/dll/win32/browseui/shellfind/CFindFolder.h @@ -9,8 +9,9 @@ class CFindFolder : public CComCoClass, public CComObjectRootEx, public IShellFolder2, + public IPersistFolder2, public IShellFolderViewCB, - public IPersistFolder2 + public IContextMenuCB { // *** IShellFolder2 methods *** STDMETHODIMP GetDefaultSearchGUID(GUID *pguid); @@ -47,14 +48,18 @@ class CFindFolder : STDMETHODIMP GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT *prgfInOut, LPVOID *ppvOut); - STDMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName); + STDMETHODIMP GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName); STDMETHODIMP SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut); //// *** IShellFolderViewCB methods *** STDMETHODIMP MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam); + //// *** IContextMenuCB method *** + STDMETHODIMP CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, + LPARAM lParam); + private: LPITEMIDLIST m_pidl; CComPtr m_pisfInner; @@ -91,6 +96,7 @@ public: COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder) COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IContextMenuCB, IContextMenuCB) END_COM_MAP() }; -- 2.17.1