shell32: Add IObjectWithSite implementation to the ExplorerBrowser control.
[wine.git] / dlls / shell32 / ebrowser.c
blobb243aa0ecda53a3b8d43275b98875d179d45e382
1 /*
2 * ExplorerBrowser Control implementation.
4 * Copyright 2010 David Hedberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
27 #include "winerror.h"
28 #include "windef.h"
29 #include "winbase.h"
31 #include "wine/list.h"
32 #include "wine/debug.h"
33 #include "debughlp.h"
35 #include "shell32_main.h"
36 #include "pidl.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(shell);
40 typedef struct _event_client {
41 struct list entry;
42 IExplorerBrowserEvents *pebe;
43 DWORD cookie;
44 } event_client;
46 typedef struct _travellog_entry {
47 struct list entry;
48 LPITEMIDLIST pidl;
49 } travellog_entry;
51 typedef struct _ExplorerBrowserImpl {
52 const IExplorerBrowserVtbl *lpVtbl;
53 const IShellBrowserVtbl *lpsbVtbl;
54 const ICommDlgBrowser3Vtbl *lpcdb3Vtbl;
55 const IObjectWithSiteVtbl *lpowsVtbl;
56 LONG ref;
57 BOOL destroyed;
59 HWND hwnd_main;
60 HWND hwnd_sv;
62 EXPLORER_BROWSER_OPTIONS eb_options;
63 FOLDERSETTINGS fs;
65 struct list event_clients;
66 DWORD events_next_cookie;
67 struct list travellog;
68 travellog_entry *travellog_cursor;
69 int travellog_count;
71 IShellView *psv;
72 RECT sv_rc;
73 LPITEMIDLIST current_pidl;
75 IUnknown *punk_site;
76 } ExplorerBrowserImpl;
78 /**************************************************************************
79 * Event functions.
81 static void events_unadvise_all(ExplorerBrowserImpl *This)
83 event_client *client, *curs;
84 TRACE("%p\n", This);
86 LIST_FOR_EACH_ENTRY_SAFE(client, curs, &This->event_clients, event_client, entry)
88 TRACE("Removing %p\n", client);
89 list_remove(&client->entry);
90 IExplorerBrowserEvents_Release(client->pebe);
91 HeapFree(GetProcessHeap(), 0, client);
95 static HRESULT events_NavigationPending(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
97 event_client *cursor;
98 HRESULT hres = S_OK;
100 TRACE("%p\n", This);
102 LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
104 TRACE("Notifying %p\n", cursor);
105 hres = IExplorerBrowserEvents_OnNavigationPending(cursor->pebe, pidl);
107 /* If this failed for any reason, the browsing is supposed to be aborted. */
108 if(FAILED(hres))
109 break;
112 return hres;
115 static void events_NavigationComplete(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
117 event_client *cursor;
119 TRACE("%p\n", This);
121 LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
123 TRACE("Notifying %p\n", cursor);
124 IExplorerBrowserEvents_OnNavigationComplete(cursor->pebe, pidl);
128 static void events_NavigationFailed(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
130 event_client *cursor;
132 TRACE("%p\n", This);
134 LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
136 TRACE("Notifying %p\n", cursor);
137 IExplorerBrowserEvents_OnNavigationFailed(cursor->pebe, pidl);
141 static void events_ViewCreated(ExplorerBrowserImpl *This, IShellView *psv)
143 event_client *cursor;
145 TRACE("%p\n", This);
147 LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
149 TRACE("Notifying %p\n", cursor);
150 IExplorerBrowserEvents_OnViewCreated(cursor->pebe, psv);
154 /**************************************************************************
155 * Travellog functions.
157 static void travellog_remove_entry(ExplorerBrowserImpl *This, travellog_entry *entry)
159 TRACE("Removing %p\n", entry);
161 list_remove(&entry->entry);
162 HeapFree(GetProcessHeap(), 0, entry);
163 This->travellog_count--;
166 static void travellog_remove_all_entries(ExplorerBrowserImpl *This)
168 travellog_entry *cursor, *cursor2;
169 TRACE("%p\n", This);
171 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
172 travellog_remove_entry(This, cursor);
174 This->travellog_cursor = NULL;
177 static void travellog_add_entry(ExplorerBrowserImpl *This, LPITEMIDLIST pidl)
179 travellog_entry *new, *cursor, *cursor2;
180 TRACE("%p (old count %d)\n", pidl, This->travellog_count);
182 /* Replace the old tail, if any, with the new entry */
183 if(This->travellog_cursor)
185 LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, &This->travellog, travellog_entry, entry)
187 if(cursor == This->travellog_cursor)
188 break;
189 travellog_remove_entry(This, cursor);
193 /* Create and add the new entry */
194 new = HeapAlloc(GetProcessHeap(), 0, sizeof(travellog_entry));
195 new->pidl = ILClone(pidl);
196 list_add_tail(&This->travellog, &new->entry);
197 This->travellog_cursor = new;
198 This->travellog_count++;
200 /* Remove the first few entries if the size limit is reached. */
201 if(This->travellog_count > 200)
203 UINT i = 0;
204 LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
206 if(i++ > 10)
207 break;
208 travellog_remove_entry(This, cursor);
213 static LPCITEMIDLIST travellog_go_back(ExplorerBrowserImpl *This)
215 travellog_entry *prev;
216 TRACE("%p, %p\n", This, This->travellog_cursor);
218 if(!This->travellog_cursor)
219 return NULL;
221 prev = LIST_ENTRY(list_prev(&This->travellog, &This->travellog_cursor->entry),
222 travellog_entry, entry);
223 if(!prev)
224 return NULL;
226 This->travellog_cursor = prev;
227 return prev->pidl;
230 static LPCITEMIDLIST travellog_go_forward(ExplorerBrowserImpl *This)
232 travellog_entry *next;
233 TRACE("%p, %p\n", This, This->travellog_cursor);
235 if(!This->travellog_cursor)
236 return NULL;
238 next = LIST_ENTRY(list_next(&This->travellog, &This->travellog_cursor->entry),
239 travellog_entry, entry);
240 if(!next)
241 return NULL;
243 This->travellog_cursor = next;
244 return next->pidl;
247 /**************************************************************************
248 * Helper functions
250 static void update_layout(ExplorerBrowserImpl *This)
252 RECT rc;
253 TRACE("%p\n", This);
255 GetClientRect(This->hwnd_main, &rc);
256 CopyRect(&This->sv_rc, &rc);
259 static void size_panes(ExplorerBrowserImpl *This)
261 MoveWindow(This->hwnd_sv,
262 This->sv_rc.left, This->sv_rc.top,
263 This->sv_rc.right - This->sv_rc.left, This->sv_rc.bottom - This->sv_rc.top,
264 TRUE);
267 static HRESULT change_viewmode(ExplorerBrowserImpl *This, UINT viewmode)
269 IFolderView *pfv;
270 HRESULT hr;
272 if(!This->psv)
273 return E_FAIL;
275 hr = IShellView_QueryInterface(This->psv, &IID_IFolderView, (void*)&pfv);
276 if(SUCCEEDED(hr))
278 hr = IFolderView_SetCurrentViewMode(pfv, This->fs.ViewMode);
279 IFolderView_Release(pfv);
282 return hr;
285 static HRESULT create_new_shellview(ExplorerBrowserImpl *This, IShellItem *psi)
287 IShellBrowser *psb = (IShellBrowser*)&This->lpsbVtbl;
288 IShellFolder *psf;
289 IShellView *psv;
290 HWND hwnd_new;
291 HRESULT hr;
293 TRACE("%p, %p\n", This, psi);
295 hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IShellFolder, (void**)&psf);
296 if(SUCCEEDED(hr))
298 hr = IShellFolder_CreateViewObject(psf, This->hwnd_main, &IID_IShellView, (void**)&psv);
299 if(SUCCEEDED(hr))
301 if(This->hwnd_sv)
303 IShellView_DestroyViewWindow(This->psv);
304 This->hwnd_sv = NULL;
307 hr = IShellView_CreateViewWindow(psv, This->psv, &This->fs, psb, &This->sv_rc, &hwnd_new);
308 if(SUCCEEDED(hr))
310 /* Replace the old shellview */
311 if(This->psv) IShellView_Release(This->psv);
313 This->psv = psv;
314 This->hwnd_sv = hwnd_new;
315 events_ViewCreated(This, psv);
317 else
319 ERR("CreateViewWindow failed (0x%x)\n", hr);
320 IShellView_Release(psv);
323 else
324 ERR("CreateViewObject failed (0x%x)\n", hr);
326 IShellFolder_Release(psf);
328 else
329 ERR("SI::BindToHandler failed (0x%x)\n", hr);
331 return hr;
334 static void get_interfaces_from_site(ExplorerBrowserImpl *This)
336 IServiceProvider *psp;
337 HRESULT hr;
339 /* Calling this with This->punk_site set to NULL should properly
340 * release any previously fetched interfaces.
343 if(This->punk_site)
345 hr = IUnknown_QueryInterface(This->punk_site, &IID_IServiceProvider, (void**)&psp);
346 if(SUCCEEDED(hr))
348 FIXME("Not requesting any interfaces.\n");
349 IServiceProvider_Release(psp);
351 else
352 ERR("Failed to get IServiceProvider from site.\n");
356 /**************************************************************************
357 * Main window related functions.
359 static LRESULT main_on_wm_create(HWND hWnd, CREATESTRUCTW *crs)
361 ExplorerBrowserImpl *This = crs->lpCreateParams;
362 TRACE("%p\n", This);
364 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LPARAM)This);
365 This->hwnd_main = hWnd;
367 return TRUE;
370 static LRESULT main_on_wm_size(ExplorerBrowserImpl *This)
372 update_layout(This);
373 size_panes(This);
375 return TRUE;
378 static LRESULT CALLBACK main_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
380 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
382 switch(uMessage)
384 case WM_CREATE: return main_on_wm_create(hWnd, (CREATESTRUCTW*)lParam);
385 case WM_SIZE: return main_on_wm_size(This);
386 default: return DefWindowProcW(hWnd, uMessage, wParam, lParam);
389 return 0;
392 /**************************************************************************
393 * IExplorerBrowser Implementation
395 static HRESULT WINAPI IExplorerBrowser_fnQueryInterface(IExplorerBrowser *iface,
396 REFIID riid, void **ppvObject)
398 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
399 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
401 *ppvObject = NULL;
402 if(IsEqualIID(riid, &IID_IExplorerBrowser) ||
403 IsEqualIID(riid, &IID_IUnknown))
405 *ppvObject = This;
407 else if(IsEqualIID(riid, &IID_IShellBrowser))
409 *ppvObject = &This->lpsbVtbl;
411 else if(IsEqualIID(riid, &IID_ICommDlgBrowser) ||
412 IsEqualIID(riid, &IID_ICommDlgBrowser2) ||
413 IsEqualIID(riid, &IID_ICommDlgBrowser3))
415 *ppvObject = &This->lpcdb3Vtbl;
417 else if(IsEqualIID(riid, &IID_IObjectWithSite))
419 *ppvObject = &This->lpowsVtbl;
422 if(*ppvObject)
424 IUnknown_AddRef((IUnknown*)*ppvObject);
425 return S_OK;
428 return E_NOINTERFACE;
431 static ULONG WINAPI IExplorerBrowser_fnAddRef(IExplorerBrowser *iface)
433 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
434 LONG ref = InterlockedIncrement(&This->ref);
435 TRACE("%p - ref %d\n", This, ref);
437 return ref;
440 static ULONG WINAPI IExplorerBrowser_fnRelease(IExplorerBrowser *iface)
442 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
443 LONG ref = InterlockedDecrement(&This->ref);
444 TRACE("%p - ref %d\n", This, ref);
446 if(!ref)
448 TRACE("Freeing.\n");
450 if(!This->destroyed)
451 IExplorerBrowser_Destroy(iface);
453 IObjectWithSite_SetSite((IObjectWithSite*)&This->lpowsVtbl, NULL);
455 HeapFree(GetProcessHeap(), 0, This);
456 return 0;
459 return ref;
462 static HRESULT WINAPI IExplorerBrowser_fnInitialize(IExplorerBrowser *iface,
463 HWND hwndParent, const RECT *prc,
464 const FOLDERSETTINGS *pfs)
466 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
467 WNDCLASSW wc;
468 LONG style;
469 static const WCHAR EB_CLASS_NAME[] =
470 {'E','x','p','l','o','r','e','r','B','r','o','w','s','e','r','C','o','n','t','r','o','l',0};
472 TRACE("%p (%p, %p, %p)\n", This, hwndParent, prc, pfs);
474 if(This->hwnd_main)
475 return E_UNEXPECTED;
477 if(!hwndParent)
478 return E_INVALIDARG;
480 if( !GetClassInfoW(shell32_hInstance, EB_CLASS_NAME, &wc) )
482 wc.style = CS_HREDRAW | CS_VREDRAW;
483 wc.lpfnWndProc = main_wndproc;
484 wc.cbClsExtra = 0;
485 wc.cbWndExtra = 0;
486 wc.hInstance = shell32_hInstance;
487 wc.hIcon = 0;
488 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
489 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
490 wc.lpszMenuName = NULL;
491 wc.lpszClassName = EB_CLASS_NAME;
493 if (!RegisterClassW(&wc)) return E_FAIL;
496 style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER;
497 This->hwnd_main = CreateWindowExW(WS_EX_CONTROLPARENT, EB_CLASS_NAME, NULL, style,
498 prc->left, prc->top,
499 prc->right - prc->left, prc->bottom - prc->top,
500 hwndParent, 0, shell32_hInstance, This);
502 if(!This->hwnd_main)
504 ERR("Failed to create the window.\n");
505 return E_FAIL;
508 This->fs.ViewMode = pfs ? pfs->ViewMode : FVM_DETAILS;
509 This->fs.fFlags = pfs ? (pfs->fFlags | FWF_NOCLIENTEDGE) : FWF_NOCLIENTEDGE;
511 return S_OK;
514 static HRESULT WINAPI IExplorerBrowser_fnDestroy(IExplorerBrowser *iface)
516 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
517 TRACE("%p\n", This);
519 if(This->psv)
521 IShellView_DestroyViewWindow(This->psv);
522 IShellView_Release(This->psv);
523 This->psv = NULL;
524 This->hwnd_sv = NULL;
527 events_unadvise_all(This);
528 travellog_remove_all_entries(This);
530 ILFree(This->current_pidl);
531 This->current_pidl = NULL;
533 DestroyWindow(This->hwnd_main);
534 This->destroyed = TRUE;
536 return S_OK;
539 static HRESULT WINAPI IExplorerBrowser_fnSetRect(IExplorerBrowser *iface,
540 HDWP *phdwp, RECT rcBrowser)
542 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
543 TRACE("%p (%p, %s)\n", This, phdwp, wine_dbgstr_rect(&rcBrowser));
545 if(phdwp)
547 *phdwp = DeferWindowPos(*phdwp, This->hwnd_main, NULL, rcBrowser.left, rcBrowser.top,
548 rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top,
549 SWP_NOZORDER | SWP_NOACTIVATE);
551 else
553 MoveWindow(This->hwnd_main, rcBrowser.left, rcBrowser.top,
554 rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top, TRUE);
557 return S_OK;
560 static HRESULT WINAPI IExplorerBrowser_fnSetPropertyBag(IExplorerBrowser *iface,
561 LPCWSTR pszPropertyBag)
563 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
564 FIXME("stub, %p (%s)\n", This, debugstr_w(pszPropertyBag));
566 return E_NOTIMPL;
569 static HRESULT WINAPI IExplorerBrowser_fnSetEmptyText(IExplorerBrowser *iface,
570 LPCWSTR pszEmptyText)
572 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
573 FIXME("stub, %p (%s)\n", This, debugstr_w(pszEmptyText));
575 return E_NOTIMPL;
578 static HRESULT WINAPI IExplorerBrowser_fnSetFolderSettings(IExplorerBrowser *iface,
579 const FOLDERSETTINGS *pfs)
581 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
582 TRACE("%p (%p)\n", This, pfs);
584 if(!pfs)
585 return E_INVALIDARG;
587 This->fs.ViewMode = pfs->ViewMode;
588 This->fs.fFlags = pfs->fFlags | FWF_NOCLIENTEDGE;
590 /* Change the settings of the current view, if any. */
591 return change_viewmode(This, This->fs.ViewMode);
594 static HRESULT WINAPI IExplorerBrowser_fnAdvise(IExplorerBrowser *iface,
595 IExplorerBrowserEvents *psbe,
596 DWORD *pdwCookie)
598 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
599 event_client *client;
600 TRACE("%p (%p, %p)\n", This, psbe, pdwCookie);
602 client = HeapAlloc(GetProcessHeap(), 0, sizeof(event_client));
603 client->pebe = psbe;
604 client->cookie = ++This->events_next_cookie;
606 IExplorerBrowserEvents_AddRef(psbe);
607 *pdwCookie = client->cookie;
609 list_add_tail(&This->event_clients, &client->entry);
611 return S_OK;
614 static HRESULT WINAPI IExplorerBrowser_fnUnadvise(IExplorerBrowser *iface,
615 DWORD dwCookie)
617 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
618 event_client *client;
619 TRACE("%p (0x%x)\n", This, dwCookie);
621 LIST_FOR_EACH_ENTRY(client, &This->event_clients, event_client, entry)
623 if(client->cookie == dwCookie)
625 list_remove(&client->entry);
626 IExplorerBrowserEvents_Release(client->pebe);
627 HeapFree(GetProcessHeap(), 0, client);
628 return S_OK;
632 return E_INVALIDARG;
635 static HRESULT WINAPI IExplorerBrowser_fnSetOptions(IExplorerBrowser *iface,
636 EXPLORER_BROWSER_OPTIONS dwFlag)
638 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
639 static const EXPLORER_BROWSER_OPTIONS unsupported_options =
640 EBO_SHOWFRAMES | EBO_ALWAYSNAVIGATE | EBO_NOWRAPPERWINDOW | EBO_HTMLSHAREPOINTVIEW;
642 TRACE("%p (0x%x)\n", This, dwFlag);
644 if(dwFlag & unsupported_options)
645 FIXME("Flags 0x%08x contains unsupported options.\n", dwFlag);
647 This->eb_options = dwFlag;
649 return S_OK;
652 static HRESULT WINAPI IExplorerBrowser_fnGetOptions(IExplorerBrowser *iface,
653 EXPLORER_BROWSER_OPTIONS *pdwFlag)
655 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
656 TRACE("%p (%p)\n", This, pdwFlag);
658 *pdwFlag = This->eb_options;
660 return S_OK;
663 static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
664 PCUIDLIST_RELATIVE pidl,
665 UINT uFlags)
667 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
668 LPITEMIDLIST absolute_pidl = NULL;
669 HRESULT hr;
670 static const UINT unsupported_browse_flags =
671 SBSP_NEWBROWSER | EBF_SELECTFROMDATAOBJECT | EBF_NODROPTARGET;
672 TRACE("%p (%p, 0x%x)\n", This, pidl, uFlags);
674 if(!This->hwnd_main)
675 return E_FAIL;
677 if(This->destroyed)
678 return HRESULT_FROM_WIN32(ERROR_BUSY);
680 if(This->current_pidl && (This->eb_options & EBO_NAVIGATEONCE))
681 return E_FAIL;
683 if(uFlags & SBSP_EXPLOREMODE)
684 return E_INVALIDARG;
686 if(uFlags & unsupported_browse_flags)
687 FIXME("Argument 0x%x contains unsupported flags.\n", uFlags);
689 if(uFlags & SBSP_NAVIGATEBACK)
691 TRACE("SBSP_NAVIGATEBACK\n");
692 absolute_pidl = ILClone(travellog_go_back(This));
693 if(!absolute_pidl && !This->current_pidl)
694 return E_FAIL;
695 else if(!absolute_pidl)
696 return S_OK;
699 else if(uFlags & SBSP_NAVIGATEFORWARD)
701 TRACE("SBSP_NAVIGATEFORWARD\n");
702 absolute_pidl = ILClone(travellog_go_forward(This));
703 if(!absolute_pidl && !This->current_pidl)
704 return E_FAIL;
705 else if(!absolute_pidl)
706 return S_OK;
709 else if(uFlags & SBSP_PARENT)
711 if(This->current_pidl)
713 if(_ILIsPidlSimple(This->current_pidl))
715 absolute_pidl = _ILCreateDesktop();
717 else
719 absolute_pidl = ILClone(This->current_pidl);
720 ILRemoveLastID(absolute_pidl);
723 if(!absolute_pidl)
725 ERR("Failed to get parent pidl.\n");
726 return E_FAIL;
730 else if(uFlags & SBSP_RELATIVE)
732 /* SBSP_RELATIVE has precedence over SBSP_ABSOLUTE */
733 TRACE("SBSP_RELATIVE\n");
734 if(This->current_pidl)
736 absolute_pidl = ILCombine(This->current_pidl, pidl);
738 if(!absolute_pidl)
740 ERR("Failed to get absolute pidl.\n");
741 return E_FAIL;
744 else
746 TRACE("SBSP_ABSOLUTE\n");
747 absolute_pidl = ILClone(pidl);
748 if(!absolute_pidl && !This->current_pidl)
749 return E_INVALIDARG;
750 else if(!absolute_pidl)
751 return S_OK;
754 /* TODO: Asynchronous browsing. Return S_OK here and finish in
755 * another thread. */
757 hr = events_NavigationPending(This, absolute_pidl);
758 if(FAILED(hr))
760 TRACE("Browsing aborted.\n");
761 ILFree(absolute_pidl);
762 return E_FAIL;
765 get_interfaces_from_site(This);
767 /* Only browse if the new pidl differs from the old */
768 if(!ILIsEqual(This->current_pidl, absolute_pidl))
770 IShellItem *psi;
771 hr = SHCreateItemFromIDList(absolute_pidl, &IID_IShellItem, (void**)&psi);
772 if(SUCCEEDED(hr))
774 hr = create_new_shellview(This, psi);
775 if(FAILED(hr))
777 events_NavigationFailed(This, absolute_pidl);
778 ILFree(absolute_pidl);
779 IShellItem_Release(psi);
780 return E_FAIL;
783 /* Add to travellog */
784 if( !(This->eb_options & EBO_NOTRAVELLOG) &&
785 !(uFlags & (SBSP_NAVIGATEFORWARD|SBSP_NAVIGATEBACK)) )
787 travellog_add_entry(This, absolute_pidl);
790 IShellItem_Release(psi);
794 events_NavigationComplete(This, absolute_pidl);
795 ILFree(This->current_pidl);
796 This->current_pidl = absolute_pidl;
798 return S_OK;
801 static HRESULT WINAPI IExplorerBrowser_fnBrowseToObject(IExplorerBrowser *iface,
802 IUnknown *punk, UINT uFlags)
804 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
805 LPITEMIDLIST pidl;
806 HRESULT hr;
807 TRACE("%p (%p, 0x%x)\n", This, punk, uFlags);
809 if(!punk)
810 return IExplorerBrowser_fnBrowseToIDList(iface, NULL, uFlags);
812 hr = SHGetIDListFromObject(punk, &pidl);
813 if(SUCCEEDED(hr))
815 hr = IExplorerBrowser_BrowseToIDList(iface, pidl, uFlags);
816 ILFree(pidl);
819 return hr;
822 static HRESULT WINAPI IExplorerBrowser_fnFillFromObject(IExplorerBrowser *iface,
823 IUnknown *punk,
824 EXPLORER_BROWSER_FILL_FLAGS dwFlags)
826 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
827 FIXME("stub, %p (%p, 0x%x)\n", This, punk, dwFlags);
829 return E_NOTIMPL;
832 static HRESULT WINAPI IExplorerBrowser_fnRemoveAll(IExplorerBrowser *iface)
834 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
835 FIXME("stub, %p\n", This);
837 return E_NOTIMPL;
840 static HRESULT WINAPI IExplorerBrowser_fnGetCurrentView(IExplorerBrowser *iface,
841 REFIID riid, void **ppv)
843 ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
844 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppv);
846 if(!This->psv)
847 return E_FAIL;
849 return IShellView_QueryInterface(This->psv, riid, ppv);
852 static const IExplorerBrowserVtbl vt_IExplorerBrowser =
854 IExplorerBrowser_fnQueryInterface,
855 IExplorerBrowser_fnAddRef,
856 IExplorerBrowser_fnRelease,
857 IExplorerBrowser_fnInitialize,
858 IExplorerBrowser_fnDestroy,
859 IExplorerBrowser_fnSetRect,
860 IExplorerBrowser_fnSetPropertyBag,
861 IExplorerBrowser_fnSetEmptyText,
862 IExplorerBrowser_fnSetFolderSettings,
863 IExplorerBrowser_fnAdvise,
864 IExplorerBrowser_fnUnadvise,
865 IExplorerBrowser_fnSetOptions,
866 IExplorerBrowser_fnGetOptions,
867 IExplorerBrowser_fnBrowseToIDList,
868 IExplorerBrowser_fnBrowseToObject,
869 IExplorerBrowser_fnFillFromObject,
870 IExplorerBrowser_fnRemoveAll,
871 IExplorerBrowser_fnGetCurrentView
874 /**************************************************************************
875 * IShellBrowser Implementation
878 static inline ExplorerBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
880 return (ExplorerBrowserImpl *)((char*)iface - FIELD_OFFSET(ExplorerBrowserImpl, lpsbVtbl));
883 static HRESULT WINAPI IShellBrowser_fnQueryInterface(IShellBrowser *iface,
884 REFIID riid, void **ppvObject)
886 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
887 TRACE("%p\n", This);
888 return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
891 static ULONG WINAPI IShellBrowser_fnAddRef(IShellBrowser *iface)
893 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
894 TRACE("%p\n", This);
895 return IUnknown_AddRef((IUnknown*) This);
898 static ULONG WINAPI IShellBrowser_fnRelease(IShellBrowser *iface)
900 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
901 TRACE("%p\n", This);
902 return IUnknown_Release((IUnknown*) This);
905 static HRESULT WINAPI IShellBrowser_fnGetWindow(IShellBrowser *iface, HWND *phwnd)
907 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
908 TRACE("%p (%p)\n", This, phwnd);
910 if(!This->hwnd_main)
911 return E_FAIL;
913 *phwnd = This->hwnd_main;
914 return S_OK;
917 static HRESULT WINAPI IShellBrowser_fnContextSensitiveHelp(IShellBrowser *iface,
918 BOOL fEnterMode)
920 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
921 FIXME("stub, %p (%d)\n", This, fEnterMode);
923 return E_NOTIMPL;
926 static HRESULT WINAPI IShellBrowser_fnInsertMenusSB(IShellBrowser *iface,
927 HMENU hmenuShared,
928 LPOLEMENUGROUPWIDTHS lpMenuWidths)
930 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
931 TRACE("%p (%p, %p)\n", This, hmenuShared, lpMenuWidths);
933 /* Not implemented. */
934 return E_NOTIMPL;
937 static HRESULT WINAPI IShellBrowser_fnSetMenuSB(IShellBrowser *iface,
938 HMENU hmenuShared,
939 HOLEMENU holemenuReserved,
940 HWND hwndActiveObject)
942 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
943 TRACE("%p (%p, %p, %p)\n", This, hmenuShared, holemenuReserved, hwndActiveObject);
945 /* Not implemented. */
946 return E_NOTIMPL;
949 static HRESULT WINAPI IShellBrowser_fnRemoveMenusSB(IShellBrowser *iface,
950 HMENU hmenuShared)
952 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
953 TRACE("%p (%p)\n", This, hmenuShared);
955 /* Not implemented. */
956 return E_NOTIMPL;
959 static HRESULT WINAPI IShellBrowser_fnSetStatusTextSB(IShellBrowser *iface,
960 LPCOLESTR pszStatusText)
962 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
963 FIXME("stub, %p (%s)\n", This, debugstr_w(pszStatusText));
965 return E_NOTIMPL;
968 static HRESULT WINAPI IShellBrowser_fnEnableModelessSB(IShellBrowser *iface,
969 BOOL fEnable)
971 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
972 FIXME("stub, %p (%d)\n", This, fEnable);
974 return E_NOTIMPL;
977 static HRESULT WINAPI IShellBrowser_fnTranslateAcceleratorSB(IShellBrowser *iface,
978 MSG *pmsg, WORD wID)
980 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
981 FIXME("stub, %p (%p, 0x%x)\n", This, pmsg, wID);
983 return E_NOTIMPL;
986 static HRESULT WINAPI IShellBrowser_fnBrowseObject(IShellBrowser *iface,
987 LPCITEMIDLIST pidl, UINT wFlags)
989 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
990 TRACE("%p (%p, %x)\n", This, pidl, wFlags);
992 return IExplorerBrowser_fnBrowseToIDList((IExplorerBrowser*)This, pidl, wFlags);
995 static HRESULT WINAPI IShellBrowser_fnGetViewStateStream(IShellBrowser *iface,
996 DWORD grfMode,
997 IStream **ppStrm)
999 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1000 FIXME("stub, %p (0x%x, %p)\n", This, grfMode, ppStrm);
1002 *ppStrm = NULL;
1003 return E_FAIL;
1006 static HRESULT WINAPI IShellBrowser_fnGetControlWindow(IShellBrowser *iface,
1007 UINT id, HWND *phwnd)
1009 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1010 TRACE("%p (%d, %p)\n", This, id, phwnd);
1012 /* Not implemented. */
1013 return E_NOTIMPL;
1016 static HRESULT WINAPI IShellBrowser_fnSendControlMsg(IShellBrowser *iface,
1017 UINT id, UINT uMsg,
1018 WPARAM wParam, LPARAM lParam,
1019 LRESULT *pret)
1021 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1022 FIXME("stub, %p (%d, %d, %lx, %lx, %p)\n", This, id, uMsg, wParam, lParam, pret);
1024 return E_NOTIMPL;
1027 static HRESULT WINAPI IShellBrowser_fnQueryActiveShellView(IShellBrowser *iface,
1028 IShellView **ppshv)
1030 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1031 TRACE("%p (%p)\n", This, ppshv);
1033 if(!This->psv)
1034 return E_FAIL;
1036 *ppshv = This->psv;
1037 IShellView_AddRef(This->psv);
1039 return S_OK;
1042 static HRESULT WINAPI IShellBrowser_fnOnViewWindowActive(IShellBrowser *iface,
1043 IShellView *pshv)
1045 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1046 FIXME("stub, %p (%p)\n", This, pshv);
1048 return E_NOTIMPL;
1051 static HRESULT WINAPI IShellBrowser_fnSetToolbarItems(IShellBrowser *iface,
1052 LPTBBUTTONSB lpButtons,
1053 UINT nButtons, UINT uFlags)
1055 ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1056 FIXME("stub, %p (%p, %d, 0x%x)\n", This, lpButtons, nButtons, uFlags);
1058 return E_NOTIMPL;
1061 static const IShellBrowserVtbl vt_IShellBrowser = {
1062 IShellBrowser_fnQueryInterface,
1063 IShellBrowser_fnAddRef,
1064 IShellBrowser_fnRelease,
1065 IShellBrowser_fnGetWindow,
1066 IShellBrowser_fnContextSensitiveHelp,
1067 IShellBrowser_fnInsertMenusSB,
1068 IShellBrowser_fnSetMenuSB,
1069 IShellBrowser_fnRemoveMenusSB,
1070 IShellBrowser_fnSetStatusTextSB,
1071 IShellBrowser_fnEnableModelessSB,
1072 IShellBrowser_fnTranslateAcceleratorSB,
1073 IShellBrowser_fnBrowseObject,
1074 IShellBrowser_fnGetViewStateStream,
1075 IShellBrowser_fnGetControlWindow,
1076 IShellBrowser_fnSendControlMsg,
1077 IShellBrowser_fnQueryActiveShellView,
1078 IShellBrowser_fnOnViewWindowActive,
1079 IShellBrowser_fnSetToolbarItems
1082 /**************************************************************************
1083 * ICommDlgBrowser3 Implementation
1086 static inline ExplorerBrowserImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
1088 return (ExplorerBrowserImpl *)((char*)iface - FIELD_OFFSET(ExplorerBrowserImpl, lpcdb3Vtbl));
1091 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
1092 REFIID riid,
1093 void **ppvObject)
1095 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1096 TRACE("%p\n", This);
1097 return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
1100 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
1102 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1103 TRACE("%p\n", This);
1104 return IUnknown_AddRef((IUnknown*) This);
1107 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
1109 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1110 TRACE("%p\n", This);
1111 return IUnknown_Release((IUnknown*) This);
1114 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
1115 IShellView *shv)
1117 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1118 IDataObject *pdo;
1119 HRESULT hr;
1120 HRESULT ret = S_FALSE;
1122 TRACE("%p (%p)\n", This, shv);
1124 hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&pdo);
1125 if(SUCCEEDED(hr))
1127 FORMATETC fmt;
1128 STGMEDIUM medium;
1130 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
1131 fmt.ptd = NULL;
1132 fmt.dwAspect = DVASPECT_CONTENT;
1133 fmt.lindex = -1;
1134 fmt.tymed = TYMED_HGLOBAL;
1136 hr = IDataObject_GetData(pdo, &fmt ,&medium);
1137 IDataObject_Release(pdo);
1138 if(SUCCEEDED(hr))
1140 LPIDA pida = GlobalLock(medium.u.hGlobal);
1141 LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]);
1143 /* Handle folders by browsing to them. */
1144 if(_ILIsFolder(pidl_child) || _ILIsDrive(pidl_child) || _ILIsSpecialFolder(pidl_child))
1146 IExplorerBrowser_BrowseToIDList((IExplorerBrowser*)This, pidl_child, SBSP_RELATIVE);
1147 ret = S_OK;
1149 GlobalUnlock(medium.u.hGlobal);
1150 GlobalFree(medium.u.hGlobal);
1152 else
1153 ERR("Failed to get data from IDataObject.\n");
1154 } else
1155 ERR("Failed to get IDataObject.\n");
1157 return ret;
1159 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
1160 IShellView *shv, ULONG uChange)
1162 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1163 FIXME("stub, %p (%p, %d)\n", This, shv, uChange);
1164 return E_NOTIMPL;
1166 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
1167 IShellView *pshv, LPCITEMIDLIST pidl)
1169 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1170 FIXME("stub, %p (%p, %p)\n", This, pshv, pidl);
1171 return S_OK;
1174 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
1175 IShellView *pshv,
1176 DWORD dwNotifyType)
1178 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1179 FIXME("stub, %p (%p, 0x%x)\n", This, pshv, dwNotifyType);
1180 return S_OK;
1183 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
1184 IShellView *pshv,
1185 LPWSTR pszText, int cchMax)
1187 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1188 FIXME("stub, %p (%p, %s, %d)\n", This, pshv, debugstr_w(pszText), cchMax);
1189 return S_OK;
1192 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface,
1193 DWORD *pdwFlags)
1195 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1196 FIXME("stub, %p (%p)\n", This, pdwFlags);
1197 return S_OK;
1200 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
1201 IShellView *pshv, int iColumn)
1203 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1204 FIXME("stub, %p (%p, %d)\n", This, pshv, iColumn);
1205 return S_OK;
1208 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
1209 LPWSTR pszFileSpec,
1210 int cchFileSpec)
1212 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1213 FIXME("stub, %p (%s, %d)\n", This, debugstr_w(pszFileSpec), cchFileSpec);
1214 return S_OK;
1217 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
1218 IShellView *pshv)
1220 ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1221 FIXME("stub, %p (%p)\n", This, pshv);
1222 return S_OK;
1225 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
1226 ICommDlgBrowser3_fnQueryInterface,
1227 ICommDlgBrowser3_fnAddRef,
1228 ICommDlgBrowser3_fnRelease,
1229 ICommDlgBrowser3_fnOnDefaultCommand,
1230 ICommDlgBrowser3_fnOnStateChange,
1231 ICommDlgBrowser3_fnIncludeObject,
1232 ICommDlgBrowser3_fnNotify,
1233 ICommDlgBrowser3_fnGetDefaultMenuText,
1234 ICommDlgBrowser3_fnGetViewFlags,
1235 ICommDlgBrowser3_fnOnColumnClicked,
1236 ICommDlgBrowser3_fnGetCurrentFilter,
1237 ICommDlgBrowser3_fnOnPreviewCreated
1240 /**************************************************************************
1241 * IObjectWithSite Implementation
1244 static inline ExplorerBrowserImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
1246 return (ExplorerBrowserImpl *)((char*)iface - FIELD_OFFSET(ExplorerBrowserImpl, lpowsVtbl));
1249 static HRESULT WINAPI IObjectWithSite_fnQueryInterface(IObjectWithSite *iface,
1250 REFIID riid, void **ppvObject)
1252 ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1253 TRACE("%p\n", This);
1254 return IUnknown_QueryInterface((IUnknown*)This, riid, ppvObject);
1257 static ULONG WINAPI IObjectWithSite_fnAddRef(IObjectWithSite *iface)
1259 ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1260 TRACE("%p\n", This);
1261 return IUnknown_AddRef((IUnknown*)This);
1264 static ULONG WINAPI IObjectWithSite_fnRelease(IObjectWithSite *iface)
1266 ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1267 TRACE("%p\n", This);
1268 return IUnknown_Release((IUnknown*)This);
1271 static HRESULT WINAPI IObjectWithSite_fnSetSite(IObjectWithSite *iface, IUnknown *punk_site)
1273 ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1274 TRACE("%p (%p)\n", This, punk_site);
1276 if(This->punk_site)
1278 IUnknown_Release(This->punk_site);
1279 This->punk_site = NULL;
1280 get_interfaces_from_site(This);
1283 This->punk_site = punk_site;
1285 if(This->punk_site)
1286 IUnknown_AddRef(This->punk_site);
1288 return S_OK;
1291 static HRESULT WINAPI IObjectWithSite_fnGetSite(IObjectWithSite *iface, REFIID riid, void **ppvSite)
1293 ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1294 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvSite);
1296 if(!This->punk_site)
1297 return E_FAIL;
1299 return IUnknown_QueryInterface(This->punk_site, riid, ppvSite);
1302 static const IObjectWithSiteVtbl vt_IObjectWithSite = {
1303 IObjectWithSite_fnQueryInterface,
1304 IObjectWithSite_fnAddRef,
1305 IObjectWithSite_fnRelease,
1306 IObjectWithSite_fnSetSite,
1307 IObjectWithSite_fnGetSite
1310 HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
1312 ExplorerBrowserImpl *eb;
1313 HRESULT ret;
1315 TRACE("%p %s %p\n", pUnkOuter, shdebugstr_guid (riid), ppv);
1317 if(!ppv)
1318 return E_POINTER;
1319 if(pUnkOuter)
1320 return CLASS_E_NOAGGREGATION;
1322 eb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExplorerBrowserImpl));
1323 eb->ref = 1;
1324 eb->lpVtbl = &vt_IExplorerBrowser;
1325 eb->lpsbVtbl = &vt_IShellBrowser;
1326 eb->lpcdb3Vtbl = &vt_ICommDlgBrowser3;
1327 eb->lpowsVtbl = &vt_IObjectWithSite;
1329 list_init(&eb->event_clients);
1330 list_init(&eb->travellog);
1332 ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
1333 IExplorerBrowser_Release((IExplorerBrowser*)eb);
1335 TRACE("--(%p)\n", ppv);
1336 return ret;