PCUITEMID_CHILD_ARRAY apidl,
DWORD dwFlags);
+static HRESULT SHELL32_CoCreateInitSF(LPCITEMIDLIST pidlRoot, PERSIST_FOLDER_TARGET_INFO* ppfti,
+ LPCITEMIDLIST pidlChild, const GUID* clsid, REFIID riid, LPVOID *ppvOut)
+{
+ HRESULT hr;
+ CComPtr<IShellFolder> pShellFolder;
+
+ hr = SHCoCreateInstance(NULL, clsid, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
+ if (FAILED(hr))
+ return hr;
+
+ LPITEMIDLIST pidlAbsolute = ILCombine (pidlRoot, pidlChild);
+ CComPtr<IPersistFolder> ppf;
+ CComPtr<IPersistFolder3> ppf3;
+
+ if (ppfti && SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3))))
+ {
+ ppf3->InitializeEx(NULL, pidlAbsolute, ppfti);
+ }
+ else if (SUCCEEDED(pShellFolder->QueryInterface(IID_PPV_ARG(IPersistFolder, &ppf))))
+ {
+ ppf->Initialize(pidlAbsolute);
+ }
+ ILFree (pidlAbsolute);
+
+ return pShellFolder->QueryInterface(riid, ppvOut);
+}
+
+static void WINAPI _InsertMenuItemW(
+ HMENU hMenu,
+ UINT indexMenu,
+ BOOL fByPosition,
+ UINT wID,
+ UINT fType,
+ LPCWSTR dwTypeData,
+ UINT fState)
+{
+ MENUITEMINFOW mii;
+ WCHAR wszText[100];
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ if (fType == MFT_SEPARATOR)
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ else if (fType == MFT_STRING)
+ {
+ mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
+ if (IS_INTRESOURCE(dwTypeData))
+ {
+ if (LoadStringW(_AtlBaseModule.GetResourceInstance(), LOWORD((ULONG_PTR)dwTypeData), wszText, _countof(wszText)))
+ mii.dwTypeData = wszText;
+ else
+ {
+ ERR("failed to load string %p\n", dwTypeData);
+ return;
+ }
+ }
+ else
+ mii.dwTypeData = (LPWSTR)dwTypeData;
+ mii.fState = fState;
+ }
+
+ mii.wID = wID;
+ mii.fType = fType;
+ InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
+}
+
struct FolderViewColumns
{
int iResource;
static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath)
{
CComHeapPtr<ITEMIDLIST> lpFSPidl(ILCreateFromPathW(lpszPath));
- if (!(LPITEMIDLIST)lpFSPidl)
+ if (!lpFSPidl)
{
ERR("Failed to create pidl from path\n");
- return 0;
+ return NULL;
}
LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl);
- int pathLen = (wcslen(lpszPath) + 1) * sizeof(WCHAR);
+ int pathLen = (PathFindFileNameW(lpszPath) - lpszPath) * sizeof(WCHAR);
int cbData = sizeof(WORD) + pathLen + lpLastFSPidl->mkid.cb;
LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(cbData + sizeof(WORD));
if (!pidl)
p += sizeof(WORD);
memcpy(p, lpszPath, pathLen);
- p += pathLen;
+ p += pathLen - sizeof(WCHAR);
+ *((WCHAR *) p) = '\0';
+ p += sizeof(WCHAR);
memcpy(p, lpLastFSPidl, lpLastFSPidl->mkid.cb);
p += lpLastFSPidl->mkid.cb;
if (!SHCreateThread(SearchThreadProc, pSearchData, NULL, NULL))
{
SHFree(pSearchData);
- return HRESULT_FROM_WIN32(GetLastError());
+ return 0;
}
- return S_OK;
+ return 0;
}
LRESULT CFindFolder::StopSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
m_shellBrowser->SetStatusTextSB(status);
}
- return S_OK;
+ return 0;
}
// *** IShellFolder2 methods ***
if (iColumn == 1)
{
- WCHAR path[MAX_PATH];
- wcscpy(path, _ILGetPath(pidl));
- PathRemoveFileSpecW(path);
- return SHSetStrRet(&pDetails->str, path);
+ return SHSetStrRet(&pDetails->str, _ILGetPath(pidl));
}
return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str);
return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut);
}
-STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
- UINT *prgfInOut, LPVOID *ppvOut)
+class CFindFolderContextMenu :
+ public IContextMenu,
+ public CComObjectRootEx<CComMultiThreadModelNoCS>
{
- if (riid == IID_IDataObject && cidl == 1)
+ CComPtr<IContextMenu> m_pInner;
+ CComPtr<IShellFolderView> m_shellFolderView;
+ UINT m_firstCmdId;
+ static const UINT ADDITIONAL_MENU_ITEMS = 2;
+
+ //// *** IContextMenu methods ***
+ STDMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
- WCHAR path[MAX_PATH];
- wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID);
- PathRemoveFileSpecW(path);
- CComHeapPtr<ITEMIDLIST> 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);
+ m_firstCmdId = indexMenu;
+ _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_STRING, MAKEINTRESOURCEW(IDS_SEARCH_OPEN_FOLDER), MFS_ENABLED);
+ _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst++, MFT_SEPARATOR, NULL, 0);
+ return m_pInner->QueryContextMenu(hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
+ }
+
+ STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
+ {
+ if (!IS_INTRESOURCE(lpcmi->lpVerb))
+ {
+ return m_pInner->InvokeCommand(lpcmi);
+ }
+
+ if (LOWORD(lpcmi->lpVerb) < m_firstCmdId + ADDITIONAL_MENU_ITEMS)
+ {
+ PCUITEMID_CHILD *apidl;
+ UINT cidl;
+ HRESULT hResult = m_shellFolderView->GetSelectedObjects(&apidl, &cidl);
+ if (FAILED_UNEXPECTEDLY(hResult))
+ return hResult;
+
+ for (UINT i = 0; i < cidl; i++)
+ {
+ CComHeapPtr<ITEMIDLIST> folderPidl(ILCreateFromPathW(_ILGetPath(apidl[i])));
+ if (!folderPidl)
+ return E_OUTOFMEMORY;
+ LPCITEMIDLIST pidl = _ILGetFSPidl(apidl[i]);
+ SHOpenFolderAndSelectItems(folderPidl, 1, &pidl, 0);
+ }
+ return S_OK;
+ }
+
+ CMINVOKECOMMANDINFOEX actualCmdInfo;
+ memcpy(&actualCmdInfo, lpcmi, lpcmi->cbSize);
+ actualCmdInfo.lpVerb -= ADDITIONAL_MENU_ITEMS;
+ return m_pInner->InvokeCommand((CMINVOKECOMMANDINFO *)&actualCmdInfo);
+ }
+
+ STDMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
+ {
+ return m_pInner->GetCommandString(idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
+ }
+
+public:
+ static HRESULT Create(IShellFolderView *pShellFolderView, IContextMenu *pInnerContextMenu, IContextMenu **pContextMenu)
+ {
+ CComObject<CFindFolderContextMenu> *pObj;
+ HRESULT hResult = CComObject<CFindFolderContextMenu>::CreateInstance(&pObj);
+ if (FAILED_UNEXPECTEDLY(hResult))
+ return hResult;
+ pObj->m_shellFolderView = pShellFolderView;
+ pObj->m_pInner = pInnerContextMenu;
+ return pObj->QueryInterface(IID_PPV_ARG(IContextMenu, pContextMenu));
}
+ BEGIN_COM_MAP(CFindFolderContextMenu)
+ COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
+ END_COM_MAP()
+};
+
+STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
+ UINT *prgfInOut, LPVOID *ppvOut)
+{
if (cidl <= 0)
{
return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
}
- PCITEMID_CHILD *aFSPidl = new PCITEMID_CHILD[cidl];
+ CComHeapPtr<PCITEMID_CHILD> aFSPidl;
+ aFSPidl.Allocate(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;
+ CComHeapPtr<ITEMIDLIST> folderPidl(ILCreateFromPathW(_ILGetPath(apidl[0])));
+ if (!folderPidl)
+ return E_OUTOFMEMORY;
+ CComPtr<IShellFolder> pDesktopFolder;
+ HRESULT hResult = SHGetDesktopFolder(&pDesktopFolder);
+ if (FAILED_UNEXPECTEDLY(hResult))
+ return hResult;
+ CComPtr<IShellFolder> pShellFolder;
+ hResult = pDesktopFolder->BindToObject(folderPidl, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
+ if (FAILED_UNEXPECTEDLY(hResult))
+ return hResult;
+ CComPtr<IContextMenu> pContextMenu;
+ hResult = pShellFolder->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, (LPVOID *)&pContextMenu);
+ if (FAILED_UNEXPECTEDLY(hResult))
+ return hResult;
+ return CFindFolderContextMenu::Create(m_shellFolderView, pContextMenu, (IContextMenu **)ppvOut);
}
- HRESULT hr = m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut);
- delete[] aFSPidl;
-
- return hr;
+ return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut);
}
STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName)
}
case SFVM_WINDOWCREATED:
{
+ // Subclass window to receive window messages
SubclassWindow((HWND) wParam);
+ // Get shell browser for updating status bar text
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, MAKEINTRESOURCEW(IDS_SEARCH_OPEN_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);
+ hr = pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
- for (UINT i = 0; i < cidl; i++)
- {
- CComHeapPtr<ITEMIDLIST> pidl;
- DWORD attrs = 0;
- hr = SHILCreateFromPathW((LPCWSTR) apidl[i]->mkid.abID, &pidl, &attrs);
- if (SUCCEEDED(hr))
- {
- SHOpenFolderAndSelectItems(NULL, 1, &pidl, 0);
- }
- }
-
- return S_OK;
+ // Open search bar
+ CComPtr<IWebBrowser2> pWebBrowser2;
+ hr = m_shellBrowser->QueryInterface(IID_PPV_ARG(IWebBrowser2, &pWebBrowser2));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+ WCHAR pwszGuid[MAX_PATH];
+ StringFromGUID2(CLSID_FileSearchBand, pwszGuid, _countof(pwszGuid));
+ CComVariant searchBar(pwszGuid);
+ return pWebBrowser2->ShowBrowserBar(&searchBar, NULL, NULL);
}
- case DFM_GETDEFSTATICID:
- return S_FALSE;
}
- return Shell_DefaultContextMenuCallBack(m_pisfInner, pdtobj);
+ return E_NOTIMPL;
}
//// *** IPersistFolder2 methods ***
-STDMETHODIMP CFindFolder::GetCurFolder(LPITEMIDLIST *pidl)
+STDMETHODIMP CFindFolder::GetCurFolder(PIDLIST_ABSOLUTE *pidl)
{
*pidl = ILClone(m_pidl);
return S_OK;