[SHELLFIND] Use case-insensitive string comparison
[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 StrStrCountNIA(const CHAR *lpFirst, const CStringA &lpSrch, UINT cchMax)
121 {
122 return StrStrNCount<CHAR, CStringA, _strnicmp>(lpFirst, lpSrch, cchMax);
123 }
124
125 static UINT StrStrCountNIW(const WCHAR *lpFirst, const CStringW &lpSrch, UINT cchMax)
126 {
127 return StrStrNCount<WCHAR, CStringW, _wcsnicmp>(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 = StrStrCountNIW((LPCWSTR) lpFileContent, pSearchData->szQueryW, size / sizeof(WCHAR));
152 }
153 else
154 {
155 uMatches = StrStrCountNIA((LPCSTR) lpFileContent, pSearchData->szQueryA, size / sizeof(CHAR));
156 }
157
158 UnmapViewOfFile(lpFileContent);
159
160 return uMatches;
161 }
162
163 static UINT RecursiveFind(LPCWSTR lpPath, _SearchData *pSearchData)
164 {
165 if (WaitForSingleObject(pSearchData->hStopEvent, 0) != WAIT_TIMEOUT)
166 return 0;
167
168 WCHAR szPath[MAX_PATH];
169 WIN32_FIND_DATAW FindData;
170 HANDLE hFindFile;
171 BOOL bMoreFiles = TRUE;
172 UINT uTotalFound = 0;
173
174 PathCombineW(szPath, lpPath, L"*.*");
175
176 for (hFindFile = FindFirstFileW(szPath, &FindData);
177 bMoreFiles && hFindFile != INVALID_HANDLE_VALUE;
178 bMoreFiles = FindNextFileW(hFindFile, &FindData))
179 {
180 if (!wcscmp(FindData.cFileName, L".") || !wcscmp(FindData.cFileName, L".."))
181 continue;
182
183 PathCombineW(szPath, lpPath, FindData.cFileName);
184
185 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
186 {
187 CStringW status;
188 status.Format(IDS_SEARCH_FOLDER, FindData.cFileName);
189 PostMessageW(pSearchData->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM) StrDupW(status.GetBuffer()));
190
191 uTotalFound += RecursiveFind(szPath, pSearchData);
192 }
193 else if ((pSearchData->szFileName.IsEmpty() || PathMatchSpecW(FindData.cFileName, pSearchData->szFileName))
194 && (pSearchData->szQueryA.IsEmpty() || SearchFile(szPath, pSearchData)))
195 {
196 uTotalFound++;
197 PostMessageW(pSearchData->hwnd, WM_SEARCH_ADD_RESULT, 0, (LPARAM) StrDupW(szPath));
198 }
199 }
200
201 if (hFindFile != INVALID_HANDLE_VALUE)
202 FindClose(hFindFile);
203
204 return uTotalFound;
205 }
206
207 DWORD WINAPI CFindFolder::SearchThreadProc(LPVOID lpParameter)
208 {
209 _SearchData *data = static_cast<_SearchData*>(lpParameter);
210
211 data->pFindFolder->NotifyConnections(DISPID_SEARCHSTART);
212
213 UINT uTotalFound = RecursiveFind(data->szPath, data);
214
215 data->pFindFolder->NotifyConnections(DISPID_SEARCHCOMPLETE);
216
217 CStringW status;
218 status.Format(IDS_SEARCH_FILES_FOUND, uTotalFound);
219 ::PostMessageW(data->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM) StrDupW(status.GetBuffer()));
220
221 delete data;
222
223 return 0;
224 }
225
226 void CFindFolder::NotifyConnections(DISPID id)
227 {
228 DISPPARAMS dispatchParams = {0};
229 CComDynamicUnkArray &subscribers =
230 IConnectionPointImpl<CFindFolder, &DIID_DSearchCommandEvents>::m_vec;
231 for (IUnknown** pSubscriber = subscribers.begin(); pSubscriber < subscribers.end(); pSubscriber++)
232 {
233 if (!*pSubscriber)
234 continue;
235
236 CComPtr<IDispatch> pDispatch;
237 HRESULT hResult = (*pSubscriber)->QueryInterface(IID_PPV_ARG(IDispatch, &pDispatch));
238 if (!FAILED_UNEXPECTEDLY(hResult))
239 pDispatch->Invoke(id, GUID_NULL, 0, DISPATCH_METHOD, &dispatchParams, NULL, NULL, NULL);
240 }
241 }
242
243 LRESULT CFindFolder::StartSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
244 {
245 if (!lParam)
246 return 0;
247
248 // Clear all previous search results
249 UINT uItemIndex;
250 m_shellFolderView->RemoveObject(NULL, &uItemIndex);
251
252 _SearchData* pSearchData = new _SearchData();
253 pSearchData->pFindFolder = this;
254 pSearchData->hwnd = m_hWnd;
255
256 SearchStart *pSearchParams = (SearchStart *) lParam;
257 pSearchData->szPath = pSearchParams->szPath;
258 pSearchData->szFileName = pSearchParams->szFileName;
259 pSearchData->szQueryA = pSearchParams->szQuery;
260 pSearchData->szQueryW = pSearchParams->szQuery;
261 SHFree(pSearchParams);
262
263 if (m_hStopEvent)
264 SetEvent(m_hStopEvent);
265 pSearchData->hStopEvent = m_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
266
267 if (!SHCreateThread(SearchThreadProc, pSearchData, NULL, NULL))
268 {
269 SHFree(pSearchData);
270 return HRESULT_FROM_WIN32(GetLastError());
271 }
272
273 return S_OK;
274 }
275
276 LRESULT CFindFolder::StopSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
277 {
278 if (m_hStopEvent)
279 {
280 SetEvent(m_hStopEvent);
281 m_hStopEvent = NULL;
282 }
283 return 0;
284 }
285
286 LRESULT CFindFolder::AddResult(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
287 {
288 if (!lParam)
289 return 0;
290
291 CComHeapPtr<WCHAR> lpPath((LPWSTR) lParam);
292
293 CComHeapPtr<ITEMIDLIST> lpSearchPidl(_ILCreate(lpPath));
294 if (lpSearchPidl)
295 {
296 UINT uItemIndex;
297 m_shellFolderView->AddObject(lpSearchPidl, &uItemIndex);
298 }
299
300 return 0;
301 }
302
303 LRESULT CFindFolder::UpdateStatus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
304 {
305 CComHeapPtr<WCHAR> status((LPWSTR) lParam);
306 if (m_shellBrowser)
307 {
308 m_shellBrowser->SetStatusTextSB(status);
309 }
310
311 return S_OK;
312 }
313
314 // *** IShellFolder2 methods ***
315 STDMETHODIMP CFindFolder::GetDefaultSearchGUID(GUID *pguid)
316 {
317 UNIMPLEMENTED;
318 return E_NOTIMPL;
319 }
320
321 STDMETHODIMP CFindFolder::EnumSearches(IEnumExtraSearch **ppenum)
322 {
323 UNIMPLEMENTED;
324 return E_NOTIMPL;
325 }
326
327 STDMETHODIMP CFindFolder::GetDefaultColumn(DWORD, ULONG *pSort, ULONG *pDisplay)
328 {
329 if (pSort)
330 *pSort = 0;
331 if (pDisplay)
332 *pDisplay = 0;
333 return S_OK;
334 }
335
336 STDMETHODIMP CFindFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
337 {
338 if (!pcsFlags)
339 return E_INVALIDARG;
340 if (iColumn >= _countof(g_ColumnDefs))
341 return m_pisfInner->GetDefaultColumnState(iColumn - _countof(g_ColumnDefs) + 1, pcsFlags);
342 *pcsFlags = g_ColumnDefs[iColumn].dwDefaultState;
343 return S_OK;
344 }
345
346 STDMETHODIMP CFindFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
347 {
348 return m_pisfInner->GetDetailsEx(pidl, pscid, pv);
349 }
350
351 STDMETHODIMP CFindFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *pDetails)
352 {
353 if (iColumn >= _countof(g_ColumnDefs))
354 return m_pisfInner->GetDetailsOf(_ILGetFSPidl(pidl), iColumn - _countof(g_ColumnDefs) + 1, pDetails);
355
356 pDetails->cxChar = g_ColumnDefs[iColumn].cxChar;
357 pDetails->fmt = g_ColumnDefs[iColumn].fmt;
358
359 if (!pidl)
360 return SHSetStrRet(&pDetails->str, g_ColumnDefs[iColumn].wzColumnName);
361
362 if (iColumn == 1)
363 {
364 WCHAR path[MAX_PATH];
365 wcscpy(path, _ILGetPath(pidl));
366 PathRemoveFileSpecW(path);
367 return SHSetStrRet(&pDetails->str, path);
368 }
369
370 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &pDetails->str);
371 }
372
373 STDMETHODIMP CFindFolder::MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
374 {
375 UNIMPLEMENTED;
376 return E_NOTIMPL;
377 }
378
379 // *** IShellFolder methods ***
380 STDMETHODIMP CFindFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten,
381 PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes)
382 {
383 UNIMPLEMENTED;
384 return E_NOTIMPL;
385 }
386
387 STDMETHODIMP CFindFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
388 {
389 *ppEnumIDList = NULL;
390 return S_FALSE;
391 }
392
393 STDMETHODIMP CFindFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
394 {
395 UNIMPLEMENTED;
396 return E_NOTIMPL;
397 }
398
399 STDMETHODIMP CFindFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
400 {
401 UNIMPLEMENTED;
402 return E_NOTIMPL;
403 }
404
405 STDMETHODIMP CFindFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
406 {
407 return m_pisfInner->CompareIDs(lParam, _ILGetFSPidl(pidl1), _ILGetFSPidl(pidl2));
408 }
409
410 STDMETHODIMP CFindFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
411 {
412 if (riid == IID_IShellView)
413 {
414 SFV_CREATE sfvparams = {};
415 sfvparams.cbSize = sizeof(SFV_CREATE);
416 sfvparams.pshf = this;
417 sfvparams.psfvcb = this;
418 HRESULT hr = SHCreateShellFolderView(&sfvparams, (IShellView **) ppvOut);
419 if (FAILED_UNEXPECTEDLY(hr))
420 {
421 return hr;
422 }
423
424 return ((IShellView * ) * ppvOut)->QueryInterface(IID_PPV_ARG(IShellFolderView, &m_shellFolderView));
425 }
426 return E_NOINTERFACE;
427 }
428
429 STDMETHODIMP CFindFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
430 {
431 CComHeapPtr<PCITEMID_CHILD> aFSPidl;
432 aFSPidl.Allocate(cidl);
433 for (UINT i = 0; i < cidl; i++)
434 {
435 aFSPidl[i] = _ILGetFSPidl(apidl[i]);
436 }
437
438 return m_pisfInner->GetAttributesOf(cidl, aFSPidl, rgfInOut);
439 }
440
441 STDMETHODIMP CFindFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid,
442 UINT *prgfInOut, LPVOID *ppvOut)
443 {
444 if (riid == IID_IDataObject && cidl == 1)
445 {
446 WCHAR path[MAX_PATH];
447 wcscpy(path, (LPCWSTR) apidl[0]->mkid.abID);
448 PathRemoveFileSpecW(path);
449 CComHeapPtr<ITEMIDLIST> rootPidl(ILCreateFromPathW(path));
450 if (!rootPidl)
451 return E_OUTOFMEMORY;
452 PCITEMID_CHILD aFSPidl[1];
453 aFSPidl[0] = _ILGetFSPidl(apidl[0]);
454 return IDataObject_Constructor(hwndOwner, rootPidl, aFSPidl, cidl, (IDataObject **) ppvOut);
455 }
456
457 if (cidl <= 0)
458 {
459 return m_pisfInner->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, ppvOut);
460 }
461
462 PCITEMID_CHILD *aFSPidl = new PCITEMID_CHILD[cidl];
463 for (UINT i = 0; i < cidl; i++)
464 {
465 aFSPidl[i] = _ILGetFSPidl(apidl[i]);
466 }
467
468 if (riid == IID_IContextMenu)
469 {
470 HKEY hKeys[16];
471 UINT cKeys = 0;
472 AddFSClassKeysToArray(aFSPidl[0], hKeys, &cKeys);
473
474 DEFCONTEXTMENU dcm;
475 dcm.hwnd = hwndOwner;
476 dcm.pcmcb = this;
477 dcm.pidlFolder = m_pidl;
478 dcm.psf = this;
479 dcm.cidl = cidl;
480 dcm.apidl = apidl;
481 dcm.cKeys = cKeys;
482 dcm.aKeys = hKeys;
483 dcm.punkAssociationInfo = NULL;
484 HRESULT hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut);
485 delete[] aFSPidl;
486
487 return hr;
488 }
489
490 HRESULT hr = m_pisfInner->GetUIObjectOf(hwndOwner, cidl, aFSPidl, riid, prgfInOut, ppvOut);
491 delete[] aFSPidl;
492
493 return hr;
494 }
495
496 STDMETHODIMP CFindFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET pName)
497 {
498 return m_pisfInner->GetDisplayNameOf(_ILGetFSPidl(pidl), dwFlags, pName);
499 }
500
501 STDMETHODIMP CFindFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags,
502 PITEMID_CHILD *pPidlOut)
503 {
504 UNIMPLEMENTED;
505 return E_NOTIMPL;
506 }
507
508 //// *** IShellFolderViewCB method ***
509 STDMETHODIMP CFindFolder::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
510 {
511 switch (uMsg)
512 {
513 case SFVM_DEFVIEWMODE:
514 {
515 FOLDERVIEWMODE *pViewMode = (FOLDERVIEWMODE *) lParam;
516 *pViewMode = FVM_DETAILS;
517 return S_OK;
518 }
519 case SFVM_WINDOWCREATED:
520 {
521 SubclassWindow((HWND) wParam);
522
523 CComPtr<IServiceProvider> pServiceProvider;
524 HRESULT hr = m_shellFolderView->QueryInterface(IID_PPV_ARG(IServiceProvider, &pServiceProvider));
525 if (FAILED_UNEXPECTEDLY(hr))
526 {
527 return hr;
528 }
529 return pServiceProvider->QueryService(SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &m_shellBrowser));
530 }
531 }
532 return E_NOTIMPL;
533 }
534
535 //// *** IContextMenuCB method ***
536 STDMETHODIMP CFindFolder::CallBack(IShellFolder *psf, HWND hwndOwner, IDataObject *pdtobj, UINT uMsg, WPARAM wParam, LPARAM lParam)
537 {
538 switch (uMsg)
539 {
540 case DFM_MERGECONTEXTMENU:
541 {
542 QCMINFO *pqcminfo = (QCMINFO *) lParam;
543 _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0);
544 _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_STRING, L"Open Containing Folder", MFS_ENABLED);
545 _InsertMenuItemW(pqcminfo->hmenu, pqcminfo->indexMenu++, TRUE, pqcminfo->idCmdFirst++, MFT_SEPARATOR, NULL, 0);
546 return S_OK;
547 }
548 case DFM_INVOKECOMMAND:
549 case DFM_INVOKECOMMANDEX:
550 {
551 if (wParam != 1)
552 break;
553
554 PCUITEMID_CHILD *apidl;
555 UINT cidl;
556 HRESULT hr = m_shellFolderView->GetSelectedObjects(&apidl, &cidl);
557 if (FAILED_UNEXPECTEDLY(hr))
558 return hr;
559
560 for (UINT i = 0; i < cidl; i++)
561 {
562 CComHeapPtr<ITEMIDLIST> pidl;
563 DWORD attrs = 0;
564 hr = SHILCreateFromPathW((LPCWSTR) apidl[i]->mkid.abID, &pidl, &attrs);
565 if (SUCCEEDED(hr))
566 {
567 SHOpenFolderAndSelectItems(NULL, 1, &pidl, 0);
568 }
569 }
570
571 return S_OK;
572 }
573 case DFM_GETDEFSTATICID:
574 return S_FALSE;
575 }
576 return Shell_DefaultContextMenuCallBack(m_pisfInner, pdtobj);
577 }
578
579 //// *** IPersistFolder2 methods ***
580 STDMETHODIMP CFindFolder::GetCurFolder(LPITEMIDLIST *pidl)
581 {
582 *pidl = ILClone(m_pidl);
583 return S_OK;
584 }
585
586 // *** IPersistFolder methods ***
587 STDMETHODIMP CFindFolder::Initialize(LPCITEMIDLIST pidl)
588 {
589 m_pidl = ILClone(pidl);
590 if (!m_pidl)
591 return E_OUTOFMEMORY;
592
593 return SHELL32_CoCreateInitSF(m_pidl,
594 NULL,
595 NULL,
596 &CLSID_ShellFSFolder,
597 IID_PPV_ARG(IShellFolder2, &m_pisfInner));
598 }
599
600 // *** IPersist methods ***
601 STDMETHODIMP CFindFolder::GetClassID(CLSID *pClassId)
602 {
603 if (pClassId == NULL)
604 return E_INVALIDARG;
605 memcpy(pClassId, &CLSID_FindFolder, sizeof(CLSID));
606 return S_OK;
607 }