dbghelp: dwarf debug info: a few more fixes to dwarf parsing.
[wine] / dlls / shell32 / ebrowser.c
1 /*
2  * ExplorerBrowser Control implementation.
3  *
4  * Copyright 2010 David Hedberg
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26
27 #include "winerror.h"
28 #include "windef.h"
29 #include "winbase.h"
30
31 #include "wine/list.h"
32 #include "wine/debug.h"
33 #include "debughlp.h"
34
35 #include "shell32_main.h"
36 #include "pidl.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(shell);
39
40 typedef struct _event_client {
41     struct list entry;
42     IExplorerBrowserEvents *pebe;
43     DWORD cookie;
44 } event_client;
45
46 typedef struct _travellog_entry {
47     struct list entry;
48     LPITEMIDLIST pidl;
49 } travellog_entry;
50
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;
58
59     HWND hwnd_main;
60     HWND hwnd_sv;
61
62     EXPLORER_BROWSER_OPTIONS eb_options;
63     FOLDERSETTINGS fs;
64
65     struct list event_clients;
66     DWORD events_next_cookie;
67     struct list travellog;
68     travellog_entry *travellog_cursor;
69     int travellog_count;
70
71     IShellView *psv;
72     RECT sv_rc;
73     LPITEMIDLIST current_pidl;
74
75     IUnknown *punk_site;
76 } ExplorerBrowserImpl;
77
78 /**************************************************************************
79  * Event functions.
80  */
81 static void events_unadvise_all(ExplorerBrowserImpl *This)
82 {
83     event_client *client, *curs;
84     TRACE("%p\n", This);
85
86     LIST_FOR_EACH_ENTRY_SAFE(client, curs, &This->event_clients, event_client, entry)
87     {
88         TRACE("Removing %p\n", client);
89         list_remove(&client->entry);
90         IExplorerBrowserEvents_Release(client->pebe);
91         HeapFree(GetProcessHeap(), 0, client);
92     }
93 }
94
95 static HRESULT events_NavigationPending(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
96 {
97     event_client *cursor;
98     HRESULT hres = S_OK;
99
100     TRACE("%p\n", This);
101
102     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
103     {
104         TRACE("Notifying %p\n", cursor);
105         hres = IExplorerBrowserEvents_OnNavigationPending(cursor->pebe, pidl);
106
107         /* If this failed for any reason, the browsing is supposed to be aborted. */
108         if(FAILED(hres))
109             break;
110     }
111
112     return hres;
113 }
114
115 static void events_NavigationComplete(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
116 {
117     event_client *cursor;
118
119     TRACE("%p\n", This);
120
121     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
122     {
123         TRACE("Notifying %p\n", cursor);
124         IExplorerBrowserEvents_OnNavigationComplete(cursor->pebe, pidl);
125     }
126 }
127
128 static void events_NavigationFailed(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
129 {
130     event_client *cursor;
131
132     TRACE("%p\n", This);
133
134     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
135     {
136         TRACE("Notifying %p\n", cursor);
137         IExplorerBrowserEvents_OnNavigationFailed(cursor->pebe, pidl);
138     }
139 }
140
141 static void events_ViewCreated(ExplorerBrowserImpl *This, IShellView *psv)
142 {
143     event_client *cursor;
144
145     TRACE("%p\n", This);
146
147     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
148     {
149         TRACE("Notifying %p\n", cursor);
150         IExplorerBrowserEvents_OnViewCreated(cursor->pebe, psv);
151     }
152 }
153
154 /**************************************************************************
155  * Travellog functions.
156  */
157 static void travellog_remove_entry(ExplorerBrowserImpl *This, travellog_entry *entry)
158 {
159     TRACE("Removing %p\n", entry);
160
161     list_remove(&entry->entry);
162     HeapFree(GetProcessHeap(), 0, entry);
163     This->travellog_count--;
164 }
165
166 static void travellog_remove_all_entries(ExplorerBrowserImpl *This)
167 {
168     travellog_entry *cursor, *cursor2;
169     TRACE("%p\n", This);
170
171     LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
172         travellog_remove_entry(This, cursor);
173
174     This->travellog_cursor = NULL;
175 }
176
177 static void travellog_add_entry(ExplorerBrowserImpl *This, LPITEMIDLIST pidl)
178 {
179     travellog_entry *new, *cursor, *cursor2;
180     TRACE("%p (old count %d)\n", pidl, This->travellog_count);
181
182     /* Replace the old tail, if any, with the new entry */
183     if(This->travellog_cursor)
184     {
185         LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, &This->travellog, travellog_entry, entry)
186         {
187             if(cursor == This->travellog_cursor)
188                 break;
189             travellog_remove_entry(This, cursor);
190         }
191     }
192
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++;
199
200     /* Remove the first few entries if the size limit is reached. */
201     if(This->travellog_count > 200)
202     {
203         UINT i = 0;
204         LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
205         {
206             if(i++ > 10)
207                 break;
208             travellog_remove_entry(This, cursor);
209         }
210     }
211 }
212
213 static LPCITEMIDLIST travellog_go_back(ExplorerBrowserImpl *This)
214 {
215     travellog_entry *prev;
216     TRACE("%p, %p\n", This, This->travellog_cursor);
217
218     if(!This->travellog_cursor)
219         return NULL;
220
221     prev = LIST_ENTRY(list_prev(&This->travellog, &This->travellog_cursor->entry),
222                       travellog_entry, entry);
223     if(!prev)
224         return NULL;
225
226     This->travellog_cursor = prev;
227     return prev->pidl;
228 }
229
230 static LPCITEMIDLIST travellog_go_forward(ExplorerBrowserImpl *This)
231 {
232     travellog_entry *next;
233     TRACE("%p, %p\n", This, This->travellog_cursor);
234
235     if(!This->travellog_cursor)
236         return NULL;
237
238     next = LIST_ENTRY(list_next(&This->travellog, &This->travellog_cursor->entry),
239                       travellog_entry, entry);
240     if(!next)
241         return NULL;
242
243     This->travellog_cursor = next;
244     return next->pidl;
245 }
246
247 /**************************************************************************
248  * Helper functions
249  */
250 static void update_layout(ExplorerBrowserImpl *This)
251 {
252     RECT rc;
253     TRACE("%p\n", This);
254
255     GetClientRect(This->hwnd_main, &rc);
256     CopyRect(&This->sv_rc, &rc);
257 }
258
259 static void size_panes(ExplorerBrowserImpl *This)
260 {
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);
265 }
266
267 static HRESULT change_viewmode(ExplorerBrowserImpl *This, UINT viewmode)
268 {
269     IFolderView *pfv;
270     HRESULT hr;
271
272     if(!This->psv)
273         return E_FAIL;
274
275     hr = IShellView_QueryInterface(This->psv, &IID_IFolderView, (void*)&pfv);
276     if(SUCCEEDED(hr))
277     {
278         hr = IFolderView_SetCurrentViewMode(pfv, This->fs.ViewMode);
279         IFolderView_Release(pfv);
280     }
281
282     return hr;
283 }
284
285 static HRESULT create_new_shellview(ExplorerBrowserImpl *This, IShellItem *psi)
286 {
287     IShellBrowser *psb = (IShellBrowser*)&This->lpsbVtbl;
288     IShellFolder *psf;
289     IShellView *psv;
290     HWND hwnd_new;
291     HRESULT hr;
292
293     TRACE("%p, %p\n", This, psi);
294
295     hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IShellFolder, (void**)&psf);
296     if(SUCCEEDED(hr))
297     {
298         hr = IShellFolder_CreateViewObject(psf, This->hwnd_main, &IID_IShellView, (void**)&psv);
299         if(SUCCEEDED(hr))
300         {
301             if(This->hwnd_sv)
302             {
303                 IShellView_DestroyViewWindow(This->psv);
304                 This->hwnd_sv = NULL;
305             }
306
307             hr = IShellView_CreateViewWindow(psv, This->psv, &This->fs, psb, &This->sv_rc, &hwnd_new);
308             if(SUCCEEDED(hr))
309             {
310                 /* Replace the old shellview */
311                 if(This->psv) IShellView_Release(This->psv);
312
313                 This->psv = psv;
314                 This->hwnd_sv = hwnd_new;
315                 events_ViewCreated(This, psv);
316             }
317             else
318             {
319                 ERR("CreateViewWindow failed (0x%x)\n", hr);
320                 IShellView_Release(psv);
321             }
322         }
323         else
324             ERR("CreateViewObject failed (0x%x)\n", hr);
325
326         IShellFolder_Release(psf);
327     }
328     else
329         ERR("SI::BindToHandler failed (0x%x)\n", hr);
330
331     return hr;
332 }
333
334 static void get_interfaces_from_site(ExplorerBrowserImpl *This)
335 {
336     IServiceProvider *psp;
337     HRESULT hr;
338
339     /* Calling this with This->punk_site set to NULL should properly
340      * release any previously fetched interfaces.
341      */
342
343     if(This->punk_site)
344     {
345         hr = IUnknown_QueryInterface(This->punk_site, &IID_IServiceProvider, (void**)&psp);
346         if(SUCCEEDED(hr))
347         {
348             FIXME("Not requesting any interfaces.\n");
349             IServiceProvider_Release(psp);
350         }
351         else
352             ERR("Failed to get IServiceProvider from site.\n");
353     }
354 }
355
356 /**************************************************************************
357  * Main window related functions.
358  */
359 static LRESULT main_on_wm_create(HWND hWnd, CREATESTRUCTW *crs)
360 {
361     ExplorerBrowserImpl *This = crs->lpCreateParams;
362     TRACE("%p\n", This);
363
364     SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LPARAM)This);
365     This->hwnd_main = hWnd;
366
367     return TRUE;
368 }
369
370 static LRESULT main_on_wm_size(ExplorerBrowserImpl *This)
371 {
372     update_layout(This);
373     size_panes(This);
374
375     return TRUE;
376 }
377
378 static LRESULT CALLBACK main_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
379 {
380     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
381
382     switch(uMessage)
383     {
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);
387     }
388
389     return 0;
390 }
391
392 /**************************************************************************
393  * IExplorerBrowser Implementation
394  */
395 static HRESULT WINAPI IExplorerBrowser_fnQueryInterface(IExplorerBrowser *iface,
396                                                         REFIID riid, void **ppvObject)
397 {
398     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
399     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
400
401     *ppvObject = NULL;
402     if(IsEqualIID(riid, &IID_IExplorerBrowser) ||
403        IsEqualIID(riid, &IID_IUnknown))
404     {
405         *ppvObject = This;
406     }
407     else if(IsEqualIID(riid, &IID_IShellBrowser))
408     {
409         *ppvObject = &This->lpsbVtbl;
410     }
411     else if(IsEqualIID(riid, &IID_ICommDlgBrowser) ||
412             IsEqualIID(riid, &IID_ICommDlgBrowser2) ||
413             IsEqualIID(riid, &IID_ICommDlgBrowser3))
414     {
415         *ppvObject = &This->lpcdb3Vtbl;
416     }
417     else if(IsEqualIID(riid, &IID_IObjectWithSite))
418     {
419         *ppvObject = &This->lpowsVtbl;
420     }
421
422     if(*ppvObject)
423     {
424         IUnknown_AddRef((IUnknown*)*ppvObject);
425         return S_OK;
426     }
427
428     return E_NOINTERFACE;
429 }
430
431 static ULONG WINAPI IExplorerBrowser_fnAddRef(IExplorerBrowser *iface)
432 {
433     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
434     LONG ref = InterlockedIncrement(&This->ref);
435     TRACE("%p - ref %d\n", This, ref);
436
437     return ref;
438 }
439
440 static ULONG WINAPI IExplorerBrowser_fnRelease(IExplorerBrowser *iface)
441 {
442     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
443     LONG ref = InterlockedDecrement(&This->ref);
444     TRACE("%p - ref %d\n", This, ref);
445
446     if(!ref)
447     {
448         TRACE("Freeing.\n");
449
450         if(!This->destroyed)
451             IExplorerBrowser_Destroy(iface);
452
453         IObjectWithSite_SetSite((IObjectWithSite*)&This->lpowsVtbl, NULL);
454
455         HeapFree(GetProcessHeap(), 0, This);
456         return 0;
457     }
458
459     return ref;
460 }
461
462 static HRESULT WINAPI IExplorerBrowser_fnInitialize(IExplorerBrowser *iface,
463                                                     HWND hwndParent, const RECT *prc,
464                                                     const FOLDERSETTINGS *pfs)
465 {
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};
471
472     TRACE("%p (%p, %p, %p)\n", This, hwndParent, prc, pfs);
473
474     if(This->hwnd_main)
475         return E_UNEXPECTED;
476
477     if(!hwndParent)
478         return E_INVALIDARG;
479
480     if( !GetClassInfoW(shell32_hInstance, EB_CLASS_NAME, &wc) )
481     {
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;
492
493         if (!RegisterClassW(&wc)) return E_FAIL;
494     }
495
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);
501
502     if(!This->hwnd_main)
503     {
504         ERR("Failed to create the window.\n");
505         return E_FAIL;
506     }
507
508     This->fs.ViewMode = pfs ? pfs->ViewMode : FVM_DETAILS;
509     This->fs.fFlags = pfs ? (pfs->fFlags | FWF_NOCLIENTEDGE) : FWF_NOCLIENTEDGE;
510
511     return S_OK;
512 }
513
514 static HRESULT WINAPI IExplorerBrowser_fnDestroy(IExplorerBrowser *iface)
515 {
516     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
517     TRACE("%p\n", This);
518
519     if(This->psv)
520     {
521         IShellView_DestroyViewWindow(This->psv);
522         IShellView_Release(This->psv);
523         This->psv = NULL;
524         This->hwnd_sv = NULL;
525     }
526
527     events_unadvise_all(This);
528     travellog_remove_all_entries(This);
529
530     ILFree(This->current_pidl);
531     This->current_pidl = NULL;
532
533     DestroyWindow(This->hwnd_main);
534     This->destroyed = TRUE;
535
536     return S_OK;
537 }
538
539 static HRESULT WINAPI IExplorerBrowser_fnSetRect(IExplorerBrowser *iface,
540                                                  HDWP *phdwp, RECT rcBrowser)
541 {
542     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
543     TRACE("%p (%p, %s)\n", This, phdwp, wine_dbgstr_rect(&rcBrowser));
544
545     if(phdwp)
546     {
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);
550     }
551     else
552     {
553         MoveWindow(This->hwnd_main, rcBrowser.left, rcBrowser.top,
554                    rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top, TRUE);
555     }
556
557     return S_OK;
558 }
559
560 static HRESULT WINAPI IExplorerBrowser_fnSetPropertyBag(IExplorerBrowser *iface,
561                                                         LPCWSTR pszPropertyBag)
562 {
563     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
564     FIXME("stub, %p (%s)\n", This, debugstr_w(pszPropertyBag));
565
566     return E_NOTIMPL;
567 }
568
569 static HRESULT WINAPI IExplorerBrowser_fnSetEmptyText(IExplorerBrowser *iface,
570                                                       LPCWSTR pszEmptyText)
571 {
572     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
573     FIXME("stub, %p (%s)\n", This, debugstr_w(pszEmptyText));
574
575     return E_NOTIMPL;
576 }
577
578 static HRESULT WINAPI IExplorerBrowser_fnSetFolderSettings(IExplorerBrowser *iface,
579                                                            const FOLDERSETTINGS *pfs)
580 {
581     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
582     TRACE("%p (%p)\n", This, pfs);
583
584     if(!pfs)
585         return E_INVALIDARG;
586
587     This->fs.ViewMode = pfs->ViewMode;
588     This->fs.fFlags = pfs->fFlags | FWF_NOCLIENTEDGE;
589
590     /* Change the settings of the current view, if any. */
591     return change_viewmode(This, This->fs.ViewMode);
592 }
593
594 static HRESULT WINAPI IExplorerBrowser_fnAdvise(IExplorerBrowser *iface,
595                                                 IExplorerBrowserEvents *psbe,
596                                                 DWORD *pdwCookie)
597 {
598     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
599     event_client *client;
600     TRACE("%p (%p, %p)\n", This, psbe, pdwCookie);
601
602     client = HeapAlloc(GetProcessHeap(), 0, sizeof(event_client));
603     client->pebe = psbe;
604     client->cookie = ++This->events_next_cookie;
605
606     IExplorerBrowserEvents_AddRef(psbe);
607     *pdwCookie = client->cookie;
608
609     list_add_tail(&This->event_clients, &client->entry);
610
611     return S_OK;
612 }
613
614 static HRESULT WINAPI IExplorerBrowser_fnUnadvise(IExplorerBrowser *iface,
615                                                   DWORD dwCookie)
616 {
617     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
618     event_client *client;
619     TRACE("%p (0x%x)\n", This, dwCookie);
620
621     LIST_FOR_EACH_ENTRY(client, &This->event_clients, event_client, entry)
622     {
623         if(client->cookie == dwCookie)
624         {
625             list_remove(&client->entry);
626             IExplorerBrowserEvents_Release(client->pebe);
627             HeapFree(GetProcessHeap(), 0, client);
628             return S_OK;
629         }
630     }
631
632     return E_INVALIDARG;
633 }
634
635 static HRESULT WINAPI IExplorerBrowser_fnSetOptions(IExplorerBrowser *iface,
636                                                     EXPLORER_BROWSER_OPTIONS dwFlag)
637 {
638     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
639     static const EXPLORER_BROWSER_OPTIONS unsupported_options =
640         EBO_SHOWFRAMES | EBO_ALWAYSNAVIGATE | EBO_NOWRAPPERWINDOW | EBO_HTMLSHAREPOINTVIEW;
641
642     TRACE("%p (0x%x)\n", This, dwFlag);
643
644     if(dwFlag & unsupported_options)
645         FIXME("Flags 0x%08x contains unsupported options.\n", dwFlag);
646
647     This->eb_options = dwFlag;
648
649     return S_OK;
650 }
651
652 static HRESULT WINAPI IExplorerBrowser_fnGetOptions(IExplorerBrowser *iface,
653                                                     EXPLORER_BROWSER_OPTIONS *pdwFlag)
654 {
655     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
656     TRACE("%p (%p)\n", This, pdwFlag);
657
658     *pdwFlag = This->eb_options;
659
660     return S_OK;
661 }
662
663 static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
664                                                         PCUIDLIST_RELATIVE pidl,
665                                                         UINT uFlags)
666 {
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);
673
674     if(!This->hwnd_main)
675         return E_FAIL;
676
677     if(This->destroyed)
678         return HRESULT_FROM_WIN32(ERROR_BUSY);
679
680     if(This->current_pidl && (This->eb_options & EBO_NAVIGATEONCE))
681         return E_FAIL;
682
683     if(uFlags & SBSP_EXPLOREMODE)
684         return E_INVALIDARG;
685
686     if(uFlags & unsupported_browse_flags)
687         FIXME("Argument 0x%x contains unsupported flags.\n", uFlags);
688
689     if(uFlags & SBSP_NAVIGATEBACK)
690     {
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;
697
698     }
699     else if(uFlags & SBSP_NAVIGATEFORWARD)
700     {
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;
707
708     }
709     else if(uFlags & SBSP_PARENT)
710     {
711         if(This->current_pidl)
712         {
713             if(_ILIsPidlSimple(This->current_pidl))
714             {
715                 absolute_pidl = _ILCreateDesktop();
716             }
717             else
718             {
719                 absolute_pidl = ILClone(This->current_pidl);
720                 ILRemoveLastID(absolute_pidl);
721             }
722         }
723         if(!absolute_pidl)
724         {
725             ERR("Failed to get parent pidl.\n");
726             return E_FAIL;
727         }
728
729     }
730     else if(uFlags & SBSP_RELATIVE)
731     {
732         /* SBSP_RELATIVE has precedence over SBSP_ABSOLUTE */
733         TRACE("SBSP_RELATIVE\n");
734         if(This->current_pidl)
735         {
736             absolute_pidl = ILCombine(This->current_pidl, pidl);
737         }
738         if(!absolute_pidl)
739         {
740             ERR("Failed to get absolute pidl.\n");
741             return E_FAIL;
742         }
743     }
744     else
745     {
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;
752     }
753
754     /* TODO: Asynchronous browsing. Return S_OK here and finish in
755      * another thread. */
756
757     hr = events_NavigationPending(This, absolute_pidl);
758     if(FAILED(hr))
759     {
760         TRACE("Browsing aborted.\n");
761         ILFree(absolute_pidl);
762         return E_FAIL;
763     }
764
765     get_interfaces_from_site(This);
766
767     /* Only browse if the new pidl differs from the old */
768     if(!ILIsEqual(This->current_pidl, absolute_pidl))
769     {
770         IShellItem *psi;
771         hr = SHCreateItemFromIDList(absolute_pidl, &IID_IShellItem, (void**)&psi);
772         if(SUCCEEDED(hr))
773         {
774             hr = create_new_shellview(This, psi);
775             if(FAILED(hr))
776             {
777                 events_NavigationFailed(This, absolute_pidl);
778                 ILFree(absolute_pidl);
779                 IShellItem_Release(psi);
780                 return E_FAIL;
781             }
782
783             /* Add to travellog */
784             if( !(This->eb_options & EBO_NOTRAVELLOG) &&
785                 !(uFlags & (SBSP_NAVIGATEFORWARD|SBSP_NAVIGATEBACK)) )
786             {
787                 travellog_add_entry(This, absolute_pidl);
788             }
789
790             IShellItem_Release(psi);
791         }
792     }
793
794     events_NavigationComplete(This, absolute_pidl);
795     ILFree(This->current_pidl);
796     This->current_pidl = absolute_pidl;
797
798     return S_OK;
799 }
800
801 static HRESULT WINAPI IExplorerBrowser_fnBrowseToObject(IExplorerBrowser *iface,
802                                                         IUnknown *punk, UINT uFlags)
803 {
804     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
805     LPITEMIDLIST pidl;
806     HRESULT hr;
807     TRACE("%p (%p, 0x%x)\n", This, punk, uFlags);
808
809     if(!punk)
810         return IExplorerBrowser_fnBrowseToIDList(iface, NULL, uFlags);
811
812     hr = SHGetIDListFromObject(punk, &pidl);
813     if(SUCCEEDED(hr))
814     {
815         hr = IExplorerBrowser_BrowseToIDList(iface, pidl, uFlags);
816         ILFree(pidl);
817     }
818
819     return hr;
820 }
821
822 static HRESULT WINAPI IExplorerBrowser_fnFillFromObject(IExplorerBrowser *iface,
823                                                         IUnknown *punk,
824                                                         EXPLORER_BROWSER_FILL_FLAGS dwFlags)
825 {
826     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
827     FIXME("stub, %p (%p, 0x%x)\n", This, punk, dwFlags);
828
829     return E_NOTIMPL;
830 }
831
832 static HRESULT WINAPI IExplorerBrowser_fnRemoveAll(IExplorerBrowser *iface)
833 {
834     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
835     FIXME("stub, %p\n", This);
836
837     return E_NOTIMPL;
838 }
839
840 static HRESULT WINAPI IExplorerBrowser_fnGetCurrentView(IExplorerBrowser *iface,
841                                                         REFIID riid, void **ppv)
842 {
843     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
844     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppv);
845
846     if(!This->psv)
847         return E_FAIL;
848
849     return IShellView_QueryInterface(This->psv, riid, ppv);
850 }
851
852 static const IExplorerBrowserVtbl vt_IExplorerBrowser =
853 {
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
872 };
873
874 /**************************************************************************
875  * IShellBrowser Implementation
876  */
877
878 static inline ExplorerBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
879 {
880     return (ExplorerBrowserImpl *)((char*)iface - FIELD_OFFSET(ExplorerBrowserImpl, lpsbVtbl));
881 }
882
883 static HRESULT WINAPI IShellBrowser_fnQueryInterface(IShellBrowser *iface,
884                                                      REFIID riid, void **ppvObject)
885 {
886     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
887     TRACE("%p\n", This);
888     return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
889 }
890
891 static ULONG WINAPI IShellBrowser_fnAddRef(IShellBrowser *iface)
892 {
893     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
894     TRACE("%p\n", This);
895     return IUnknown_AddRef((IUnknown*) This);
896 }
897
898 static ULONG WINAPI IShellBrowser_fnRelease(IShellBrowser *iface)
899 {
900     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
901     TRACE("%p\n", This);
902     return IUnknown_Release((IUnknown*) This);
903 }
904
905 static HRESULT WINAPI IShellBrowser_fnGetWindow(IShellBrowser *iface, HWND *phwnd)
906 {
907     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
908     TRACE("%p (%p)\n", This, phwnd);
909
910     if(!This->hwnd_main)
911         return E_FAIL;
912
913     *phwnd = This->hwnd_main;
914     return S_OK;
915 }
916
917 static HRESULT WINAPI IShellBrowser_fnContextSensitiveHelp(IShellBrowser *iface,
918                                                            BOOL fEnterMode)
919 {
920     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
921     FIXME("stub, %p (%d)\n", This, fEnterMode);
922
923     return E_NOTIMPL;
924 }
925
926 static HRESULT WINAPI IShellBrowser_fnInsertMenusSB(IShellBrowser *iface,
927                                                     HMENU hmenuShared,
928                                                     LPOLEMENUGROUPWIDTHS lpMenuWidths)
929 {
930     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
931     TRACE("%p (%p, %p)\n", This, hmenuShared, lpMenuWidths);
932
933     /* Not implemented. */
934     return E_NOTIMPL;
935 }
936
937 static HRESULT WINAPI IShellBrowser_fnSetMenuSB(IShellBrowser *iface,
938                                                 HMENU hmenuShared,
939                                                 HOLEMENU holemenuReserved,
940                                                 HWND hwndActiveObject)
941 {
942     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
943     TRACE("%p (%p, %p, %p)\n", This, hmenuShared, holemenuReserved, hwndActiveObject);
944
945     /* Not implemented. */
946     return E_NOTIMPL;
947 }
948
949 static HRESULT WINAPI IShellBrowser_fnRemoveMenusSB(IShellBrowser *iface,
950                                                     HMENU hmenuShared)
951 {
952     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
953     TRACE("%p (%p)\n", This, hmenuShared);
954
955     /* Not implemented. */
956     return E_NOTIMPL;
957 }
958
959 static HRESULT WINAPI IShellBrowser_fnSetStatusTextSB(IShellBrowser *iface,
960                                                       LPCOLESTR pszStatusText)
961 {
962     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
963     FIXME("stub, %p (%s)\n", This, debugstr_w(pszStatusText));
964
965     return E_NOTIMPL;
966 }
967
968 static HRESULT WINAPI IShellBrowser_fnEnableModelessSB(IShellBrowser *iface,
969                                                        BOOL fEnable)
970 {
971     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
972     FIXME("stub, %p (%d)\n", This, fEnable);
973
974     return E_NOTIMPL;
975 }
976
977 static HRESULT WINAPI IShellBrowser_fnTranslateAcceleratorSB(IShellBrowser *iface,
978                                                              MSG *pmsg, WORD wID)
979 {
980     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
981     FIXME("stub, %p (%p, 0x%x)\n", This, pmsg, wID);
982
983     return E_NOTIMPL;
984 }
985
986 static HRESULT WINAPI IShellBrowser_fnBrowseObject(IShellBrowser *iface,
987                                                    LPCITEMIDLIST pidl, UINT wFlags)
988 {
989     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
990     TRACE("%p (%p, %x)\n", This, pidl, wFlags);
991
992     return IExplorerBrowser_fnBrowseToIDList((IExplorerBrowser*)This, pidl, wFlags);
993 }
994
995 static HRESULT WINAPI IShellBrowser_fnGetViewStateStream(IShellBrowser *iface,
996                                                          DWORD grfMode,
997                                                          IStream **ppStrm)
998 {
999     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1000     FIXME("stub, %p (0x%x, %p)\n", This, grfMode, ppStrm);
1001
1002     *ppStrm = NULL;
1003     return E_FAIL;
1004 }
1005
1006 static HRESULT WINAPI IShellBrowser_fnGetControlWindow(IShellBrowser *iface,
1007                                                        UINT id, HWND *phwnd)
1008 {
1009     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1010     TRACE("%p (%d, %p)\n", This, id, phwnd);
1011
1012     /* Not implemented. */
1013     return E_NOTIMPL;
1014 }
1015
1016 static HRESULT WINAPI IShellBrowser_fnSendControlMsg(IShellBrowser *iface,
1017                                                      UINT id, UINT uMsg,
1018                                                      WPARAM wParam, LPARAM lParam,
1019                                                      LRESULT *pret)
1020 {
1021     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1022     FIXME("stub, %p (%d, %d, %lx, %lx, %p)\n", This, id, uMsg, wParam, lParam, pret);
1023
1024     return E_NOTIMPL;
1025 }
1026
1027 static HRESULT WINAPI IShellBrowser_fnQueryActiveShellView(IShellBrowser *iface,
1028                                                            IShellView **ppshv)
1029 {
1030     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1031     TRACE("%p (%p)\n", This, ppshv);
1032
1033     if(!This->psv)
1034         return E_FAIL;
1035
1036     *ppshv = This->psv;
1037     IShellView_AddRef(This->psv);
1038
1039     return S_OK;
1040 }
1041
1042 static HRESULT WINAPI IShellBrowser_fnOnViewWindowActive(IShellBrowser *iface,
1043                                                          IShellView *pshv)
1044 {
1045     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1046     FIXME("stub, %p (%p)\n", This, pshv);
1047
1048     return E_NOTIMPL;
1049 }
1050
1051 static HRESULT WINAPI IShellBrowser_fnSetToolbarItems(IShellBrowser *iface,
1052                                                       LPTBBUTTONSB lpButtons,
1053                                                       UINT nButtons, UINT uFlags)
1054 {
1055     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1056     FIXME("stub, %p (%p, %d, 0x%x)\n", This, lpButtons, nButtons, uFlags);
1057
1058     return E_NOTIMPL;
1059 }
1060
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
1080 };
1081
1082 /**************************************************************************
1083  * ICommDlgBrowser3 Implementation
1084  */
1085
1086 static inline ExplorerBrowserImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
1087 {
1088     return (ExplorerBrowserImpl *)((char*)iface - FIELD_OFFSET(ExplorerBrowserImpl, lpcdb3Vtbl));
1089 }
1090
1091 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
1092                                                         REFIID riid,
1093                                                         void **ppvObject)
1094 {
1095     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1096     TRACE("%p\n", This);
1097     return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
1098 }
1099
1100 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
1101 {
1102     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1103     TRACE("%p\n", This);
1104     return IUnknown_AddRef((IUnknown*) This);
1105 }
1106
1107 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
1108 {
1109     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1110     TRACE("%p\n", This);
1111     return IUnknown_Release((IUnknown*) This);
1112 }
1113
1114 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
1115                                                           IShellView *shv)
1116 {
1117     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1118     IDataObject *pdo;
1119     HRESULT hr;
1120     HRESULT ret = S_FALSE;
1121
1122     TRACE("%p (%p)\n", This, shv);
1123
1124     hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&pdo);
1125     if(SUCCEEDED(hr))
1126     {
1127         FORMATETC fmt;
1128         STGMEDIUM medium;
1129
1130         fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
1131         fmt.ptd = NULL;
1132         fmt.dwAspect = DVASPECT_CONTENT;
1133         fmt.lindex = -1;
1134         fmt.tymed = TYMED_HGLOBAL;
1135
1136         hr = IDataObject_GetData(pdo, &fmt ,&medium);
1137         IDataObject_Release(pdo);
1138         if(SUCCEEDED(hr))
1139         {
1140             LPIDA pida = GlobalLock(medium.u.hGlobal);
1141             LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]);
1142
1143             /* Handle folders by browsing to them. */
1144             if(_ILIsFolder(pidl_child) || _ILIsDrive(pidl_child) || _ILIsSpecialFolder(pidl_child))
1145             {
1146                 IExplorerBrowser_BrowseToIDList((IExplorerBrowser*)This, pidl_child, SBSP_RELATIVE);
1147                 ret = S_OK;
1148             }
1149             GlobalUnlock(medium.u.hGlobal);
1150             GlobalFree(medium.u.hGlobal);
1151         }
1152         else
1153             ERR("Failed to get data from IDataObject.\n");
1154     } else
1155         ERR("Failed to get IDataObject.\n");
1156
1157     return ret;
1158 }
1159 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
1160                                                        IShellView *shv, ULONG uChange)
1161 {
1162     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1163     FIXME("stub, %p (%p, %d)\n", This, shv, uChange);
1164     return E_NOTIMPL;
1165 }
1166 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
1167                                                        IShellView *pshv, LPCITEMIDLIST pidl)
1168 {
1169     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1170     FIXME("stub, %p (%p, %p)\n", This, pshv, pidl);
1171     return S_OK;
1172 }
1173
1174 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
1175                                                 IShellView *pshv,
1176                                                 DWORD dwNotifyType)
1177 {
1178     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1179     FIXME("stub, %p (%p, 0x%x)\n", This, pshv, dwNotifyType);
1180     return S_OK;
1181 }
1182
1183 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
1184                                                             IShellView *pshv,
1185                                                             LPWSTR pszText, int cchMax)
1186 {
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;
1190 }
1191
1192 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface,
1193                                                       DWORD *pdwFlags)
1194 {
1195     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1196     FIXME("stub, %p (%p)\n", This, pdwFlags);
1197     return S_OK;
1198 }
1199
1200 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
1201                                                          IShellView *pshv, int iColumn)
1202 {
1203     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1204     FIXME("stub, %p (%p, %d)\n", This, pshv, iColumn);
1205     return S_OK;
1206 }
1207
1208 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
1209                                                           LPWSTR pszFileSpec,
1210                                                           int cchFileSpec)
1211 {
1212     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1213     FIXME("stub, %p (%s, %d)\n", This, debugstr_w(pszFileSpec), cchFileSpec);
1214     return S_OK;
1215 }
1216
1217 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
1218                                                           IShellView *pshv)
1219 {
1220     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1221     FIXME("stub, %p (%p)\n", This, pshv);
1222     return S_OK;
1223 }
1224
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
1238 };
1239
1240 /**************************************************************************
1241  * IObjectWithSite Implementation
1242  */
1243
1244 static inline ExplorerBrowserImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
1245 {
1246     return (ExplorerBrowserImpl *)((char*)iface - FIELD_OFFSET(ExplorerBrowserImpl, lpowsVtbl));
1247 }
1248
1249 static HRESULT WINAPI IObjectWithSite_fnQueryInterface(IObjectWithSite *iface,
1250                                                        REFIID riid, void **ppvObject)
1251 {
1252     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1253     TRACE("%p\n", This);
1254     return IUnknown_QueryInterface((IUnknown*)This, riid, ppvObject);
1255 }
1256
1257 static ULONG WINAPI IObjectWithSite_fnAddRef(IObjectWithSite *iface)
1258 {
1259     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1260     TRACE("%p\n", This);
1261     return IUnknown_AddRef((IUnknown*)This);
1262 }
1263
1264 static ULONG WINAPI IObjectWithSite_fnRelease(IObjectWithSite *iface)
1265 {
1266     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1267     TRACE("%p\n", This);
1268     return IUnknown_Release((IUnknown*)This);
1269 }
1270
1271 static HRESULT WINAPI IObjectWithSite_fnSetSite(IObjectWithSite *iface, IUnknown *punk_site)
1272 {
1273     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1274     TRACE("%p (%p)\n", This, punk_site);
1275
1276     if(This->punk_site)
1277     {
1278         IUnknown_Release(This->punk_site);
1279         This->punk_site = NULL;
1280         get_interfaces_from_site(This);
1281     }
1282
1283     This->punk_site = punk_site;
1284
1285     if(This->punk_site)
1286         IUnknown_AddRef(This->punk_site);
1287
1288     return S_OK;
1289 }
1290
1291 static HRESULT WINAPI IObjectWithSite_fnGetSite(IObjectWithSite *iface, REFIID riid, void **ppvSite)
1292 {
1293     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1294     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvSite);
1295
1296     if(!This->punk_site)
1297         return E_FAIL;
1298
1299     return IUnknown_QueryInterface(This->punk_site, riid, ppvSite);
1300 }
1301
1302 static const IObjectWithSiteVtbl vt_IObjectWithSite = {
1303     IObjectWithSite_fnQueryInterface,
1304     IObjectWithSite_fnAddRef,
1305     IObjectWithSite_fnRelease,
1306     IObjectWithSite_fnSetSite,
1307     IObjectWithSite_fnGetSite
1308 };
1309
1310 HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
1311 {
1312     ExplorerBrowserImpl *eb;
1313     HRESULT ret;
1314
1315     TRACE("%p %s %p\n", pUnkOuter, shdebugstr_guid (riid), ppv);
1316
1317     if(!ppv)
1318         return E_POINTER;
1319     if(pUnkOuter)
1320         return CLASS_E_NOAGGREGATION;
1321
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;
1328
1329     list_init(&eb->event_clients);
1330     list_init(&eb->travellog);
1331
1332     ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
1333     IExplorerBrowser_Release((IExplorerBrowser*)eb);
1334
1335     TRACE("--(%p)\n", ppv);
1336     return ret;
1337 }