From 666bf346407ec9759c52bf5f8cbcefa68dd1a62d Mon Sep 17 00:00:00 2001 From: Brock Mammen Date: Fri, 19 Jul 2019 19:27:31 -0500 Subject: [PATCH] [SHELLFIND] Create PIDLs and add search results to folder --- dll/win32/browseui/shellfind/CFindFolder.cpp | 126 ++++++++++++++++++- dll/win32/browseui/shellfind/CFindFolder.h | 3 + 2 files changed, 123 insertions(+), 6 deletions(-) diff --git a/dll/win32/browseui/shellfind/CFindFolder.cpp b/dll/win32/browseui/shellfind/CFindFolder.cpp index f9c1c957167..7983ee74129 100644 --- a/dll/win32/browseui/shellfind/CFindFolder.cpp +++ b/dll/win32/browseui/shellfind/CFindFolder.cpp @@ -24,6 +24,85 @@ static FolderViewColumns g_ColumnDefs[] = {L"Relevance", SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 0} }; +static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath, LPCITEMIDLIST lpcFindDataPidl) +{ + int pathLen = (wcslen(lpszPath) + 1) * sizeof(WCHAR); + int cbData = sizeof(WORD) + pathLen + lpcFindDataPidl->mkid.cb; + LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(cbData + sizeof(WORD)); + if (!pidl) + return NULL; + + LPBYTE p = (LPBYTE) pidl; + *((WORD *) p) = cbData; + p += sizeof(WORD); + + memcpy(p, lpszPath, pathLen); + p += pathLen; + + memcpy(p, lpcFindDataPidl, lpcFindDataPidl->mkid.cb); + p += lpcFindDataPidl->mkid.cb; + + *((WORD *) p) = 0; + + return pidl; +} + +static LPCWSTR _ILGetPath(LPCITEMIDLIST pidl) +{ + if (!pidl || !pidl->mkid.cb) + return NULL; + return (LPCWSTR) pidl->mkid.abID; +} + +static LPCITEMIDLIST _ILGetFSPidl(LPCITEMIDLIST pidl) +{ + if (!pidl || !pidl->mkid.cb) + return pidl; + return (LPCITEMIDLIST) ((LPBYTE) pidl->mkid.abID + + ((wcslen((LPCWSTR) pidl->mkid.abID) + 1) * sizeof(WCHAR))); +} + +LRESULT CFindFolder::AddItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + if (!lParam) + return 0; + + HRESULT hr; + LPWSTR path = (LPWSTR) lParam; + + CComPtr pShellFolder; + hr = SHGetDesktopFolder(&pShellFolder); + if (FAILED_UNEXPECTEDLY(hr)) + { + LocalFree(path); + return hr; + } + + LPITEMIDLIST lpFSPidl; + DWORD pchEaten; + hr = pShellFolder->ParseDisplayName(NULL, NULL, path, &pchEaten, &lpFSPidl, NULL); + if (FAILED_UNEXPECTEDLY(hr)) + { + LocalFree(path); + return hr; + } + + LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl); + LPITEMIDLIST lpSearchPidl = _ILCreate(path, lpLastFSPidl); + ILFree(lpFSPidl); + LocalFree(path); + if (!lpSearchPidl) + { + return E_OUTOFMEMORY; + } + + UINT uItemIndex; + hr = m_shellFolderView->AddObject(lpSearchPidl, &uItemIndex); + ILFree(lpSearchPidl); + + return hr; +} + // *** IShellFolder2 methods *** STDMETHODIMP CFindFolder::GetDefaultSearchGUID(GUID *pguid) { @@ -64,7 +143,7 @@ STDMETHODIMP CFindFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *p STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *pDetails) { if (iColumn >= _countof(g_ColumnDefs)) - return m_pisfInner->GetDetailsOf(pidl, iColumn - _countof(g_ColumnDefs) + 1, pDetails); + return m_pisfInner->GetDetailsOf(_ILGetFSPidl(pidl), iColumn - _countof(g_ColumnDefs) + 1, pDetails); pDetails->cxChar = g_ColumnDefs[iColumn].cxChar; pDetails->fmt = g_ColumnDefs[iColumn].fmt; @@ -72,6 +151,14 @@ STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELL if (!pidl) return SHSetStrRet(&pDetails->str, g_ColumnDefs[iColumn].wzColumnName); + if (iColumn == 1) + { + WCHAR path[MAX_PATH]; + wcscpy(path, _ILGetPath(pidl)); + PathRemoveFileSpecW(path); + return SHSetStrRet(&pDetails->str, path); + } + return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str); } @@ -109,7 +196,7 @@ STDMETHODIMP CFindFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserve STDMETHODIMP CFindFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) { - return m_pisfInner->CompareIDs(lParam, pidl1, pidl2); + return m_pisfInner->CompareIDs(lParam, _ILGetFSPidl(pidl1), _ILGetFSPidl(pidl2)); } STDMETHODIMP CFindFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) @@ -120,25 +207,52 @@ STDMETHODIMP CFindFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * sfvparams.cbSize = sizeof(SFV_CREATE); sfvparams.pshf = this; sfvparams.psfvcb = this; - return SHCreateShellFolderView(&sfvparams, (IShellView **) ppvOut); + HRESULT hr = SHCreateShellFolderView(&sfvparams, (IShellView **) ppvOut); + if (FAILED_UNEXPECTEDLY(hr)) + { + return hr; + } + + return ((IShellView * ) * ppvOut)->QueryInterface(IID_PPV_ARG(IShellFolderView, &m_shellFolderView)); } return E_NOINTERFACE; } STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) { - return m_pisfInner->GetAttributesOf(cidl, apidl, rgfInOut); + CComHeapPtr aFSPidl; + aFSPidl.Allocate(cidl); + for (UINT i = 0; i < cidl; i++) + { + aFSPidl[i] = _ILGetFSPidl(apidl[i]); + } + + return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut); } STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT *prgfInOut, LPVOID *ppvOut) { - return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut); + if (cidl <= 0) + { + return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut); + } + + PCITEMID_CHILD *aFSPidl = new PCITEMID_CHILD[cidl]; + for (UINT i = 0; i < cidl; i++) + { + aFSPidl[i] = _ILGetFSPidl(apidl[i]); + } + + HRESULT hr = m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut); + delete[] aFSPidl; + + return hr; } STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName) { - return m_pisfInner->GetDisplayNameOf(pidl, dwFlags, pName); + return m_pisfInner->GetDisplayNameOf(_ILGetFSPidl(pidl), dwFlags, pName); } STDMETHODIMP CFindFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, diff --git a/dll/win32/browseui/shellfind/CFindFolder.h b/dll/win32/browseui/shellfind/CFindFolder.h index 34f6165acdf..c9aa530b1db 100644 --- a/dll/win32/browseui/shellfind/CFindFolder.h +++ b/dll/win32/browseui/shellfind/CFindFolder.h @@ -58,6 +58,7 @@ class CFindFolder : private: LPITEMIDLIST m_pidl; CComPtr m_pisfInner; + CComPtr m_shellFolderView; //// *** IPersistFolder2 methods *** STDMETHODIMP GetCurFolder(LPITEMIDLIST *pidl); @@ -70,6 +71,8 @@ private: // *** IPersist methods *** STDMETHODIMP GetClassID(CLSID *pClassId); + LRESULT AddItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + public: DECLARE_REGISTRY_RESOURCEID(IDR_FINDFOLDER)