1 /*
2 * PROJECT: ReactOS Search Shell Extension
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Search UI
5 * COPYRIGHT: Copyright 2019 Brock Mammen
6 */
7
8 #include "CSearchBar.h"
9 #include <psdk/wingdi.h>
10 #include <commoncontrols.h>
11 #include <../browseui.h>
12 #include <shellapi.h>
13 #include <exdispid.h>
14
15 WINE_DEFAULT_DEBUG_CHANNEL(shellfind);
16
17 #if 1
18 #undef UNIMPLEMENTED
19
20 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
21 #endif
22
CSearchBar()23 CSearchBar::CSearchBar() :
24 m_pSite(NULL),
25 m_bVisible(FALSE)
26 {
27 }
28
~CSearchBar()29 CSearchBar::~CSearchBar()
30 {
31 }
32
OnInitDialog(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)33 LRESULT CSearchBar::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
34 {
35 HKEY hkey;
36 DWORD dwType;
37 DWORD size = sizeof(DWORD);
38 DWORD result;
39 DWORD SearchHiddenValue = 0;
40
41 result = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", 0, KEY_QUERY_VALUE, &hkey);
42 if (result == ERROR_SUCCESS)
43 {
44 if (RegQueryValueEx(hkey, L"SearchHidden", NULL, &dwType, (LPBYTE)&SearchHiddenValue, &size) == ERROR_SUCCESS)
45 {
46 if ((dwType != REG_DWORD) || (size != sizeof(DWORD)))
47 {
48 ERR("RegQueryKey for \"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SearchHidden\" returned error(s).\n");
49 SearchHiddenValue = 1;
50 }
51 else
52 {
53 TRACE("SearchHidden is '%d'.\n", SearchHiddenValue);
54 }
55 }
56 else
57 {
58 ERR("RegQueryKey for \"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SearchHidden\" Failed.\n");
59 }
60 RegCloseKey(hkey);
61 }
62 else
63 ERR("RegOpenKey for \"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\" Failed.\n");
64
65 if (SearchHiddenValue != 0)
66 CheckDlgButton(IDC_SEARCH_HIDDEN, BST_CHECKED);
67 else
68 CheckDlgButton(IDC_SEARCH_HIDDEN, BST_UNCHECKED);
69
70 SetSearchInProgress(FALSE);
71
72 HWND hCombobox = GetDlgItem(IDC_SEARCH_COMBOBOX);
73 CComPtr<IImageList> pImageList;
74 HRESULT hResult = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &pImageList));
75 SendMessage(hCombobox, CBEM_SETIMAGELIST, 0, FAILED_UNEXPECTEDLY(hResult) ? 0 : reinterpret_cast<LPARAM>(pImageList.p));
76
77 SendMessage(hCombobox, CBEM_SETEXTENDEDSTYLE,
78 CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT, CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT);
79 HWND hEditControl = reinterpret_cast<HWND>(SendMessage(hCombobox, CBEM_GETEDITCONTROL, 0, 0));
80 hResult = CAddressEditBox_CreateInstance(IID_PPV_ARG(IAddressEditBox, &m_AddressEditBox));
81 if (FAILED_UNEXPECTEDLY(hResult))
82 return FALSE;
83
84 hResult = m_AddressEditBox->Init(hCombobox, hEditControl, 0, m_pSite);
85 if (FAILED_UNEXPECTEDLY(hResult))
86 return FALSE;
87
88 // Subscribe to navigation events
89 CComPtr<IShellBrowser> pShellBrowser;
90 hResult = IUnknown_QueryService(m_pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pShellBrowser));
91 DWORD dwAdviseCookie;
92 if (SUCCEEDED(hResult))
93 AtlAdvise(pShellBrowser, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &dwAdviseCookie);
94
95 // Invoke the navigate event in case a search results folder is already open
96 DISPPARAMS params = {0};
97 Invoke(DISPID_NAVIGATECOMPLETE2, GUID_NULL, 0, DISPATCH_METHOD, ¶ms, NULL, NULL, NULL);
98
99 return TRUE;
100 }
101
102
103 // *** ATL event handlers ***
OnSetFocus(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)104 LRESULT CSearchBar::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
105 {
106 IUnknown_OnFocusChangeIS(m_pSite, static_cast<IDeskBand *>(this), TRUE);
107 bHandled = FALSE;
108 return TRUE;
109 }
110
GetSearchResultsFolder(IShellBrowser ** ppShellBrowser,HWND * pHwnd,IShellFolder ** ppShellFolder)111 HRESULT CSearchBar::GetSearchResultsFolder(IShellBrowser **ppShellBrowser, HWND *pHwnd, IShellFolder **ppShellFolder)
112 {
113 HRESULT hr;
114 CComPtr<IShellBrowser> pShellBrowser;
115 if (!ppShellBrowser)
116 ppShellBrowser = &pShellBrowser;
117 if (!*ppShellBrowser)
118 {
119 hr = IUnknown_QueryService(m_pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, ppShellBrowser));
120 if (FAILED_UNEXPECTEDLY(hr))
121 return hr;
122 }
123
124 CComPtr<IShellView> pShellView;
125 hr = (*ppShellBrowser)->QueryActiveShellView(&pShellView);
126 if (FAILED(hr) || !pShellView)
127 return hr;
128
129 CComPtr<IFolderView> pFolderView;
130 hr = pShellView->QueryInterface(IID_PPV_ARG(IFolderView, &pFolderView));
131 if (FAILED(hr) || !pFolderView)
132 return hr;
133
134 CComPtr<IShellFolder> pShellFolder;
135 if (!ppShellFolder)
136 ppShellFolder = &pShellFolder;
137 hr = pFolderView->GetFolder(IID_PPV_ARG(IShellFolder, ppShellFolder));
138 if (FAILED(hr) || !pShellFolder)
139 return hr;
140
141 CLSID clsid;
142 hr = IUnknown_GetClassID(*ppShellFolder, &clsid);
143 if (FAILED(hr))
144 return hr;
145 if (clsid != CLSID_FindFolder)
146 return E_FAIL;
147
148 if (pHwnd)
149 {
150 hr = pShellView->GetWindow(pHwnd);
151 if (FAILED_UNEXPECTEDLY(hr))
152 return hr;
153 }
154
155 return S_OK;
156 }
157
OnSearchButtonClicked(WORD wNotifyCode,WORD wID,HWND hWndCtl,BOOL & bHandled)158 LRESULT CSearchBar::OnSearchButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
159 {
160 size_t len = 0;
161 WCHAR endchar;
162 WCHAR startchar;
163
164 CComHeapPtr<SearchStart> pSearchStart(static_cast<SearchStart *>(CoTaskMemAlloc(sizeof(SearchStart))));
165 GetDlgItemText(IDC_SEARCH_FILENAME, pSearchStart->szFileName, _countof(pSearchStart->szFileName));
166 GetDlgItemText(IDC_SEARCH_QUERY, pSearchStart->szQuery, _countof(pSearchStart->szQuery));
167
168 pSearchStart->SearchHidden = IsDlgButtonChecked(IDC_SEARCH_HIDDEN);
169
170 if (!GetAddressEditBoxPath(pSearchStart->szPath))
171 {
172 ShellMessageBoxW(_AtlBaseModule.GetResourceInstance(), m_hWnd, MAKEINTRESOURCEW(IDS_SEARCHINVALID), MAKEINTRESOURCEW(IDS_SEARCHLABEL), MB_OK | MB_ICONERROR, pSearchStart->szPath);
173 return 0;
174 }
175
176 // See if we have an szFileName by testing for its entry lenth > 0 and our searched FileName does not contain
177 // an asterisk or a question mark. If so, then prepend and append an asterisk to the searched FileName.
178 // (i.e. it's equivalent to searching for *<the_file_name>* )
179 if (FAILED (StringCchLengthW (pSearchStart->szFileName, MAX_PATH, &len))) return 0;
180 if ((len > 0) && !wcspbrk(pSearchStart->szFileName, L"*?"))
181 {
182 endchar = pSearchStart->szFileName[len - 1];
183 startchar = pSearchStart->szFileName[0];
184 if ((len < MAX_PATH - 1) && (startchar != L'*'))
185 {
186 memmove(&pSearchStart->szFileName[1], &pSearchStart->szFileName[0],
187 len * sizeof(WCHAR) + sizeof(WCHAR));
188 len = len + 1;
189 pSearchStart->szFileName[0] = L'*';
190 }
191
192 // See if our last character is an asterisk and if not and we have room then add one
193 if ((len < MAX_PATH - 1) && (endchar != L'*'))
194 StringCchCatW(pSearchStart->szFileName, MAX_PATH, L"*");
195 }
196
197 // Print our final search string for szFileName
198 TRACE("Searched szFileName is '%S'.\n", pSearchStart->szFileName);
199
200 CComPtr<IShellBrowser> pShellBrowser;
201 HRESULT hr = IUnknown_QueryService(m_pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pShellBrowser));
202 if (FAILED_UNEXPECTEDLY(hr))
203 return 0;
204
205 HWND hwnd;
206 if (FAILED(GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL)))
207 {
208 // Open a new search results folder
209 WCHAR szShellGuid[MAX_PATH];
210 const WCHAR shellGuidPrefix[] = L"shell:::";
211 memcpy(szShellGuid, shellGuidPrefix, sizeof(shellGuidPrefix));
212 hr = StringFromGUID2(CLSID_FindFolder, szShellGuid + _countof(shellGuidPrefix) - 1,
213 _countof(szShellGuid) - _countof(shellGuidPrefix));
214 if (FAILED_UNEXPECTEDLY(hr))
215 return 0;
216
217 CComHeapPtr<ITEMIDLIST> findFolderPidl;
218 hr = SHParseDisplayName(szShellGuid, NULL, &findFolderPidl, 0, NULL);
219 if (FAILED_UNEXPECTEDLY(hr))
220 return 0;
221
222 hr = pShellBrowser->BrowseObject(findFolderPidl, 0);
223 if (FAILED_UNEXPECTEDLY(hr))
224 return 0;
225
226 hr = GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL);
227 if (FAILED_UNEXPECTEDLY(hr))
228 return 0;
229 }
230
231 ::PostMessageW(hwnd, WM_SEARCH_START, 0, (LPARAM) pSearchStart.Detach());
232
233 SetSearchInProgress(TRUE);
234
235 return 0;
236 }
237
OnStopButtonClicked(WORD wNotifyCode,WORD wID,HWND hWndCtl,BOOL & bHandled)238 LRESULT CSearchBar::OnStopButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
239 {
240 HWND hwnd;
241 HRESULT hr = GetSearchResultsFolder(NULL, &hwnd, NULL);
242 if (SUCCEEDED(hr))
243 ::PostMessageW(hwnd, WM_SEARCH_STOP, 0, 0);
244
245 return 0;
246 }
247
GetAddressEditBoxPath(WCHAR * szPath)248 BOOL CSearchBar::GetAddressEditBoxPath(WCHAR *szPath)
249 {
250 HWND hComboboxEx = GetDlgItem(IDC_SEARCH_COMBOBOX);
251 ::GetWindowTextW(hComboboxEx, szPath, MAX_PATH);
252 INT iSelectedIndex = SendMessageW(hComboboxEx, CB_GETCURSEL, 0, 0);
253 if (iSelectedIndex != CB_ERR)
254 {
255 WCHAR szItemText[MAX_PATH];
256 COMBOBOXEXITEMW item = {0};
257 item.mask = CBEIF_LPARAM | CBEIF_TEXT;
258 item.iItem = iSelectedIndex;
259 item.pszText = szItemText;
260 item.cchTextMax = _countof(szItemText);
261 SendMessageW(hComboboxEx, CBEM_GETITEMW, 0, (LPARAM)&item);
262
263 if (!wcscmp(szItemText, szPath) && SHGetPathFromIDListW((LPCITEMIDLIST)item.lParam, szItemText))
264 {
265 StringCbCopyW(szPath, MAX_PATH * sizeof(WCHAR), szItemText);
266 return TRUE;
267 }
268 }
269
270 DWORD dwAttributes = GetFileAttributesW(szPath);
271 return dwAttributes != INVALID_FILE_ATTRIBUTES
272 && (dwAttributes & FILE_ATTRIBUTE_DIRECTORY);
273 }
274
OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)275 LRESULT CSearchBar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
276 {
277 INT iWidth = LOWORD(lParam);
278 INT iPadding = 10;
279
280 ((CWindow)GetDlgItem(IDC_SEARCH_LABEL)).SetWindowPos(NULL, 0, 0, iWidth - iPadding, 40, SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
281
282 int inputs[] = { IDC_SEARCH_FILENAME, IDC_SEARCH_QUERY, IDC_SEARCH_COMBOBOX, IDC_SEARCH_BUTTON, IDC_SEARCH_STOP_BUTTON, IDC_PROGRESS_BAR };
283 HDWP hdwp = BeginDeferWindowPos(_countof(inputs));
284 for (SIZE_T i = 0; i < _countof(inputs); i++)
285 {
286 CWindow wnd = (CWindow) GetDlgItem(inputs[i]);
287 RECT rect;
288 wnd.GetWindowRect(&rect);
289 POINT pt = { rect.left, rect.top };
290 ScreenToClient(&pt);
291 hdwp = wnd.DeferWindowPos(hdwp,
292 HWND_TOP,
293 iPadding,
294 pt.y,
295 iWidth - iPadding * 2,
296 rect.bottom - rect.top,
297 SWP_NOZORDER | SWP_NOACTIVATE);
298 }
299 EndDeferWindowPos(hdwp);
300
301 return 0;
302 }
303
304
305 // *** IOleWindow methods ***
GetWindow(HWND * lphwnd)306 HRESULT STDMETHODCALLTYPE CSearchBar::GetWindow(HWND *lphwnd)
307 {
308 if (!lphwnd)
309 return E_INVALIDARG;
310 *lphwnd = m_hWnd;
311 return S_OK;
312 }
313
ContextSensitiveHelp(BOOL fEnterMode)314 HRESULT STDMETHODCALLTYPE CSearchBar::ContextSensitiveHelp(BOOL fEnterMode)
315 {
316 UNIMPLEMENTED;
317 return E_NOTIMPL;
318 }
319
320
321 // *** IDockingWindow methods ***
CloseDW(DWORD dwReserved)322 HRESULT STDMETHODCALLTYPE CSearchBar::CloseDW(DWORD dwReserved)
323 {
324 // We do nothing, we don't have anything to save yet
325 TRACE("CloseDW called\n");
326 return S_OK;
327 }
328
ResizeBorderDW(const RECT * prcBorder,IUnknown * punkToolbarSite,BOOL fReserved)329 HRESULT STDMETHODCALLTYPE CSearchBar::ResizeBorderDW(const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
330 {
331 /* Must return E_NOTIMPL according to MSDN */
332 return E_NOTIMPL;
333 }
334
ShowDW(BOOL fShow)335 HRESULT STDMETHODCALLTYPE CSearchBar::ShowDW(BOOL fShow)
336 {
337 m_bVisible = fShow;
338 ShowWindow(fShow);
339 return S_OK;
340 }
341
342
343 // *** IDeskBand methods ***
GetBandInfo(DWORD dwBandID,DWORD dwViewMode,DESKBANDINFO * pdbi)344 HRESULT STDMETHODCALLTYPE CSearchBar::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi)
345 {
346 if (!pdbi)
347 {
348 return E_INVALIDARG;
349 }
350
351 if (pdbi->dwMask & DBIM_MINSIZE)
352 {
353 pdbi->ptMinSize.x = 200;
354 pdbi->ptMinSize.y = 30;
355 }
356
357 if (pdbi->dwMask & DBIM_MAXSIZE)
358 {
359 pdbi->ptMaxSize.y = -1;
360 }
361
362 if (pdbi->dwMask & DBIM_INTEGRAL)
363 {
364 pdbi->ptIntegral.y = 1;
365 }
366
367 if (pdbi->dwMask & DBIM_ACTUAL)
368 {
369 pdbi->ptActual.x = 200;
370 pdbi->ptActual.y = 30;
371 }
372
373 if (pdbi->dwMask & DBIM_TITLE)
374 {
375 if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), IDS_SEARCHLABEL, pdbi->wszTitle, _countof(pdbi->wszTitle)))
376 return HRESULT_FROM_WIN32(GetLastError());
377 }
378
379 if (pdbi->dwMask & DBIM_MODEFLAGS)
380 {
381 pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
382 }
383
384 if (pdbi->dwMask & DBIM_BKCOLOR)
385 {
386 pdbi->dwMask &= ~DBIM_BKCOLOR;
387 }
388 return S_OK;
389 }
390
391
392 // *** IObjectWithSite methods ***
SetSite(IUnknown * pUnkSite)393 HRESULT STDMETHODCALLTYPE CSearchBar::SetSite(IUnknown *pUnkSite)
394 {
395 HRESULT hr;
396 HWND parentWnd;
397
398 if (pUnkSite == m_pSite)
399 return S_OK;
400
401 TRACE("SetSite called \n");
402 if (!pUnkSite)
403 {
404 DestroyWindow();
405 m_hWnd = NULL;
406 return S_OK;
407 }
408
409 hr = IUnknown_GetWindow(pUnkSite, &parentWnd);
410 if (!SUCCEEDED(hr))
411 {
412 ERR("Could not get parent's window ! Status: %08lx\n", hr);
413 return E_INVALIDARG;
414 }
415
416 m_pSite = pUnkSite;
417
418 if (m_hWnd)
419 {
420 // Change its parent
421 SetParent(parentWnd);
422 }
423 else
424 {
425 CDialogImpl::Create(parentWnd);
426
427 }
428 return S_OK;
429 }
430
GetSite(REFIID riid,void ** ppvSite)431 HRESULT STDMETHODCALLTYPE CSearchBar::GetSite(REFIID riid, void **ppvSite)
432 {
433 if (!ppvSite)
434 return E_POINTER;
435 *ppvSite = m_pSite;
436 return S_OK;
437 }
438
439
440 // *** IInputObject methods ***
UIActivateIO(BOOL fActivate,LPMSG lpMsg)441 HRESULT STDMETHODCALLTYPE CSearchBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
442 {
443 if (fActivate)
444 {
445 //SetFocus();
446 SetActiveWindow();
447 }
448 // TODO: handle message
449 if(lpMsg)
450 {
451 TranslateMessage(lpMsg);
452 DispatchMessage(lpMsg);
453 }
454 return S_OK;
455 }
456
HasFocusIO()457 HRESULT STDMETHODCALLTYPE CSearchBar::HasFocusIO()
458 {
459 return S_OK;
460 }
461
TranslateAcceleratorIO(LPMSG lpMsg)462 HRESULT STDMETHODCALLTYPE CSearchBar::TranslateAcceleratorIO(LPMSG lpMsg)
463 {
464 if (IsDialogMessage(lpMsg))
465 return S_OK;
466
467 if ((lpMsg->hwnd == m_hWnd || IsChild(lpMsg->hwnd)))
468 {
469 TranslateMessage(lpMsg);
470 DispatchMessage(lpMsg);
471 return S_OK;
472 }
473
474 return S_FALSE;
475 }
476
477 // *** IPersist methods ***
GetClassID(CLSID * pClassID)478 HRESULT STDMETHODCALLTYPE CSearchBar::GetClassID(CLSID *pClassID)
479 {
480 if (!pClassID)
481 return E_POINTER;
482 *pClassID = CLSID_FileSearchBand;
483 return S_OK;
484 }
485
486
487 // *** IPersistStream methods ***
IsDirty()488 HRESULT STDMETHODCALLTYPE CSearchBar::IsDirty()
489 {
490 UNIMPLEMENTED;
491 return E_NOTIMPL;
492 }
493
Load(IStream * pStm)494 HRESULT STDMETHODCALLTYPE CSearchBar::Load(IStream *pStm)
495 {
496 UNIMPLEMENTED;
497 return E_NOTIMPL;
498 }
499
Save(IStream * pStm,BOOL fClearDirty)500 HRESULT STDMETHODCALLTYPE CSearchBar::Save(IStream *pStm, BOOL fClearDirty)
501 {
502 UNIMPLEMENTED;
503 return E_NOTIMPL;
504 }
505
GetSizeMax(ULARGE_INTEGER * pcbSize)506 HRESULT STDMETHODCALLTYPE CSearchBar::GetSizeMax(ULARGE_INTEGER *pcbSize)
507 {
508 // TODO: calculate max size
509 UNIMPLEMENTED;
510 return E_NOTIMPL;
511 }
512
513
514 // *** IDispatch methods ***
GetTypeInfoCount(UINT * pctinfo)515 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfoCount(UINT *pctinfo)
516 {
517 UNIMPLEMENTED;
518 return E_NOTIMPL;
519 }
520
GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)521 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
522 {
523 UNIMPLEMENTED;
524 return E_NOTIMPL;
525 }
526
GetIDsOfNames(REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)527 HRESULT STDMETHODCALLTYPE CSearchBar::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
528 {
529 UNIMPLEMENTED;
530 return E_NOTIMPL;
531 }
532
SetSearchInProgress(BOOL bInProgress)533 void CSearchBar::SetSearchInProgress(BOOL bInProgress)
534 {
535 ::ShowWindow(GetDlgItem(IDC_SEARCH_BUTTON), bInProgress ? SW_HIDE : SW_SHOW);
536 ::ShowWindow(GetDlgItem(IDC_SEARCH_STOP_BUTTON), bInProgress ? SW_SHOW : SW_HIDE);
537 HWND hProgressBar = GetDlgItem(IDC_PROGRESS_BAR);
538 ::ShowWindow(hProgressBar, bInProgress ? SW_SHOW : SW_HIDE);
539 ::PostMessage(hProgressBar, PBM_SETMARQUEE, bInProgress, 0);
540 }
541
TrySubscribeToSearchEvents()542 HRESULT CSearchBar::TrySubscribeToSearchEvents()
543 {
544 CComPtr<IShellFolder> pShellFolder;
545 HRESULT hr = GetSearchResultsFolder(NULL, NULL, &pShellFolder);
546 if (FAILED(hr))
547 return hr;
548
549 DWORD fAdviseCookie;
550 hr = AtlAdvise(pShellFolder, static_cast<IDispatch *>(this), DIID_DSearchCommandEvents, &fAdviseCookie);
551 if (FAILED_UNEXPECTEDLY(hr))
552 return hr;
553
554 return S_OK;
555 }
556
Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)557 HRESULT STDMETHODCALLTYPE CSearchBar::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
558 {
559 switch (dispIdMember)
560 {
561 case DISPID_NAVIGATECOMPLETE2:
562 case DISPID_DOCUMENTCOMPLETE:
563 {
564 TrySubscribeToSearchEvents();
565
566 // Remove the search results folder from the address box
567 CComPtr<IDispatch> pDispatch;
568 HRESULT hResult = m_AddressEditBox->QueryInterface(IID_PPV_ARG(IDispatch, &pDispatch));
569 if (FAILED_UNEXPECTEDLY(hResult))
570 return hResult;
571 pDispatch->Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
572 CComPtr<IShellService> pShellService;
573 hResult = m_AddressEditBox->QueryInterface(IID_PPV_ARG(IShellService, &pShellService));
574 if (FAILED_UNEXPECTEDLY(hResult))
575 return hResult;
576 hResult = pShellService->SetOwner(NULL);
577 if (FAILED_UNEXPECTEDLY(hResult))
578 return hResult;
579 HWND hComboboxEx = GetDlgItem(IDC_SEARCH_COMBOBOX);
580 int index = SendMessageW(hComboboxEx, CB_GETCOUNT, 0, 0);
581 if (index <= 0)
582 return S_OK;
583 COMBOBOXEXITEMW item = {0};
584 item.mask = CBEIF_LPARAM;
585 item.iItem = index - 1;
586 SendMessageW(hComboboxEx, CBEM_GETITEMW, 0, (LPARAM)&item);
587 if (!item.lParam)
588 return S_OK;
589 CComPtr<IShellFolder> pDesktopFolder;
590 hResult = SHGetDesktopFolder(&pDesktopFolder);
591 if (FAILED_UNEXPECTEDLY(hResult))
592 return hResult;
593 CComPtr<IShellFolder> pShellFolder;
594 hResult = pDesktopFolder->BindToObject((LPCITEMIDLIST)item.lParam, NULL, IID_PPV_ARG(IShellFolder, &pShellFolder));
595 if (FAILED(hResult))
596 return S_OK;
597 CLSID clsid;
598 hResult = IUnknown_GetClassID(pShellFolder, &clsid);
599 if (SUCCEEDED(hResult) && clsid == CLSID_FindFolder)
600 {
601 SendMessageW(hComboboxEx, CBEM_DELETEITEM, item.iItem, 0);
602 SendMessageW(hComboboxEx, CB_SETCURSEL, 0, 0);
603 }
604 return S_OK;
605 }
606 case DISPID_SEARCHCOMPLETE:
607 case DISPID_SEARCHABORT:
608 SetSearchInProgress(FALSE);
609 return S_OK;
610 default:
611 return E_INVALIDARG;
612 }
613 }
614