1ccf9ce32SBrock Mammen #include "CFindFolder.h" 241d7b370SBrock Mammen #include <exdispid.h> 3ccf9ce32SBrock Mammen 4ccf9ce32SBrock Mammen WINE_DEFAULT_DEBUG_CHANNEL(shellfind); 5ccf9ce32SBrock Mammen 62fdaa386SBrock Mammen // FIXME: Remove this declaration after the function has been fully implemented 72fdaa386SBrock Mammen EXTERN_C HRESULT 82fdaa386SBrock Mammen WINAPI 92fdaa386SBrock Mammen SHOpenFolderAndSelectItems(LPITEMIDLIST pidlFolder, 102fdaa386SBrock Mammen UINT cidl, 112fdaa386SBrock Mammen PCUITEMID_CHILD_ARRAY apidl, 122fdaa386SBrock Mammen DWORD dwFlags); 132fdaa386SBrock Mammen 14ccf9ce32SBrock Mammen struct FolderViewColumns 15ccf9ce32SBrock Mammen { 16ccf9ce32SBrock Mammen LPCWSTR wzColumnName; 17ccf9ce32SBrock Mammen DWORD dwDefaultState; 18ccf9ce32SBrock Mammen int fmt; 19ccf9ce32SBrock Mammen int cxChar; 20ccf9ce32SBrock Mammen }; 21ccf9ce32SBrock Mammen 22ccf9ce32SBrock Mammen static FolderViewColumns g_ColumnDefs[] = 23ccf9ce32SBrock Mammen { 24ccf9ce32SBrock Mammen {L"Name", SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30}, 25ccf9ce32SBrock Mammen {L"In Folder", SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30}, 26ccf9ce32SBrock Mammen {L"Relevance", SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 0} 27ccf9ce32SBrock Mammen }; 28ccf9ce32SBrock Mammen 296d6bc885SBrock Mammen CFindFolder::CFindFolder() : 306d6bc885SBrock Mammen m_hStopEvent(NULL) 316d6bc885SBrock Mammen { 326d6bc885SBrock Mammen } 336d6bc885SBrock Mammen 342f3db8d9SBrock Mammen static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath) 35666bf346SBrock Mammen { 362f3db8d9SBrock Mammen CComHeapPtr<ITEMIDLIST> lpFSPidl(ILCreateFromPathW(lpszPath)); 372f3db8d9SBrock Mammen if (!(LPITEMIDLIST)lpFSPidl) 382f3db8d9SBrock Mammen { 392f3db8d9SBrock Mammen ERR("Failed to create pidl from path\n"); 402f3db8d9SBrock Mammen return 0; 412f3db8d9SBrock Mammen } 422f3db8d9SBrock Mammen LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl); 432f3db8d9SBrock Mammen 44666bf346SBrock Mammen int pathLen = (wcslen(lpszPath) + 1) * sizeof(WCHAR); 452f3db8d9SBrock Mammen int cbData = sizeof(WORD) + pathLen + lpLastFSPidl->mkid.cb; 46666bf346SBrock Mammen LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(cbData + sizeof(WORD)); 47666bf346SBrock Mammen if (!pidl) 48666bf346SBrock Mammen return NULL; 49666bf346SBrock Mammen 50666bf346SBrock Mammen LPBYTE p = (LPBYTE) pidl; 51666bf346SBrock Mammen *((WORD *) p) = cbData; 52666bf346SBrock Mammen p += sizeof(WORD); 53666bf346SBrock Mammen 54666bf346SBrock Mammen memcpy(p, lpszPath, pathLen); 55666bf346SBrock Mammen p += pathLen; 56666bf346SBrock Mammen 572f3db8d9SBrock Mammen memcpy(p, lpLastFSPidl, lpLastFSPidl->mkid.cb); 582f3db8d9SBrock Mammen p += lpLastFSPidl->mkid.cb; 59666bf346SBrock Mammen 60666bf346SBrock Mammen *((WORD *) p) = 0; 61666bf346SBrock Mammen 62666bf346SBrock Mammen return pidl; 63666bf346SBrock Mammen } 64666bf346SBrock Mammen 65666bf346SBrock Mammen static LPCWSTR _ILGetPath(LPCITEMIDLIST pidl) 66666bf346SBrock Mammen { 67666bf346SBrock Mammen if (!pidl || !pidl->mkid.cb) 68666bf346SBrock Mammen return NULL; 69666bf346SBrock Mammen return (LPCWSTR) pidl->mkid.abID; 70666bf346SBrock Mammen } 71666bf346SBrock Mammen 72666bf346SBrock Mammen static LPCITEMIDLIST _ILGetFSPidl(LPCITEMIDLIST pidl) 73666bf346SBrock Mammen { 74666bf346SBrock Mammen if (!pidl || !pidl->mkid.cb) 75666bf346SBrock Mammen return pidl; 76666bf346SBrock Mammen return (LPCITEMIDLIST) ((LPBYTE) pidl->mkid.abID 77666bf346SBrock Mammen + ((wcslen((LPCWSTR) pidl->mkid.abID) + 1) * sizeof(WCHAR))); 78666bf346SBrock Mammen } 79666bf346SBrock Mammen 802f3db8d9SBrock Mammen struct _SearchData 812f3db8d9SBrock Mammen { 822f3db8d9SBrock Mammen HWND hwnd; 832f3db8d9SBrock Mammen HANDLE hStopEvent; 848246cd4eSBrock Mammen CStringW szPath; 858246cd4eSBrock Mammen CStringW szFileName; 868246cd4eSBrock Mammen CStringA szQueryA; 878246cd4eSBrock Mammen CStringW szQueryW; 888246cd4eSBrock Mammen CComPtr<CFindFolder> pFindFolder; 892f3db8d9SBrock Mammen }; 902f3db8d9SBrock Mammen 918246cd4eSBrock Mammen template<typename TChar, typename TString, int (&StrNCmp)(const TChar *, const TChar *, size_t)> 928246cd4eSBrock Mammen static const TChar* StrStrN(const TChar *lpFirst, const TString &lpSrch, UINT cchMax) 932f3db8d9SBrock Mammen { 948246cd4eSBrock Mammen if (!lpFirst || lpSrch.IsEmpty() || !cchMax) 952f3db8d9SBrock Mammen return NULL; 962f3db8d9SBrock Mammen 978246cd4eSBrock Mammen for (UINT i = cchMax; i > 0 && *lpFirst; i--, lpFirst++) 982f3db8d9SBrock Mammen { 998246cd4eSBrock Mammen if (!StrNCmp(lpFirst, lpSrch, lpSrch.GetLength())) 1008246cd4eSBrock Mammen return (const TChar*)lpFirst; 1012f3db8d9SBrock Mammen } 1022f3db8d9SBrock Mammen 1032f3db8d9SBrock Mammen return NULL; 1042f3db8d9SBrock Mammen } 1052f3db8d9SBrock Mammen 1068246cd4eSBrock Mammen template<typename TChar, typename TString, int (&StrNCmp)(const TChar *, const TChar *, size_t)> 1078246cd4eSBrock Mammen static UINT StrStrNCount(const TChar *lpFirst, const TString &lpSrch, UINT cchMax) 1088246cd4eSBrock Mammen { 1098246cd4eSBrock Mammen const TChar *lpSearchEnd = lpFirst + cchMax; 1108246cd4eSBrock Mammen UINT uCount = 0; 1118246cd4eSBrock Mammen while (lpFirst < lpSearchEnd && (lpFirst = StrStrN<TChar, TString, StrNCmp>(lpFirst, lpSrch, cchMax))) 1128246cd4eSBrock Mammen { 1138246cd4eSBrock Mammen uCount++; 1148246cd4eSBrock Mammen lpFirst += lpSrch.GetLength(); 1158246cd4eSBrock Mammen cchMax = lpSearchEnd - lpFirst; 1168246cd4eSBrock Mammen } 1178246cd4eSBrock Mammen return uCount; 1188246cd4eSBrock Mammen } 1198246cd4eSBrock Mammen 1208246cd4eSBrock Mammen static UINT StrStrCountA(const CHAR *lpFirst, const CStringA &lpSrch, UINT cchMax) 1218246cd4eSBrock Mammen { 1228246cd4eSBrock Mammen return StrStrNCount<CHAR, CStringA, strncmp>(lpFirst, lpSrch, cchMax); 1238246cd4eSBrock Mammen } 1248246cd4eSBrock Mammen 1258246cd4eSBrock Mammen static UINT StrStrCountW(const WCHAR *lpFirst, const CStringW &lpSrch, UINT cchMax) 1268246cd4eSBrock Mammen { 1278246cd4eSBrock Mammen return StrStrNCount<WCHAR, CStringW, wcsncmp>(lpFirst, lpSrch, cchMax); 1288246cd4eSBrock Mammen } 1298246cd4eSBrock Mammen 1302f3db8d9SBrock Mammen static UINT SearchFile(LPCWSTR lpFilePath, _SearchData *pSearchData) 1312f3db8d9SBrock Mammen { 1322f3db8d9SBrock Mammen HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); 1332f3db8d9SBrock Mammen if (hFile == INVALID_HANDLE_VALUE) 1342f3db8d9SBrock Mammen return 0; 1352f3db8d9SBrock Mammen 1362f3db8d9SBrock Mammen DWORD size = GetFileSize(hFile, NULL); 1372f3db8d9SBrock Mammen HANDLE hFileMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 1382f3db8d9SBrock Mammen CloseHandle(hFile); 1392f3db8d9SBrock Mammen if (hFileMap == INVALID_HANDLE_VALUE) 1402f3db8d9SBrock Mammen return 0; 1412f3db8d9SBrock Mammen 1422f3db8d9SBrock Mammen LPBYTE lpFileContent = (LPBYTE) MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); 1432f3db8d9SBrock Mammen CloseHandle(hFileMap); 1442f3db8d9SBrock Mammen if (!lpFileContent) 1452f3db8d9SBrock Mammen return 0; 1462f3db8d9SBrock Mammen 1472f3db8d9SBrock Mammen UINT uMatches = 0; 1488246cd4eSBrock Mammen // Check for UTF-16 BOM 1498246cd4eSBrock Mammen if (size >= 2 && lpFileContent[0] == 0xFF && lpFileContent[1] == 0xFE) 1502f3db8d9SBrock Mammen { 1518246cd4eSBrock Mammen uMatches = StrStrCountW((LPCWSTR) lpFileContent, pSearchData->szQueryW, size / sizeof(WCHAR)); 1522f3db8d9SBrock Mammen } 1532f3db8d9SBrock Mammen else 1542f3db8d9SBrock Mammen { 1558246cd4eSBrock Mammen uMatches = StrStrCountA((LPCSTR) lpFileContent, pSearchData->szQueryA, size / sizeof(CHAR)); 1562f3db8d9SBrock Mammen } 1572f3db8d9SBrock Mammen 1582f3db8d9SBrock Mammen UnmapViewOfFile(lpFileContent); 1592f3db8d9SBrock Mammen 1602f3db8d9SBrock Mammen return uMatches; 1612f3db8d9SBrock Mammen } 1622f3db8d9SBrock Mammen 163*c46d6036SBrock Mammen static UINT RecursiveFind(LPCWSTR lpPath, _SearchData *pSearchData) 1642f3db8d9SBrock Mammen { 1652f3db8d9SBrock Mammen if (WaitForSingleObject(pSearchData->hStopEvent, 0) != WAIT_TIMEOUT) 166*c46d6036SBrock Mammen return 0; 1672f3db8d9SBrock Mammen 1682f3db8d9SBrock Mammen WCHAR szPath[MAX_PATH]; 1692f3db8d9SBrock Mammen WIN32_FIND_DATAW FindData; 1702f3db8d9SBrock Mammen HANDLE hFindFile; 1712f3db8d9SBrock Mammen BOOL bMoreFiles = TRUE; 172*c46d6036SBrock Mammen UINT uTotalFound = 0; 1732f3db8d9SBrock Mammen 1742f3db8d9SBrock Mammen PathCombineW(szPath, lpPath, L"*.*"); 1752f3db8d9SBrock Mammen 1762f3db8d9SBrock Mammen for (hFindFile = FindFirstFileW(szPath, &FindData); 1772f3db8d9SBrock Mammen bMoreFiles && hFindFile != INVALID_HANDLE_VALUE; 1782f3db8d9SBrock Mammen bMoreFiles = FindNextFileW(hFindFile, &FindData)) 1792f3db8d9SBrock Mammen { 1802f3db8d9SBrock Mammen if (!wcscmp(FindData.cFileName, L".") || !wcscmp(FindData.cFileName, L"..")) 1812f3db8d9SBrock Mammen continue; 1822f3db8d9SBrock Mammen 1832f3db8d9SBrock Mammen PathCombineW(szPath, lpPath, FindData.cFileName); 1842f3db8d9SBrock Mammen 1852f3db8d9SBrock Mammen if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 1862f3db8d9SBrock Mammen { 187*c46d6036SBrock Mammen CStringW status; 188*c46d6036SBrock Mammen status.Format(IDS_SEARCH_FOLDER, FindData.cFileName); 189*c46d6036SBrock Mammen PostMessageW(pSearchData->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM) StrDupW(status.GetBuffer())); 1902f3db8d9SBrock Mammen 191*c46d6036SBrock Mammen uTotalFound += RecursiveFind(szPath, pSearchData); 1922f3db8d9SBrock Mammen } 1938246cd4eSBrock Mammen else if ((pSearchData->szFileName.IsEmpty() || PathMatchSpecW(FindData.cFileName, pSearchData->szFileName)) 1948246cd4eSBrock Mammen && (pSearchData->szQueryA.IsEmpty() || SearchFile(szPath, pSearchData))) 1952f3db8d9SBrock Mammen { 1968246cd4eSBrock Mammen uTotalFound++; 1978246cd4eSBrock Mammen PostMessageW(pSearchData->hwnd, WM_SEARCH_ADD_RESULT, 0, (LPARAM) StrDupW(szPath)); 1982f3db8d9SBrock Mammen } 1992f3db8d9SBrock Mammen } 2002f3db8d9SBrock Mammen 2012f3db8d9SBrock Mammen if (hFindFile != INVALID_HANDLE_VALUE) 2022f3db8d9SBrock Mammen FindClose(hFindFile); 203*c46d6036SBrock Mammen 204*c46d6036SBrock Mammen return uTotalFound; 2052f3db8d9SBrock Mammen } 2062f3db8d9SBrock Mammen 2078246cd4eSBrock Mammen DWORD WINAPI CFindFolder::SearchThreadProc(LPVOID lpParameter) 2082f3db8d9SBrock Mammen { 2092f3db8d9SBrock Mammen _SearchData *data = static_cast<_SearchData*>(lpParameter); 2102f3db8d9SBrock Mammen 21141d7b370SBrock Mammen data->pFindFolder->NotifyConnections(DISPID_SEARCHSTART); 21241d7b370SBrock Mammen 213*c46d6036SBrock Mammen UINT uTotalFound = RecursiveFind(data->szPath, data); 2142f3db8d9SBrock Mammen 21541d7b370SBrock Mammen data->pFindFolder->NotifyConnections(DISPID_SEARCHCOMPLETE); 21641d7b370SBrock Mammen 217*c46d6036SBrock Mammen CStringW status; 218*c46d6036SBrock Mammen status.Format(IDS_SEARCH_FILES_FOUND, uTotalFound); 219*c46d6036SBrock Mammen ::PostMessageW(data->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM) StrDupW(status.GetBuffer())); 220*c46d6036SBrock Mammen 221*c46d6036SBrock Mammen delete data; 2222f3db8d9SBrock Mammen 2232f3db8d9SBrock Mammen return 0; 2242f3db8d9SBrock Mammen } 2252f3db8d9SBrock Mammen 22641d7b370SBrock Mammen void CFindFolder::NotifyConnections(DISPID id) 22741d7b370SBrock Mammen { 22841d7b370SBrock Mammen DISPPARAMS dispatchParams = {0}; 22941d7b370SBrock Mammen CComDynamicUnkArray &subscribers = 23041d7b370SBrock Mammen IConnectionPointImpl<CFindFolder, &DIID_DSearchCommandEvents>::m_vec; 23141d7b370SBrock Mammen for (IUnknown** pSubscriber = subscribers.begin(); pSubscriber < subscribers.end(); pSubscriber++) 23241d7b370SBrock Mammen { 23341d7b370SBrock Mammen if (!*pSubscriber) 23441d7b370SBrock Mammen continue; 23541d7b370SBrock Mammen 23641d7b370SBrock Mammen CComPtr<IDispatch> pDispatch; 23741d7b370SBrock Mammen HRESULT hResult = (*pSubscriber)->QueryInterface(IID_PPV_ARG(IDispatch, &pDispatch)); 23841d7b370SBrock Mammen if (!FAILED_UNEXPECTEDLY(hResult)) 23941d7b370SBrock Mammen pDispatch->Invoke(id, GUID_NULL, 0, DISPATCH_METHOD, &dispatchParams, NULL, NULL, NULL); 24041d7b370SBrock Mammen } 24141d7b370SBrock Mammen } 24241d7b370SBrock Mammen 2432f3db8d9SBrock Mammen LRESULT CFindFolder::StartSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 244666bf346SBrock Mammen { 245666bf346SBrock Mammen if (!lParam) 246666bf346SBrock Mammen return 0; 247666bf346SBrock Mammen 2482f3db8d9SBrock Mammen // Clear all previous search results 249666bf346SBrock Mammen UINT uItemIndex; 2502f3db8d9SBrock Mammen m_shellFolderView->RemoveObject(NULL, &uItemIndex); 251666bf346SBrock Mammen 2522f3db8d9SBrock Mammen _SearchData* pSearchData = new _SearchData(); 2532f3db8d9SBrock Mammen pSearchData->pFindFolder = this; 2542f3db8d9SBrock Mammen pSearchData->hwnd = m_hWnd; 2558246cd4eSBrock Mammen 2568246cd4eSBrock Mammen SearchStart *pSearchParams = (SearchStart *) lParam; 2578246cd4eSBrock Mammen pSearchData->szPath = pSearchParams->szPath; 2588246cd4eSBrock Mammen pSearchData->szFileName = pSearchParams->szFileName; 2598246cd4eSBrock Mammen pSearchData->szQueryA = pSearchParams->szQuery; 2608246cd4eSBrock Mammen pSearchData->szQueryW = pSearchParams->szQuery; 2618246cd4eSBrock Mammen SHFree(pSearchParams); 2628246cd4eSBrock Mammen 2632f3db8d9SBrock Mammen if (m_hStopEvent) 2642f3db8d9SBrock Mammen SetEvent(m_hStopEvent); 2652f3db8d9SBrock Mammen pSearchData->hStopEvent = m_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 2662f3db8d9SBrock Mammen 2678246cd4eSBrock Mammen if (!SHCreateThread(SearchThreadProc, pSearchData, NULL, NULL)) 2682f3db8d9SBrock Mammen { 2692f3db8d9SBrock Mammen SHFree(pSearchData); 2702f3db8d9SBrock Mammen return HRESULT_FROM_WIN32(GetLastError()); 2712f3db8d9SBrock Mammen } 2722f3db8d9SBrock Mammen 2732f3db8d9SBrock Mammen return S_OK; 2742f3db8d9SBrock Mammen } 2752f3db8d9SBrock Mammen 27641f9ad12SBrock Mammen LRESULT CFindFolder::StopSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 27741f9ad12SBrock Mammen { 27841f9ad12SBrock Mammen if (m_hStopEvent) 27941f9ad12SBrock Mammen { 28041f9ad12SBrock Mammen SetEvent(m_hStopEvent); 28141f9ad12SBrock Mammen m_hStopEvent = NULL; 28241f9ad12SBrock Mammen } 28341f9ad12SBrock Mammen return 0; 28441f9ad12SBrock Mammen } 28541f9ad12SBrock Mammen 2862f3db8d9SBrock Mammen LRESULT CFindFolder::AddResult(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2872f3db8d9SBrock Mammen { 2882f3db8d9SBrock Mammen if (!lParam) 2892f3db8d9SBrock Mammen return 0; 2902f3db8d9SBrock Mammen 2912f3db8d9SBrock Mammen CComHeapPtr<WCHAR> lpPath((LPWSTR) lParam); 2922f3db8d9SBrock Mammen 2932f3db8d9SBrock Mammen CComHeapPtr<ITEMIDLIST> lpSearchPidl(_ILCreate(lpPath)); 2942f3db8d9SBrock Mammen if (lpSearchPidl) 2952f3db8d9SBrock Mammen { 2962f3db8d9SBrock Mammen UINT uItemIndex; 2972f3db8d9SBrock Mammen m_shellFolderView->AddObject(lpSearchPidl, &uItemIndex); 2982f3db8d9SBrock Mammen } 2992f3db8d9SBrock Mammen 3002f3db8d9SBrock Mammen return 0; 301666bf346SBrock Mammen } 302666bf346SBrock Mammen 30304fcbe32SBrock Mammen LRESULT CFindFolder::UpdateStatus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 30404fcbe32SBrock Mammen { 305*c46d6036SBrock Mammen CComHeapPtr<WCHAR> status((LPWSTR) lParam); 30604fcbe32SBrock Mammen if (m_shellBrowser) 30704fcbe32SBrock Mammen { 308*c46d6036SBrock Mammen m_shellBrowser->SetStatusTextSB(status); 30904fcbe32SBrock Mammen } 31004fcbe32SBrock Mammen 31104fcbe32SBrock Mammen return S_OK; 31204fcbe32SBrock Mammen } 31304fcbe32SBrock Mammen 314ccf9ce32SBrock Mammen // *** IShellFolder2 methods *** 315ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDefaultSearchGUID(GUID *pguid) 316ccf9ce32SBrock Mammen { 317ccf9ce32SBrock Mammen UNIMPLEMENTED; 318ccf9ce32SBrock Mammen return E_NOTIMPL; 319ccf9ce32SBrock Mammen } 320ccf9ce32SBrock Mammen 321ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::EnumSearches(IEnumExtraSearch **ppenum) 322ccf9ce32SBrock Mammen { 323ccf9ce32SBrock Mammen UNIMPLEMENTED; 324ccf9ce32SBrock Mammen return E_NOTIMPL; 325ccf9ce32SBrock Mammen } 326ccf9ce32SBrock Mammen 327ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDefaultColumn(DWORD, ULONG *pSort, ULONG *pDisplay) 328ccf9ce32SBrock Mammen { 329ccf9ce32SBrock Mammen if (pSort) 330ccf9ce32SBrock Mammen *pSort = 0; 331ccf9ce32SBrock Mammen if (pDisplay) 332ccf9ce32SBrock Mammen *pDisplay = 0; 333ccf9ce32SBrock Mammen return S_OK; 334ccf9ce32SBrock Mammen } 335ccf9ce32SBrock Mammen 336ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags) 337ccf9ce32SBrock Mammen { 338c0799cd2SBrock Mammen if (!pcsFlags) 339ccf9ce32SBrock Mammen return E_INVALIDARG; 340c0799cd2SBrock Mammen if (iColumn >= _countof(g_ColumnDefs)) 341c0799cd2SBrock Mammen return m_pisfInner->GetDefaultColumnState(iColumn - _countof(g_ColumnDefs) + 1, pcsFlags); 342ccf9ce32SBrock Mammen *pcsFlags = g_ColumnDefs[iColumn].dwDefaultState; 343ccf9ce32SBrock Mammen return S_OK; 344ccf9ce32SBrock Mammen } 345ccf9ce32SBrock Mammen 346ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv) 347ccf9ce32SBrock Mammen { 348c0799cd2SBrock Mammen return m_pisfInner->GetDetailsEx(pidl, pscid, pv); 349ccf9ce32SBrock Mammen } 350ccf9ce32SBrock Mammen 351ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *pDetails) 352ccf9ce32SBrock Mammen { 353ccf9ce32SBrock Mammen if (iColumn >= _countof(g_ColumnDefs)) 354666bf346SBrock Mammen return m_pisfInner->GetDetailsOf(_ILGetFSPidl(pidl), iColumn - _countof(g_ColumnDefs) + 1, pDetails); 355ccf9ce32SBrock Mammen 356ccf9ce32SBrock Mammen pDetails->cxChar = g_ColumnDefs[iColumn].cxChar; 357ccf9ce32SBrock Mammen pDetails->fmt = g_ColumnDefs[iColumn].fmt; 358ccf9ce32SBrock Mammen 359ccf9ce32SBrock Mammen if (!pidl) 360ccf9ce32SBrock Mammen return SHSetStrRet(&pDetails->str, g_ColumnDefs[iColumn].wzColumnName); 361ccf9ce32SBrock Mammen 362666bf346SBrock Mammen if (iColumn == 1) 363666bf346SBrock Mammen { 364666bf346SBrock Mammen WCHAR path[MAX_PATH]; 365666bf346SBrock Mammen wcscpy(path, _ILGetPath(pidl)); 366666bf346SBrock Mammen PathRemoveFileSpecW(path); 367666bf346SBrock Mammen return SHSetStrRet(&pDetails->str, path); 368666bf346SBrock Mammen } 369666bf346SBrock Mammen 370ccf9ce32SBrock Mammen return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str); 371ccf9ce32SBrock Mammen } 372ccf9ce32SBrock Mammen 373ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid) 374ccf9ce32SBrock Mammen { 375ccf9ce32SBrock Mammen UNIMPLEMENTED; 376ccf9ce32SBrock Mammen return E_NOTIMPL; 377ccf9ce32SBrock Mammen } 378ccf9ce32SBrock Mammen 379ccf9ce32SBrock Mammen // *** IShellFolder methods *** 380ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten, 381ccf9ce32SBrock Mammen PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes) 382ccf9ce32SBrock Mammen { 383ccf9ce32SBrock Mammen UNIMPLEMENTED; 384ccf9ce32SBrock Mammen return E_NOTIMPL; 385ccf9ce32SBrock Mammen } 386ccf9ce32SBrock Mammen 387ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) 388ccf9ce32SBrock Mammen { 389ccf9ce32SBrock Mammen *ppEnumIDList = NULL; 390ccf9ce32SBrock Mammen return S_FALSE; 391ccf9ce32SBrock Mammen } 392ccf9ce32SBrock Mammen 393ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) 394ccf9ce32SBrock Mammen { 395ccf9ce32SBrock Mammen UNIMPLEMENTED; 396ccf9ce32SBrock Mammen return E_NOTIMPL; 397ccf9ce32SBrock Mammen } 398ccf9ce32SBrock Mammen 399ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut) 400ccf9ce32SBrock Mammen { 401ccf9ce32SBrock Mammen UNIMPLEMENTED; 402ccf9ce32SBrock Mammen return E_NOTIMPL; 403ccf9ce32SBrock Mammen } 404ccf9ce32SBrock Mammen 405ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2) 406ccf9ce32SBrock Mammen { 407666bf346SBrock Mammen return m_pisfInner->CompareIDs(lParam, _ILGetFSPidl(pidl1), _ILGetFSPidl(pidl2)); 408ccf9ce32SBrock Mammen } 409ccf9ce32SBrock Mammen 410ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut) 411ccf9ce32SBrock Mammen { 412ccf9ce32SBrock Mammen if (riid == IID_IShellView) 413ccf9ce32SBrock Mammen { 414ccf9ce32SBrock Mammen SFV_CREATE sfvparams = {}; 415ccf9ce32SBrock Mammen sfvparams.cbSize = sizeof(SFV_CREATE); 416ccf9ce32SBrock Mammen sfvparams.pshf = this; 4179c290040SBrock Mammen sfvparams.psfvcb = this; 418666bf346SBrock Mammen HRESULT hr = SHCreateShellFolderView(&sfvparams, (IShellView **) ppvOut); 419666bf346SBrock Mammen if (FAILED_UNEXPECTEDLY(hr)) 420666bf346SBrock Mammen { 421666bf346SBrock Mammen return hr; 422666bf346SBrock Mammen } 423666bf346SBrock Mammen 424666bf346SBrock Mammen return ((IShellView * ) * ppvOut)->QueryInterface(IID_PPV_ARG(IShellFolderView, &m_shellFolderView)); 425ccf9ce32SBrock Mammen } 426ccf9ce32SBrock Mammen return E_NOINTERFACE; 427ccf9ce32SBrock Mammen } 428ccf9ce32SBrock Mammen 429ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut) 430ccf9ce32SBrock Mammen { 431666bf346SBrock Mammen CComHeapPtr<PCITEMID_CHILD> aFSPidl; 432666bf346SBrock Mammen aFSPidl.Allocate(cidl); 433666bf346SBrock Mammen for (UINT i = 0; i < cidl; i++) 434666bf346SBrock Mammen { 435666bf346SBrock Mammen aFSPidl[i] = _ILGetFSPidl(apidl[i]); 436666bf346SBrock Mammen } 437666bf346SBrock Mammen 438666bf346SBrock Mammen return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut); 439ccf9ce32SBrock Mammen } 440ccf9ce32SBrock Mammen 441ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, 442ccf9ce32SBrock Mammen UINT *prgfInOut, LPVOID *ppvOut) 443ccf9ce32SBrock Mammen { 4442fdaa386SBrock Mammen if (riid == IID_IDataObject && cidl == 1) 4452fdaa386SBrock Mammen { 4462fdaa386SBrock Mammen WCHAR path[MAX_PATH]; 4472fdaa386SBrock Mammen wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID); 4482fdaa386SBrock Mammen PathRemoveFileSpecW(path); 4496d6bc885SBrock Mammen CComHeapPtr<ITEMIDLIST> rootPidl(ILCreateFromPathW(path)); 4502fdaa386SBrock Mammen if (!rootPidl) 4512fdaa386SBrock Mammen return E_OUTOFMEMORY; 4522fdaa386SBrock Mammen PCITEMID_CHILD aFSPidl[1]; 4532fdaa386SBrock Mammen aFSPidl[0] = _ILGetFSPidl(apidl[0]); 4542fdaa386SBrock Mammen return IDataObject_Constructor(hwndOwner, rootPidl, aFSPidl, cidl, (IDataObject **) ppvOut); 4552fdaa386SBrock Mammen } 4562fdaa386SBrock Mammen 457666bf346SBrock Mammen if (cidl <= 0) 458666bf346SBrock Mammen { 459c0799cd2SBrock Mammen return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut); 460ccf9ce32SBrock Mammen } 461ccf9ce32SBrock Mammen 462666bf346SBrock Mammen PCITEMID_CHILD *aFSPidl = new PCITEMID_CHILD[cidl]; 463666bf346SBrock Mammen for (UINT i = 0; i < cidl; i++) 464666bf346SBrock Mammen { 465666bf346SBrock Mammen aFSPidl[i] = _ILGetFSPidl(apidl[i]); 466666bf346SBrock Mammen } 467666bf346SBrock Mammen 4682fdaa386SBrock Mammen if (riid == IID_IContextMenu) 4692fdaa386SBrock Mammen { 4702fdaa386SBrock Mammen HKEY hKeys[16]; 4712fdaa386SBrock Mammen UINT cKeys = 0; 4722fdaa386SBrock Mammen AddFSClassKeysToArray(aFSPidl[0], hKeys, &cKeys); 4732fdaa386SBrock Mammen 4742fdaa386SBrock Mammen DEFCONTEXTMENU dcm; 4752fdaa386SBrock Mammen dcm.hwnd = hwndOwner; 4762fdaa386SBrock Mammen dcm.pcmcb = this; 4772fdaa386SBrock Mammen dcm.pidlFolder = m_pidl; 4782fdaa386SBrock Mammen dcm.psf = this; 4792fdaa386SBrock Mammen dcm.cidl = cidl; 4802fdaa386SBrock Mammen dcm.apidl = apidl; 4812fdaa386SBrock Mammen dcm.cKeys = cKeys; 4822fdaa386SBrock Mammen dcm.aKeys = hKeys; 4832fdaa386SBrock Mammen dcm.punkAssociationInfo = NULL; 4842fdaa386SBrock Mammen HRESULT hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut); 4852fdaa386SBrock Mammen delete[] aFSPidl; 4862fdaa386SBrock Mammen 4872fdaa386SBrock Mammen return hr; 4882fdaa386SBrock Mammen } 4892fdaa386SBrock Mammen 490666bf346SBrock Mammen HRESULT hr = m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut); 491666bf346SBrock Mammen delete[] aFSPidl; 492666bf346SBrock Mammen 493666bf346SBrock Mammen return hr; 494666bf346SBrock Mammen } 495666bf346SBrock Mammen 496ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName) 497ccf9ce32SBrock Mammen { 498666bf346SBrock Mammen return m_pisfInner->GetDisplayNameOf(_ILGetFSPidl(pidl), dwFlags, pName); 499ccf9ce32SBrock Mammen } 500ccf9ce32SBrock Mammen 501ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, 502ccf9ce32SBrock Mammen PITEMID_CHILD *pPidlOut) 503ccf9ce32SBrock Mammen { 504ccf9ce32SBrock Mammen UNIMPLEMENTED; 505ccf9ce32SBrock Mammen return E_NOTIMPL; 506ccf9ce32SBrock Mammen } 5079c290040SBrock Mammen 5089c290040SBrock Mammen //// *** IShellFolderViewCB method *** 5099c290040SBrock Mammen STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) 5109c290040SBrock Mammen { 5119c290040SBrock Mammen switch (uMsg) 5129c290040SBrock Mammen { 5139c290040SBrock Mammen case SFVM_DEFVIEWMODE: 5149c290040SBrock Mammen { 5159c290040SBrock Mammen FOLDERVIEWMODE *pViewMode = (FOLDERVIEWMODE *) lParam; 5169c290040SBrock Mammen *pViewMode = FVM_DETAILS; 5179c290040SBrock Mammen return S_OK; 5189c290040SBrock Mammen } 51906fd04d7SBrock Mammen case SFVM_WINDOWCREATED: 52006fd04d7SBrock Mammen { 52106fd04d7SBrock Mammen SubclassWindow((HWND) wParam); 52204fcbe32SBrock Mammen 52304fcbe32SBrock Mammen CComPtr<IServiceProvider> pServiceProvider; 52404fcbe32SBrock Mammen HRESULT hr = m_shellFolderView->QueryInterface(IID_PPV_ARG(IServiceProvider, &pServiceProvider)); 52504fcbe32SBrock Mammen if (FAILED_UNEXPECTEDLY(hr)) 52604fcbe32SBrock Mammen { 52704fcbe32SBrock Mammen return hr; 52804fcbe32SBrock Mammen } 52904fcbe32SBrock Mammen return pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser)); 53006fd04d7SBrock Mammen } 5319c290040SBrock Mammen } 5329c290040SBrock Mammen return E_NOTIMPL; 5339c290040SBrock Mammen } 5349c290040SBrock Mammen 5352fdaa386SBrock Mammen //// *** IContextMenuCB method *** 5362fdaa386SBrock Mammen STDMETHODIMP CFindFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam) 5372fdaa386SBrock Mammen { 5382fdaa386SBrock Mammen switch (uMsg) 5392fdaa386SBrock Mammen { 5402fdaa386SBrock Mammen case DFM_MERGECONTEXTMENU: 5412fdaa386SBrock Mammen { 5422fdaa386SBrock Mammen QCMINFO *pqcminfo = (QCMINFO *) lParam; 5432fdaa386SBrock Mammen _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0); 5442fdaa386SBrock Mammen _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_STRING, L"Open Containing Folder", MFS_ENABLED); 5452fdaa386SBrock Mammen _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0); 5462fdaa386SBrock Mammen return S_OK; 5472fdaa386SBrock Mammen } 5482fdaa386SBrock Mammen case DFM_INVOKECOMMAND: 5492fdaa386SBrock Mammen case DFM_INVOKECOMMANDEX: 5502fdaa386SBrock Mammen { 5512fdaa386SBrock Mammen if (wParam != 1) 5522fdaa386SBrock Mammen break; 5532fdaa386SBrock Mammen 5542fdaa386SBrock Mammen PCUITEMID_CHILD *apidl; 5552fdaa386SBrock Mammen UINT cidl; 5562fdaa386SBrock Mammen HRESULT hr = m_shellFolderView->GetSelectedObjects(&apidl, &cidl); 5572fdaa386SBrock Mammen if (FAILED_UNEXPECTEDLY(hr)) 5582fdaa386SBrock Mammen return hr; 5592fdaa386SBrock Mammen 5602fdaa386SBrock Mammen for (UINT i = 0; i < cidl; i++) 5612fdaa386SBrock Mammen { 5626d6bc885SBrock Mammen CComHeapPtr<ITEMIDLIST> pidl; 5632fdaa386SBrock Mammen DWORD attrs = 0; 5642fdaa386SBrock Mammen hr = SHILCreateFromPathW((LPCWSTR) apidl[i]->mkid.abID, &pidl, &attrs); 5652fdaa386SBrock Mammen if (SUCCEEDED(hr)) 5662fdaa386SBrock Mammen { 5672fdaa386SBrock Mammen SHOpenFolderAndSelectItems(NULL, 1, &pidl, 0); 5682fdaa386SBrock Mammen } 5692fdaa386SBrock Mammen } 5702fdaa386SBrock Mammen 5712fdaa386SBrock Mammen return S_OK; 5722fdaa386SBrock Mammen } 5732fdaa386SBrock Mammen case DFM_GETDEFSTATICID: 5742fdaa386SBrock Mammen return S_FALSE; 5752fdaa386SBrock Mammen } 5762fdaa386SBrock Mammen return Shell_DefaultContextMenuCallBack(m_pisfInner, pdtobj); 5772fdaa386SBrock Mammen } 5782fdaa386SBrock Mammen 579ccf9ce32SBrock Mammen //// *** IPersistFolder2 methods *** 580ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetCurFolder(LPITEMIDLIST *pidl) 581ccf9ce32SBrock Mammen { 582ccf9ce32SBrock Mammen *pidl = ILClone(m_pidl); 583ccf9ce32SBrock Mammen return S_OK; 584ccf9ce32SBrock Mammen } 585ccf9ce32SBrock Mammen 586ccf9ce32SBrock Mammen // *** IPersistFolder methods *** 587ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::Initialize(LPCITEMIDLIST pidl) 588ccf9ce32SBrock Mammen { 589ccf9ce32SBrock Mammen m_pidl = ILClone(pidl); 590ccf9ce32SBrock Mammen if (!m_pidl) 591ccf9ce32SBrock Mammen return E_OUTOFMEMORY; 592ccf9ce32SBrock Mammen 593c0799cd2SBrock Mammen return SHELL32_CoCreateInitSF(m_pidl, 594c0799cd2SBrock Mammen NULL, 595c0799cd2SBrock Mammen NULL, 596c0799cd2SBrock Mammen &CLSID_ShellFSFolder, 597c0799cd2SBrock Mammen IID_PPV_ARG(IShellFolder2, &m_pisfInner)); 598ccf9ce32SBrock Mammen } 599ccf9ce32SBrock Mammen 600ccf9ce32SBrock Mammen // *** IPersist methods *** 601ccf9ce32SBrock Mammen STDMETHODIMP CFindFolder::GetClassID(CLSID *pClassId) 602ccf9ce32SBrock Mammen { 603ccf9ce32SBrock Mammen if (pClassId == NULL) 604ccf9ce32SBrock Mammen return E_INVALIDARG; 605ccf9ce32SBrock Mammen memcpy(pClassId, &CLSID_FindFolder, sizeof(CLSID)); 606ccf9ce32SBrock Mammen return S_OK; 607ccf9ce32SBrock Mammen } 608