[SHELLFIND] Use smart pointers for PIDLs
[reactos.git] / dll / win32 / browseui / shellfind / CSearchBar.cpp
1 /*
2 * ReactOS Explorer
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19 #include "CSearchBar.h"
20 #include <psdk/wingdi.h>
21
22 WINE_DEFAULT_DEBUG_CHANNEL(shellfind);
23
24 #if 1
25 #undef UNIMPLEMENTED
26
27 #define UNIMPLEMENTED DbgPrint("%s is UNIMPLEMENTED!\n", __FUNCTION__)
28 #endif
29
30 CSearchBar::CSearchBar() :
31 pSite(NULL),
32 fVisible(FALSE),
33 bFocused(FALSE)
34 {
35 }
36
37 CSearchBar::~CSearchBar()
38 {
39 }
40
41 void CSearchBar::InitializeSearchBar()
42 {
43 CreateWindowExW(0, WC_STATIC, L"Search by any or all of the criteria below.",
44 WS_CHILD | WS_VISIBLE,
45 10, 10, 200, 40,
46 m_hWnd, NULL,
47 _AtlBaseModule.GetModuleInstance(), NULL);
48
49 CreateWindowExW(0, WC_STATIC, L"A &word or phrase in the file:",
50 WS_CHILD | WS_VISIBLE,
51 10, 50, 500, 20,
52 m_hWnd, NULL,
53 _AtlBaseModule.GetModuleInstance(), NULL);
54 CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
55 WS_BORDER | WS_CHILD | WS_VISIBLE,
56 10, 70, 100, 20,
57 m_hWnd, NULL,
58 _AtlBaseModule.GetModuleInstance(), NULL);
59
60 CreateWindowExW(0, WC_STATIC, L"&Look in:",
61 WS_CHILD | WS_VISIBLE,
62 10, 100, 500, 20,
63 m_hWnd, NULL,
64 _AtlBaseModule.GetModuleInstance(), NULL);
65 CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
66 WS_BORDER | WS_CHILD | WS_VISIBLE,
67 10, 120, 100, 20,
68 m_hWnd, NULL,
69 _AtlBaseModule.GetModuleInstance(), NULL);
70
71 CreateWindowExW(0, WC_STATIC, L"&Look in:",
72 WS_CHILD | WS_VISIBLE,
73 10, 150, 500, 20,
74 m_hWnd, NULL,
75 _AtlBaseModule.GetModuleInstance(), NULL);
76 CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
77 WS_BORDER | WS_CHILD | WS_VISIBLE,
78 10, 180, 100, 20,
79 m_hWnd, NULL,
80 _AtlBaseModule.GetModuleInstance(), NULL);
81
82 CreateWindowExW(0, WC_BUTTON, L"Sea&rch",
83 WS_BORDER | WS_CHILD | WS_VISIBLE,
84 10, 210, 100, 20,
85 m_hWnd, NULL,
86 _AtlBaseModule.GetModuleInstance(), NULL);
87 }
88
89 HRESULT CSearchBar::ExecuteCommand(CComPtr<IContextMenu>& menu, UINT nCmd)
90 {
91 CComPtr<IOleWindow> pBrowserOleWnd;
92 CMINVOKECOMMANDINFO cmi;
93 HWND browserWnd;
94 HRESULT hr;
95
96 hr = IUnknown_QueryService(pSite, SID_SShellBrowser, IID_PPV_ARG(IOleWindow, &pBrowserOleWnd));
97 if (FAILED_UNEXPECTEDLY(hr))
98 return hr;
99
100 hr = pBrowserOleWnd->GetWindow(&browserWnd);
101 if (FAILED_UNEXPECTEDLY(hr))
102 return hr;
103
104 ZeroMemory(&cmi, sizeof(cmi));
105 cmi.cbSize = sizeof(cmi);
106 cmi.lpVerb = MAKEINTRESOURCEA(nCmd);
107 cmi.hwnd = browserWnd;
108 if (GetKeyState(VK_SHIFT) & 0x8000)
109 cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
110 if (GetKeyState(VK_CONTROL) & 0x8000)
111 cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
112
113 return menu->InvokeCommand(&cmi);
114 }
115
116
117 // *** ATL event handlers ***
118 LRESULT CSearchBar::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
119 {
120 bFocused = TRUE;
121 IUnknown_OnFocusChangeIS(pSite, reinterpret_cast<IUnknown*>(this), TRUE);
122 bHandled = FALSE;
123 return TRUE;
124 }
125
126 HRESULT CSearchBar::GetSearchResultsFolder(IShellBrowser **ppShellBrowser, HWND *pHwnd, IShellFolder **ppShellFolder)
127 {
128 HRESULT hr;
129 CComPtr<IShellBrowser> pShellBrowser;
130 if (!ppShellBrowser)
131 ppShellBrowser = &pShellBrowser;
132 if (!*ppShellBrowser)
133 {
134 hr = IUnknown_QueryService(m_pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, ppShellBrowser));
135 if (FAILED_UNEXPECTEDLY(hr))
136 return hr;
137 }
138
139 CComPtr<IShellView> pShellView;
140 hr = (*ppShellBrowser)->QueryActiveShellView(&pShellView);
141 if (FAILED(hr) || !pShellView)
142 return hr;
143
144 CComPtr<IFolderView> pFolderView;
145 hr = pShellView->QueryInterface(IID_PPV_ARG(IFolderView, &pFolderView));
146 if (FAILED(hr) || !pFolderView)
147 return hr;
148
149 CComPtr<IShellFolder> pShellFolder;
150 if (!ppShellFolder)
151 ppShellFolder = &pShellFolder;
152 hr = pFolderView->GetFolder(IID_PPV_ARG(IShellFolder, ppShellFolder));
153 if (FAILED(hr) || !pShellFolder)
154 return hr;
155
156 CLSID clsid;
157 hr = IUnknown_GetClassID(*ppShellFolder, &clsid);
158 if (FAILED(hr))
159 return hr;
160 if (clsid != CLSID_FindFolder)
161 return E_FAIL;
162
163 if (pHwnd)
164 {
165 hr = pShellView->GetWindow(pHwnd);
166 if (FAILED_UNEXPECTEDLY(hr))
167 return hr;
168 }
169
170 return S_OK;
171 }
172
173 LRESULT CSearchBar::OnSearchButtonClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
174 {
175 CComPtr<IShellBrowser> pShellBrowser;
176 HRESULT hr = IUnknown_QueryService(pSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pShellBrowser));
177 if (FAILED_UNEXPECTEDLY(hr))
178 return hr;
179
180 HWND hwnd;
181 if (FAILED(GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL)))
182 {
183 WCHAR szShellGuid[MAX_PATH];
184 const WCHAR shellGuidPrefix[] = L"shell:::";
185 memcpy(szShellGuid, shellGuidPrefix, sizeof(shellGuidPrefix));
186 hr = StringFromGUID2(CLSID_FindFolder, szShellGuid + _countof(shellGuidPrefix) - 1,
187 _countof(szShellGuid) - _countof(shellGuidPrefix));
188 if (FAILED_UNEXPECTEDLY(hr))
189 return hr;
190
191 CComHeapPtr<ITEMIDLIST> findFolderPidl;
192 hr = SHParseDisplayName(szShellGuid, NULL, &findFolderPidl, 0, NULL);
193 if (FAILED_UNEXPECTEDLY(hr))
194 return hr;
195
196 hr = pShellBrowser->BrowseObject(findFolderPidl, 0);
197 if (FAILED_UNEXPECTEDLY(hr))
198 return hr;
199 }
200
201 GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL);
202 if (hwnd)
203 // TODO: Use message ID in header file
204 ::PostMessageW(hwnd, WM_USER + 1, 0, (LPARAM) StrDupW(L"Starting search..."));
205
206 return S_OK;
207 }
208
209 LRESULT CSearchBar::OnClicked(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
210 {
211 HWND hwnd;
212 HRESULT hr = GetSearchResultsFolder(NULL, &hwnd, NULL);
213 if (SUCCEEDED(hr))
214 {
215 LPCWSTR path = L"C:\\readme.txt";
216 // TODO: Use message ID in header file
217 ::PostMessageW(hwnd, WM_USER, 0, (LPARAM) StrDupW(path));
218 }
219
220 return 0;
221 }
222
223
224 // *** IOleWindow methods ***
225 HRESULT STDMETHODCALLTYPE CSearchBar::GetWindow(HWND *lphwnd)
226 {
227 if (!lphwnd)
228 return E_INVALIDARG;
229 *lphwnd = m_hWnd;
230 return S_OK;
231 }
232
233 HRESULT STDMETHODCALLTYPE CSearchBar::ContextSensitiveHelp(BOOL fEnterMode)
234 {
235 UNIMPLEMENTED;
236 return E_NOTIMPL;
237 }
238
239
240 // *** IDockingWindow methods ***
241 HRESULT STDMETHODCALLTYPE CSearchBar::CloseDW(DWORD dwReserved)
242 {
243 // We do nothing, we don't have anything to save yet
244 TRACE("CloseDW called\n");
245 return S_OK;
246 }
247
248 HRESULT STDMETHODCALLTYPE CSearchBar::ResizeBorderDW(const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved)
249 {
250 /* Must return E_NOTIMPL according to MSDN */
251 return E_NOTIMPL;
252 }
253
254 HRESULT STDMETHODCALLTYPE CSearchBar::ShowDW(BOOL fShow)
255 {
256 fVisible = fShow;
257 ShowWindow(fShow);
258 return S_OK;
259 }
260
261
262 // *** IDeskBand methods ***
263 HRESULT STDMETHODCALLTYPE CSearchBar::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi)
264 {
265 if (!pdbi)
266 {
267 return E_INVALIDARG;
268 }
269
270 if (pdbi->dwMask & DBIM_MINSIZE)
271 {
272 pdbi->ptMinSize.x = 200;
273 pdbi->ptMinSize.y = 30;
274 }
275
276 if (pdbi->dwMask & DBIM_MAXSIZE)
277 {
278 pdbi->ptMaxSize.y = -1;
279 }
280
281 if (pdbi->dwMask & DBIM_INTEGRAL)
282 {
283 pdbi->ptIntegral.y = 1;
284 }
285
286 if (pdbi->dwMask & DBIM_ACTUAL)
287 {
288 pdbi->ptActual.x = 200;
289 pdbi->ptActual.y = 30;
290 }
291
292 if (pdbi->dwMask & DBIM_TITLE)
293 {
294 if (!LoadStringW(_AtlBaseModule.GetResourceInstance(), IDS_SEARCHLABEL, pdbi->wszTitle, _countof(pdbi->wszTitle)))
295 return HRESULT_FROM_WIN32(GetLastError());
296 }
297
298 if (pdbi->dwMask & DBIM_MODEFLAGS)
299 {
300 pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
301 }
302
303 if (pdbi->dwMask & DBIM_BKCOLOR)
304 {
305 pdbi->dwMask &= ~DBIM_BKCOLOR;
306 }
307 return S_OK;
308 }
309
310 LRESULT CALLBACK MyWindowProc(
311 _In_ HWND hwnd,
312 _In_ UINT uMsg,
313 _In_ WPARAM wParam,
314 _In_ LPARAM lParam
315 )
316 {
317 return 0;
318 }
319
320 // *** IObjectWithSite methods ***
321 HRESULT STDMETHODCALLTYPE CSearchBar::SetSite(IUnknown *pUnkSite)
322 {
323 HRESULT hr;
324 HWND parentWnd;
325
326 if (pUnkSite == pSite)
327 return S_OK;
328
329 TRACE("SetSite called \n");
330 if (!pUnkSite)
331 {
332 DestroyWindow();
333 m_hWnd = NULL;
334 }
335
336 if (pUnkSite != pSite)
337 {
338 pSite = NULL;
339 }
340
341 if(!pUnkSite)
342 return S_OK;
343
344 hr = IUnknown_GetWindow(pUnkSite, &parentWnd);
345 if (!SUCCEEDED(hr))
346 {
347 ERR("Could not get parent's window ! Status: %08lx\n", hr);
348 return E_INVALIDARG;
349 }
350
351 pSite = pUnkSite;
352
353 if (m_hWnd)
354 {
355 // Change its parent
356 SetParent(parentWnd);
357 }
358 else
359 {
360 CWindowImpl::Create(parentWnd);
361
362 InitializeSearchBar();
363 }
364 return S_OK;
365 }
366
367 HRESULT STDMETHODCALLTYPE CSearchBar::GetSite(REFIID riid, void **ppvSite)
368 {
369 if (!ppvSite)
370 return E_POINTER;
371 *ppvSite = pSite;
372 return S_OK;
373 }
374
375
376 // *** IOleCommandTarget methods ***
377 HRESULT STDMETHODCALLTYPE CSearchBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
378 {
379 UNIMPLEMENTED;
380 return E_NOTIMPL;
381 }
382
383 HRESULT STDMETHODCALLTYPE CSearchBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
384 {
385 UNIMPLEMENTED;
386 return E_NOTIMPL;
387 }
388
389
390 // *** IServiceProvider methods ***
391 HRESULT STDMETHODCALLTYPE CSearchBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
392 {
393 /* FIXME: we probably want to handle more services here */
394 return IUnknown_QueryService(pSite, SID_SShellBrowser, riid, ppvObject);
395 }
396
397
398 // *** IInputObject methods ***
399 HRESULT STDMETHODCALLTYPE CSearchBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
400 {
401 if (fActivate)
402 {
403 //SetFocus();
404 SetActiveWindow();
405 }
406 // TODO: handle message
407 if(lpMsg)
408 {
409 TranslateMessage(lpMsg);
410 DispatchMessage(lpMsg);
411 }
412 return S_OK;
413 }
414
415 HRESULT STDMETHODCALLTYPE CSearchBar::HasFocusIO()
416 {
417 return bFocused ? S_OK : S_FALSE;
418 }
419
420 HRESULT STDMETHODCALLTYPE CSearchBar::TranslateAcceleratorIO(LPMSG lpMsg)
421 {
422 if (lpMsg->hwnd == m_hWnd)
423 {
424 TranslateMessage(lpMsg);
425 DispatchMessage(lpMsg);
426 return S_OK;
427 }
428
429 return S_FALSE;
430 }
431
432 // *** IPersist methods ***
433 HRESULT STDMETHODCALLTYPE CSearchBar::GetClassID(CLSID *pClassID)
434 {
435 if (!pClassID)
436 return E_POINTER;
437 memcpy(pClassID, &CLSID_FileSearchBand, sizeof(CLSID));
438 return S_OK;
439 }
440
441
442 // *** IPersistStream methods ***
443 HRESULT STDMETHODCALLTYPE CSearchBar::IsDirty()
444 {
445 UNIMPLEMENTED;
446 return E_NOTIMPL;
447 }
448
449 HRESULT STDMETHODCALLTYPE CSearchBar::Load(IStream *pStm)
450 {
451 UNIMPLEMENTED;
452 return E_NOTIMPL;
453 }
454
455 HRESULT STDMETHODCALLTYPE CSearchBar::Save(IStream *pStm, BOOL fClearDirty)
456 {
457 UNIMPLEMENTED;
458 return E_NOTIMPL;
459 }
460
461 HRESULT STDMETHODCALLTYPE CSearchBar::GetSizeMax(ULARGE_INTEGER *pcbSize)
462 {
463 // TODO: calculate max size
464 UNIMPLEMENTED;
465 return E_NOTIMPL;
466 }
467
468
469 // *** IWinEventHandler methods ***
470 HRESULT STDMETHODCALLTYPE CSearchBar::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
471 {
472 return S_OK;
473 }
474
475 HRESULT STDMETHODCALLTYPE CSearchBar::IsWindowOwner(HWND hWnd)
476 {
477 return (hWnd == m_hWnd) ? S_OK : S_FALSE;
478 }
479
480 // *** IBandNavigate methods ***
481 HRESULT STDMETHODCALLTYPE CSearchBar::Select(long paramC)
482 {
483 UNIMPLEMENTED;
484 return E_NOTIMPL;
485 }
486
487 // *** INamespaceProxy ***
488 HRESULT STDMETHODCALLTYPE CSearchBar::GetNavigateTarget(long paramC, long param10, long param14)
489 {
490 UNIMPLEMENTED;
491 return E_NOTIMPL;
492 }
493
494 HRESULT STDMETHODCALLTYPE CSearchBar::Invoke(long paramC)
495 {
496 UNIMPLEMENTED;
497 return E_NOTIMPL;
498 }
499
500 HRESULT STDMETHODCALLTYPE CSearchBar::OnSelectionChanged(long paramC)
501 {
502 UNIMPLEMENTED;
503 return E_NOTIMPL;
504 }
505
506 HRESULT STDMETHODCALLTYPE CSearchBar::RefreshFlags(long paramC, long param10, long param14)
507 {
508 UNIMPLEMENTED;
509 return E_NOTIMPL;
510 }
511
512 HRESULT STDMETHODCALLTYPE CSearchBar::CacheItem(long paramC)
513 {
514 UNIMPLEMENTED;
515 return E_NOTIMPL;
516 }
517
518 // *** IDispatch methods ***
519 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfoCount(UINT *pctinfo)
520 {
521 UNIMPLEMENTED;
522 return E_NOTIMPL;
523 }
524
525 HRESULT STDMETHODCALLTYPE CSearchBar::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
526 {
527 UNIMPLEMENTED;
528 return E_NOTIMPL;
529 }
530
531 HRESULT STDMETHODCALLTYPE CSearchBar::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
532 {
533 UNIMPLEMENTED;
534 return E_NOTIMPL;
535 }
536
537 HRESULT STDMETHODCALLTYPE CSearchBar::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
538 {
539 TRACE("Unknown dispid requested: %08x\n", dispIdMember);
540 return E_INVALIDARG;
541 }