[SHELLFIND] Remove duplicate search code
[reactos.git] / dll / win32 / browseui / shellfind / CFindFolder.cpp
1 #include "CFindFolder.h"
2 #include <exdispid.h>
3
4 WINE_DEFAULT_DEBUG_CHANNEL(shellfind);
5
6 // FIXME: Remove this declaration after the function has been fully implemented
7 EXTERN_C HRESULT
8 WINAPI
9 SHOpenFolderAndSelectItems(LPITEMIDLIST pidlFolder,
10 UINT cidl,
11 PCUITEMID_CHILD_ARRAY apidl,
12 DWORD dwFlags);
13
14 struct FolderViewColumns
15 {
16 LPCWSTR wzColumnName;
17 DWORD dwDefaultState;
18 int fmt;
19 int cxChar;
20 };
21
22 static FolderViewColumns g_ColumnDefs[] =
23 {
24 {L"Name", SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30},
25 {L"In Folder", SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_LEFT, 30},
26 {L"Relevance", SHCOLSTATE_TYPE_STR, LVCFMT_LEFT, 0}
27 };
28
29 CFindFolder::CFindFolder() :
30 m_hStopEvent(NULL)
31 {
32 }
33
34 static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath)
35 {
36 CComHeapPtr<ITEMIDLIST> lpFSPidl(ILCreateFromPathW(lpszPath));
37 if (!(LPITEMIDLIST)lpFSPidl)
38 {
39 ERR("Failed to create pidl from path\n");
40 return 0;
41 }
42 LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl);
43
44 int pathLen = (wcslen(lpszPath) + 1) * sizeof(WCHAR);
45 int cbData = sizeof(WORD) + pathLen + lpLastFSPidl->mkid.cb;
46 LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(cbData + sizeof(WORD));
47 if (!pidl)
48 return NULL;
49
50 LPBYTE p = (LPBYTE) pidl;
51 *((WORD *) p) = cbData;
52 p += sizeof(WORD);
53
54 memcpy(p, lpszPath, pathLen);
55 p += pathLen;
56
57 memcpy(p, lpLastFSPidl, lpLastFSPidl->mkid.cb);
58 p += lpLastFSPidl->mkid.cb;
59
60 *((WORD *) p) = 0;
61
62 return pidl;
63 }
64
65 static LPCWSTR _ILGetPath(LPCITEMIDLIST pidl)
66 {
67 if (!pidl || !pidl->mkid.cb)
68 return NULL;
69 return (LPCWSTR) pidl->mkid.abID;
70 }
71
72 static LPCITEMIDLIST _ILGetFSPidl(LPCITEMIDLIST pidl)
73 {
74 if (!pidl || !pidl->mkid.cb)
75 return pidl;
76 return (LPCITEMIDLIST) ((LPBYTE) pidl->mkid.abID
77 + ((wcslen((LPCWSTR) pidl->mkid.abID) + 1) * sizeof(WCHAR)));
78 }
79
80 struct _SearchData
81 {
82 HWND hwnd;
83 HANDLE hStopEvent;
84 CStringW szPath;
85 CStringW szFileName;
86 CStringA szQueryA;
87 CStringW szQueryW;
88 CComPtr<CFindFolder> pFindFolder;
89 };
90
91 template<typename TChar, typename TString, int (&StrNCmp)(const TChar *, const TChar *, size_t)>
92 static const TChar* StrStrN(const TChar *lpFirst, const TString &lpSrch, UINT cchMax)
93 {
94 if (!lpFirst || lpSrch.IsEmpty() || !cchMax)
95 return NULL;
96
97 for (UINT i = cchMax; i > 0 && *lpFirst; i--, lpFirst++)
98 {
99 if (!StrNCmp(lpFirst, lpSrch, lpSrch.GetLength()))
100 return (const TChar*)lpFirst;
101 }
102
103 return NULL;
104 }
105
106 template<typename TChar, typename TString, int (&StrNCmp)(const TChar *, const TChar *, size_t)>
107 static UINT StrStrNCount(const TChar *lpFirst, const TString &lpSrch, UINT cchMax)
108 {
109 const TChar *lpSearchEnd = lpFirst + cchMax;
110 UINT uCount = 0;
111 while (lpFirst < lpSearchEnd && (lpFirst = StrStrN<TChar, TString, StrNCmp>(lpFirst, lpSrch, cchMax)))
112 {
113 uCount++;
114 lpFirst += lpSrch.GetLength();
115 cchMax = lpSearchEnd - lpFirst;
116 }
117 return uCount;
118 }
119
120 static UINT StrStrCountA(const CHAR *lpFirst, const CStringA &lpSrch, UINT cchMax)
121 {
122 return StrStrNCount<CHAR, CStringA, strncmp>(lpFirst, lpSrch, cchMax);
123 }
124
125 static UINT StrStrCountW(const WCHAR *lpFirst, const CStringW &lpSrch, UINT cchMax)
126 {
127 return StrStrNCount<WCHAR, CStringW, wcsncmp>(lpFirst, lpSrch, cchMax);
128 }
129
130 static UINT SearchFile(LPCWSTR lpFilePath, _SearchData *pSearchData)
131 {
132 HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
133 if (hFile == INVALID_HANDLE_VALUE)
134 return 0;
135
136 DWORD size = GetFileSize(hFile, NULL);
137 HANDLE hFileMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
138 CloseHandle(hFile);
139 if (hFileMap == INVALID_HANDLE_VALUE)
140 return 0;
141
142 LPBYTE lpFileContent = (LPBYTE) MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
143 CloseHandle(hFileMap);
144 if (!lpFileContent)
145 return 0;
146
147 UINT uMatches = 0;
148 // Check for UTF-16 BOM
149 if (size >= 2 && lpFileContent[0] == 0xFF && lpFileContent[1] == 0xFE)
150 {
151 uMatches = StrStrCountW((LPCWSTR) lpFileContent, pSearchData->szQueryW, size / sizeof(WCHAR));
152 }
153 else
154 {
155 uMatches = StrStrCountA((LPCSTR) lpFileContent, pSearchData->szQueryA, size / sizeof(CHAR));
156 }
157
158 UnmapViewOfFile(lpFileContent);
159
160 return uMatches;
161 }
162
163 static VOID RecursiveFind(LPCWSTR lpPath, _SearchData *pSearchData)
164 {
165 if (WaitForSingleObject(pSearchData->hStopEvent, 0) != WAIT_TIMEOUT)
166 return;
167
168 WCHAR szPath[MAX_PATH];
169 WIN32_FIND_DATAW FindData;
170 HANDLE hFindFile;
171 BOOL bMoreFiles = TRUE;
172
173 PathCombineW(szPath, lpPath, L"*.*");
174
175 for (hFindFile = FindFirstFileW(szPath, &FindData);
176 bMoreFiles && hFindFile != INVALID_HANDLE_VALUE;
177 bMoreFiles = FindNextFileW(hFindFile, &FindData))
178 {
179 if (!wcscmp(FindData.cFileName, L".") || !wcscmp(FindData.cFileName, L".."))
180 continue;
181
182 PathCombineW(szPath, lpPath, FindData.cFileName);
183
184 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
185 {
186 CStringW* status = new CStringW();
187 status->Format(L"Searching '%s'", FindData.cFileName);
188 PostMessageW(pSearchData->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM) status);
189
190 RecursiveFind(szPath, pSearchData);
191 }
192 else if ((pSearchData->szFileName.IsEmpty() || PathMatchSpecW(FindData.cFileName, pSearchData->szFileName))
193 && (pSearchData->szQueryA.IsEmpty() || SearchFile(szPath, pSearchData)))
194 {
195 uTotalFound++;
196 PostMessageW(pSearchData->hwnd, WM_SEARCH_ADD_RESULT, 0, (LPARAM) StrDupW(szPath));
197 }
198 }
199
200 if (hFindFile != INVALID_HANDLE_VALUE)
201 FindClose(hFindFile);
202 }
203
204 DWORD WINAPI CFindFolder::SearchThreadProc(LPVOID lpParameter)
205 {
206 _SearchData *data = static_cast<_SearchData*>(lpParameter);
207
208 data->pFindFolder->NotifyConnections(DISPID_SEARCHSTART);
209
210 RecursiveFind(params->szPath, data);
211
212 data->pFindFolder->NotifyConnections(DISPID_SEARCHCOMPLETE);
213
214 SHFree(params);
215 SHFree(lpParameter);
216
217 return 0;
218 }
219
220 void CFindFolder::NotifyConnections(DISPID id)
221 {
222 DISPPARAMS dispatchParams = {0};
223 CComDynamicUnkArray &subscribers =
224 IConnectionPointImpl<CFindFolder, &DIID_DSearchCommandEvents>::m_vec;
225 for (IUnknown** pSubscriber = subscribers.begin(); pSubscriber < subscribers.end(); pSubscriber++)
226 {
227 if (!*pSubscriber)
228 continue;
229
230 CComPtr<IDispatch> pDispatch;
231 HRESULT hResult = (*pSubscriber)->QueryInterface(IID_PPV_ARG(IDispatch, &pDispatch));
232 if (!FAILED_UNEXPECTEDLY(hResult))
233 pDispatch->Invoke(id, GUID_NULL, 0, DISPATCH_METHOD, &dispatchParams, NULL, NULL, NULL);
234 }
235 }
236
237 LRESULT CFindFolder::StartSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
238 {
239 if (!lParam)
240 return 0;
241
242 // Clear all previous search results
243 UINT uItemIndex;
244 m_shellFolderView->RemoveObject(NULL, &uItemIndex);
245
246 _SearchData* pSearchData = new _SearchData();
247 pSearchData->pFindFolder = this;
248 pSearchData->hwnd = m_hWnd;
249
250 SearchStart *pSearchParams = (SearchStart *) lParam;
251 pSearchData->szPath = pSearchParams->szPath;
252 pSearchData->szFileName = pSearchParams->szFileName;
253 pSearchData->szQueryA = pSearchParams->szQuery;
254 pSearchData->szQueryW = pSearchParams->szQuery;
255 SHFree(pSearchParams);
256
257 if (m_hStopEvent)
258 SetEvent(m_hStopEvent);
259 pSearchData->hStopEvent = m_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
260
261 if (!SHCreateThread(SearchThreadProc, pSearchData, NULL, NULL))
262 {
263 SHFree(pSearchData);
264 return HRESULT_FROM_WIN32(GetLastError());
265 }
266
267 return S_OK;
268 }
269
270 LRESULT CFindFolder::StopSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
271 {
272 if (m_hStopEvent)
273 {
274 SetEvent(m_hStopEvent);
275 m_hStopEvent = NULL;
276 }
277 return 0;
278 }
279
280 LRESULT CFindFolder::AddResult(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
281 {
282 if (!lParam)
283 return 0;
284
285 CComHeapPtr<WCHAR> lpPath((LPWSTR) lParam);
286
287 CComHeapPtr<ITEMIDLIST> lpSearchPidl(_ILCreate(lpPath));
288 if (lpSearchPidl)
289 {
290 UINT uItemIndex;
291 m_shellFolderView->AddObject(lpSearchPidl, &uItemIndex);
292 }
293
294 return 0;
295 }
296
297 LRESULT CFindFolder::UpdateStatus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
298 {
299 CStringW *status = (CStringW *) lParam;
300 if (m_shellBrowser)
301 {
302 m_shellBrowser->SetStatusTextSB(status->GetBuffer());
303 }
304 delete status;
305
306 return S_OK;
307 }
308
309 // *** IShellFolder2 methods ***
310 STDMETHODIMP CFindFolder::GetDefaultSearchGUID(GUID *pguid)
311 {
312 UNIMPLEMENTED;
313 return E_NOTIMPL;
314 }
315
316 STDMETHODIMP CFindFolder::EnumSearches(IEnumExtraSearch **ppenum)
317 {
318 UNIMPLEMENTED;
319 return E_NOTIMPL;
320 }
321
322 STDMETHODIMP CFindFolder::GetDefaultColumn(DWORD, ULONG *pSort, ULONG *pDisplay)
323 {
324 if (pSort)
325 *pSort = 0;
326 if (pDisplay)
327 *pDisplay = 0;
328 return S_OK;
329 }
330
331 STDMETHODIMP CFindFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
332 {
333 if (!pcsFlags)
334 return E_INVALIDARG;
335 if (iColumn >= _countof(g_ColumnDefs))
336 return m_pisfInner->GetDefaultColumnState(iColumn - _countof(g_ColumnDefs) + 1, pcsFlags);
337 *pcsFlags = g_ColumnDefs[iColumn].dwDefaultState;
338 return S_OK;
339 }
340
341 STDMETHODIMP CFindFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
342 {
343 return m_pisfInner->GetDetailsEx(pidl, pscid, pv);
344 }
345
346 STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *pDetails)
347 {
348 if (iColumn >= _countof(g_ColumnDefs))
349 return m_pisfInner->GetDetailsOf(_ILGetFSPidl(pidl), iColumn - _countof(g_ColumnDefs) + 1, pDetails);
350
351 pDetails->cxChar = g_ColumnDefs[iColumn].cxChar;
352 pDetails->fmt = g_ColumnDefs[iColumn].fmt;
353
354 if (!pidl)
355 return SHSetStrRet(&pDetails->str, g_ColumnDefs[iColumn].wzColumnName);
356
357 if (iColumn == 1)
358 {
359 WCHAR path[MAX_PATH];
360 wcscpy(path, _ILGetPath(pidl));
361 PathRemoveFileSpecW(path);
362 return SHSetStrRet(&pDetails->str, path);
363 }
364
365 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str);
366 }
367
368 STDMETHODIMP CFindFolder::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
369 {
370 UNIMPLEMENTED;
371 return E_NOTIMPL;
372 }
373
374 // *** IShellFolder methods ***
375 STDMETHODIMP CFindFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten,
376 PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes)
377 {
378 UNIMPLEMENTED;
379 return E_NOTIMPL;
380 }
381
382 STDMETHODIMP CFindFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
383 {
384 *ppEnumIDList = NULL;
385 return S_FALSE;
386 }
387
388 STDMETHODIMP CFindFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
389 {
390 UNIMPLEMENTED;
391 return E_NOTIMPL;
392 }
393
394 STDMETHODIMP CFindFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
395 {
396 UNIMPLEMENTED;
397 return E_NOTIMPL;
398 }
399
400 STDMETHODIMP CFindFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
401 {
402 return m_pisfInner->CompareIDs(lParam, _ILGetFSPidl(pidl1), _ILGetFSPidl(pidl2));
403 }
404
405 STDMETHODIMP CFindFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
406 {
407 if (riid == IID_IShellView)
408 {
409 SFV_CREATE sfvparams = {};
410 sfvparams.cbSize = sizeof(SFV_CREATE);
411 sfvparams.pshf = this;
412 sfvparams.psfvcb = this;
413 HRESULT hr = SHCreateShellFolderView(&sfvparams, (IShellView **) ppvOut);
414 if (FAILED_UNEXPECTEDLY(hr))
415 {
416 return hr;
417 }
418
419 return ((IShellView * ) * ppvOut)->QueryInterface(IID_PPV_ARG(IShellFolderView, &m_shellFolderView));
420 }
421 return E_NOINTERFACE;
422 }
423
424 STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
425 {
426 CComHeapPtr<PCITEMID_CHILD> aFSPidl;
427 aFSPidl.Allocate(cidl);
428 for (UINT i = 0; i < cidl; i++)
429 {
430 aFSPidl[i] = _ILGetFSPidl(apidl[i]);
431 }
432
433 return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut);
434 }
435
436 STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
437 UINT *prgfInOut, LPVOID *ppvOut)
438 {
439 if (riid == IID_IDataObject && cidl == 1)
440 {
441 WCHAR path[MAX_PATH];
442 wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID);
443 PathRemoveFileSpecW(path);
444 CComHeapPtr<ITEMIDLIST> rootPidl(ILCreateFromPathW(path));
445 if (!rootPidl)
446 return E_OUTOFMEMORY;
447 PCITEMID_CHILD aFSPidl[1];
448 aFSPidl[0] = _ILGetFSPidl(apidl[0]);
449 return IDataObject_Constructor(hwndOwner, rootPidl, aFSPidl, cidl, (IDataObject **) ppvOut);
450 }
451
452 if (cidl <= 0)
453 {
454 return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
455 }
456
457 PCITEMID_CHILD *aFSPidl = new PCITEMID_CHILD[cidl];
458 for (UINT i = 0; i < cidl; i++)
459 {
460 aFSPidl[i] = _ILGetFSPidl(apidl[i]);
461 }
462
463 if (riid == IID_IContextMenu)
464 {
465 HKEY hKeys[16];
466 UINT cKeys = 0;
467 AddFSClassKeysToArray(aFSPidl[0], hKeys, &cKeys);
468
469 DEFCONTEXTMENU dcm;
470 dcm.hwnd = hwndOwner;
471 dcm.pcmcb = this;
472 dcm.pidlFolder = m_pidl;
473 dcm.psf = this;
474 dcm.cidl = cidl;
475 dcm.apidl = apidl;
476 dcm.cKeys = cKeys;
477 dcm.aKeys = hKeys;
478 dcm.punkAssociationInfo = NULL;
479 HRESULT hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut);
480 delete[] aFSPidl;
481
482 return hr;
483 }
484
485 HRESULT hr = m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut);
486 delete[] aFSPidl;
487
488 return hr;
489 }
490
491 STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName)
492 {
493 return m_pisfInner->GetDisplayNameOf(_ILGetFSPidl(pidl), dwFlags, pName);
494 }
495
496 STDMETHODIMP CFindFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags,
497 PITEMID_CHILD *pPidlOut)
498 {
499 UNIMPLEMENTED;
500 return E_NOTIMPL;
501 }
502
503 //// *** IShellFolderViewCB method ***
504 STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
505 {
506 switch (uMsg)
507 {
508 case SFVM_DEFVIEWMODE:
509 {
510 FOLDERVIEWMODE *pViewMode = (FOLDERVIEWMODE *) lParam;
511 *pViewMode = FVM_DETAILS;
512 return S_OK;
513 }
514 case SFVM_WINDOWCREATED:
515 {
516 SubclassWindow((HWND) wParam);
517
518 CComPtr<IServiceProvider> pServiceProvider;
519 HRESULT hr = m_shellFolderView->QueryInterface(IID_PPV_ARG(IServiceProvider, &pServiceProvider));
520 if (FAILED_UNEXPECTEDLY(hr))
521 {
522 return hr;
523 }
524 return pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser));
525 }
526 }
527 return E_NOTIMPL;
528 }
529
530 //// *** IContextMenuCB method ***
531 STDMETHODIMP CFindFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
532 {
533 switch (uMsg)
534 {
535 case DFM_MERGECONTEXTMENU:
536 {
537 QCMINFO *pqcminfo = (QCMINFO *) lParam;
538 _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0);
539 _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_STRING, L"Open Containing Folder", MFS_ENABLED);
540 _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0);
541 return S_OK;
542 }
543 case DFM_INVOKECOMMAND:
544 case DFM_INVOKECOMMANDEX:
545 {
546 if (wParam != 1)
547 break;
548
549 PCUITEMID_CHILD *apidl;
550 UINT cidl;
551 HRESULT hr = m_shellFolderView->GetSelectedObjects(&apidl, &cidl);
552 if (FAILED_UNEXPECTEDLY(hr))
553 return hr;
554
555 for (UINT i = 0; i < cidl; i++)
556 {
557 CComHeapPtr<ITEMIDLIST> pidl;
558 DWORD attrs = 0;
559 hr = SHILCreateFromPathW((LPCWSTR) apidl[i]->mkid.abID, &pidl, &attrs);
560 if (SUCCEEDED(hr))
561 {
562 SHOpenFolderAndSelectItems(NULL, 1, &pidl, 0);
563 }
564 }
565
566 return S_OK;
567 }
568 case DFM_GETDEFSTATICID:
569 return S_FALSE;
570 }
571 return Shell_DefaultContextMenuCallBack(m_pisfInner, pdtobj);
572 }
573
574 //// *** IPersistFolder2 methods ***
575 STDMETHODIMP CFindFolder::GetCurFolder(LPITEMIDLIST *pidl)
576 {
577 *pidl = ILClone(m_pidl);
578 return S_OK;
579 }
580
581 // *** IPersistFolder methods ***
582 STDMETHODIMP CFindFolder::Initialize(LPCITEMIDLIST pidl)
583 {
584 m_pidl = ILClone(pidl);
585 if (!m_pidl)
586 return E_OUTOFMEMORY;
587
588 return SHELL32_CoCreateInitSF(m_pidl,
589 NULL,
590 NULL,
591 &CLSID_ShellFSFolder,
592 IID_PPV_ARG(IShellFolder2, &m_pisfInner));
593 }
594
595 // *** IPersist methods ***
596 STDMETHODIMP CFindFolder::GetClassID(CLSID *pClassId)
597 {
598 if (pClassId == NULL)
599 return E_INVALIDARG;
600 memcpy(pClassId, &CLSID_FindFolder, sizeof(CLSID));
601 return S_OK;
602 }