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;
{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<IShellFolder> 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;
+}
+
+LRESULT CFindFolder::UpdateStatus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+ LPWSTR status = (LPWSTR) lParam;
+ if (m_shellBrowser)
+ {
+ m_shellBrowser->SetStatusTextSB(status);
+ }
+ LocalFree(status);
+
+ return S_OK;
+}
+
// *** IShellFolder2 methods ***
STDMETHODIMP CFindFolder::GetDefaultSearchGUID(GUID *pguid)
{
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;
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);
}
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)
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<PCITEMID_CHILD> 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 (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);
+ }
+
+ PCITEMID_CHILD *aFSPidl = new PCITEMID_CHILD[cidl];
+ for (UINT i = 0; i < cidl; i++)
+ {
+ 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;
+
+ 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,
*pViewMode = FVM_DETAILS;
return S_OK;
}
+ case SFVM_WINDOWCREATED:
+ {
+ SubclassWindow((HWND) wParam);
+
+ CComPtr<IServiceProvider> pServiceProvider;
+ HRESULT hr = m_shellFolderView->QueryInterface(IID_PPV_ARG(IServiceProvider, &pServiceProvider));
+ if (FAILED_UNEXPECTEDLY(hr))
+ {
+ return hr;
+ }
+ return pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser));
+ }
}
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)
{