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