urlmon/tests: Added tests for IUriBuilder_HasBeenModified.
[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/debug.h"
32 #include "debughlp.h"
33
34 #include "shell32_main.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37
38 typedef struct _ExplorerBrowserImpl {
39     const IExplorerBrowserVtbl *lpVtbl;
40     const IShellBrowserVtbl *lpsbVtbl;
41     LONG ref;
42     BOOL destroyed;
43
44     HWND hwnd_main;
45     HWND hwnd_sv;
46
47     EXPLORER_BROWSER_OPTIONS eb_options;
48     FOLDERSETTINGS fs;
49
50     IShellView *psv;
51     RECT sv_rc;
52 } ExplorerBrowserImpl;
53
54 /**************************************************************************
55  * Helper functions
56  */
57 static void update_layout(ExplorerBrowserImpl *This)
58 {
59     RECT rc;
60     TRACE("%p\n", This);
61
62     GetClientRect(This->hwnd_main, &rc);
63     CopyRect(&This->sv_rc, &rc);
64 }
65
66 static void size_panes(ExplorerBrowserImpl *This)
67 {
68     MoveWindow(This->hwnd_sv,
69                This->sv_rc.left, This->sv_rc.top,
70                This->sv_rc.right - This->sv_rc.left, This->sv_rc.bottom - This->sv_rc.top,
71                TRUE);
72 }
73
74 static HRESULT change_viewmode(ExplorerBrowserImpl *This, UINT viewmode)
75 {
76     IFolderView *pfv;
77     HRESULT hr;
78
79     if(!This->psv)
80         return E_FAIL;
81
82     hr = IShellView_QueryInterface(This->psv, &IID_IFolderView, (void*)&pfv);
83     if(SUCCEEDED(hr))
84     {
85         hr = IFolderView_SetCurrentViewMode(pfv, This->fs.ViewMode);
86         IFolderView_Release(pfv);
87     }
88
89     return hr;
90 }
91
92 /**************************************************************************
93  * Main window related functions.
94  */
95 static LRESULT main_on_wm_create(HWND hWnd, CREATESTRUCTW *crs)
96 {
97     ExplorerBrowserImpl *This = crs->lpCreateParams;
98     TRACE("%p\n", This);
99
100     SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LPARAM)This);
101     This->hwnd_main = hWnd;
102
103     return TRUE;
104 }
105
106 static LRESULT main_on_wm_size(ExplorerBrowserImpl *This)
107 {
108     update_layout(This);
109     size_panes(This);
110
111     return TRUE;
112 }
113
114 static LRESULT CALLBACK main_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
115 {
116     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
117
118     switch(uMessage)
119     {
120     case WM_CREATE:           return main_on_wm_create(hWnd, (CREATESTRUCTW*)lParam);
121     case WM_SIZE:             return main_on_wm_size(This);
122     default:                  return DefWindowProcW(hWnd, uMessage, wParam, lParam);
123     }
124
125     return 0;
126 }
127
128 /**************************************************************************
129  * IExplorerBrowser Implementation
130  */
131 static HRESULT WINAPI IExplorerBrowser_fnQueryInterface(IExplorerBrowser *iface,
132                                                         REFIID riid, void **ppvObject)
133 {
134     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
135     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
136
137     *ppvObject = NULL;
138     if(IsEqualIID(riid, &IID_IExplorerBrowser) ||
139        IsEqualIID(riid, &IID_IUnknown))
140     {
141         *ppvObject = This;
142     }
143     else if(IsEqualIID(riid, &IID_IShellBrowser))
144     {
145         *ppvObject = &This->lpsbVtbl;
146     }
147
148     if(*ppvObject)
149     {
150         IUnknown_AddRef((IUnknown*)*ppvObject);
151         return S_OK;
152     }
153
154     return E_NOINTERFACE;
155 }
156
157 static ULONG WINAPI IExplorerBrowser_fnAddRef(IExplorerBrowser *iface)
158 {
159     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
160     LONG ref = InterlockedIncrement(&This->ref);
161     TRACE("%p - ref %d\n", This, ref);
162
163     return ref;
164 }
165
166 static ULONG WINAPI IExplorerBrowser_fnRelease(IExplorerBrowser *iface)
167 {
168     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
169     LONG ref = InterlockedDecrement(&This->ref);
170     TRACE("%p - ref %d\n", This, ref);
171
172     if(!ref)
173     {
174         TRACE("Freeing.\n");
175
176         if(!This->destroyed)
177             IExplorerBrowser_Destroy(iface);
178
179         HeapFree(GetProcessHeap(), 0, This);
180         return 0;
181     }
182
183     return ref;
184 }
185
186 static HRESULT WINAPI IExplorerBrowser_fnInitialize(IExplorerBrowser *iface,
187                                                     HWND hwndParent, const RECT *prc,
188                                                     const FOLDERSETTINGS *pfs)
189 {
190     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
191     WNDCLASSW wc;
192     LONG style;
193     static const WCHAR EB_CLASS_NAME[] =
194         {'E','x','p','l','o','r','e','r','B','r','o','w','s','e','r','C','o','n','t','r','o','l',0};
195
196     TRACE("%p (%p, %p, %p)\n", This, hwndParent, prc, pfs);
197
198     if(This->hwnd_main)
199         return E_UNEXPECTED;
200
201     if(!hwndParent)
202         return E_INVALIDARG;
203
204     if( !GetClassInfoW(shell32_hInstance, EB_CLASS_NAME, &wc) )
205     {
206         wc.style            = CS_HREDRAW | CS_VREDRAW;
207         wc.lpfnWndProc      = main_wndproc;
208         wc.cbClsExtra       = 0;
209         wc.cbWndExtra       = 0;
210         wc.hInstance        = shell32_hInstance;
211         wc.hIcon            = 0;
212         wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_ARROW);
213         wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
214         wc.lpszMenuName     = NULL;
215         wc.lpszClassName    = EB_CLASS_NAME;
216
217         if (!RegisterClassW(&wc)) return E_FAIL;
218     }
219
220     style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER;
221     This->hwnd_main = CreateWindowExW(WS_EX_CONTROLPARENT, EB_CLASS_NAME, NULL, style,
222                                       prc->left, prc->top,
223                                       prc->right - prc->left, prc->bottom - prc->top,
224                                       hwndParent, 0, shell32_hInstance, This);
225
226     if(!This->hwnd_main)
227     {
228         ERR("Failed to create the window.\n");
229         return E_FAIL;
230     }
231
232     This->fs.ViewMode = pfs ? pfs->ViewMode : FVM_DETAILS;
233     This->fs.fFlags = pfs ? (pfs->fFlags | FWF_NOCLIENTEDGE) : FWF_NOCLIENTEDGE;
234
235     return S_OK;
236 }
237
238 static HRESULT WINAPI IExplorerBrowser_fnDestroy(IExplorerBrowser *iface)
239 {
240     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
241     TRACE("%p\n", This);
242
243     if(This->psv)
244     {
245         IShellView_DestroyViewWindow(This->psv);
246         IShellView_Release(This->psv);
247         This->psv = NULL;
248         This->hwnd_sv = NULL;
249     }
250
251     DestroyWindow(This->hwnd_main);
252     This->destroyed = TRUE;
253
254     return S_OK;
255 }
256
257 static HRESULT WINAPI IExplorerBrowser_fnSetRect(IExplorerBrowser *iface,
258                                                  HDWP *phdwp, RECT rcBrowser)
259 {
260     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
261     TRACE("%p (%p, %s)\n", This, phdwp, wine_dbgstr_rect(&rcBrowser));
262
263     if(phdwp)
264     {
265         *phdwp = DeferWindowPos(*phdwp, This->hwnd_main, NULL, rcBrowser.left, rcBrowser.top,
266                                 rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top,
267                                 SWP_NOZORDER | SWP_NOACTIVATE);
268     }
269     else
270     {
271         MoveWindow(This->hwnd_main, rcBrowser.left, rcBrowser.top,
272                    rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top, TRUE);
273     }
274
275     return S_OK;
276 }
277
278 static HRESULT WINAPI IExplorerBrowser_fnSetPropertyBag(IExplorerBrowser *iface,
279                                                         LPCWSTR pszPropertyBag)
280 {
281     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
282     FIXME("stub, %p (%s)\n", This, debugstr_w(pszPropertyBag));
283
284     return E_NOTIMPL;
285 }
286
287 static HRESULT WINAPI IExplorerBrowser_fnSetEmptyText(IExplorerBrowser *iface,
288                                                       LPCWSTR pszEmptyText)
289 {
290     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
291     FIXME("stub, %p (%s)\n", This, debugstr_w(pszEmptyText));
292
293     return E_NOTIMPL;
294 }
295
296 static HRESULT WINAPI IExplorerBrowser_fnSetFolderSettings(IExplorerBrowser *iface,
297                                                            const FOLDERSETTINGS *pfs)
298 {
299     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
300     TRACE("%p (%p)\n", This, pfs);
301
302     if(!pfs)
303         return E_INVALIDARG;
304
305     This->fs.ViewMode = pfs->ViewMode;
306     This->fs.fFlags = pfs->fFlags | FWF_NOCLIENTEDGE;
307
308     /* Change the settings of the current view, if any. */
309     return change_viewmode(This, This->fs.ViewMode);
310 }
311
312 static HRESULT WINAPI IExplorerBrowser_fnAdvise(IExplorerBrowser *iface,
313                                                 IExplorerBrowserEvents *psbe,
314                                                 DWORD *pdwCookie)
315 {
316     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
317     FIXME("stub, %p (%p, %p)\n", This, psbe, pdwCookie);
318
319     return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI IExplorerBrowser_fnUnadvise(IExplorerBrowser *iface,
323                                                   DWORD dwCookie)
324 {
325     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
326     FIXME("stub, %p (0x%x)\n", This, dwCookie);
327
328     return E_NOTIMPL;
329 }
330
331 static HRESULT WINAPI IExplorerBrowser_fnSetOptions(IExplorerBrowser *iface,
332                                                     EXPLORER_BROWSER_OPTIONS dwFlag)
333 {
334     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
335     static const EXPLORER_BROWSER_OPTIONS unsupported_options =
336         EBO_SHOWFRAMES | EBO_ALWAYSNAVIGATE | EBO_NOWRAPPERWINDOW | EBO_HTMLSHAREPOINTVIEW;
337
338     TRACE("%p (0x%x)\n", This, dwFlag);
339
340     if(dwFlag & unsupported_options)
341         FIXME("Flags 0x%08x contains unsupported options.\n", dwFlag);
342
343     This->eb_options = dwFlag;
344
345     return S_OK;
346 }
347
348 static HRESULT WINAPI IExplorerBrowser_fnGetOptions(IExplorerBrowser *iface,
349                                                     EXPLORER_BROWSER_OPTIONS *pdwFlag)
350 {
351     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
352     TRACE("%p (%p)\n", This, pdwFlag);
353
354     *pdwFlag = This->eb_options;
355
356     return S_OK;
357 }
358
359 static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
360                                                         PCUIDLIST_RELATIVE pidl,
361                                                         UINT uFlags)
362 {
363     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
364     FIXME("stub, %p (%p, 0x%x)\n", This, pidl, uFlags);
365
366     return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI IExplorerBrowser_fnBrowseToObject(IExplorerBrowser *iface,
370                                                         IUnknown *punk, UINT uFlags)
371 {
372     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
373     FIXME("stub, %p (%p, 0x%x)\n", This, punk, uFlags);
374
375     return E_NOTIMPL;
376 }
377
378 static HRESULT WINAPI IExplorerBrowser_fnFillFromObject(IExplorerBrowser *iface,
379                                                         IUnknown *punk,
380                                                         EXPLORER_BROWSER_FILL_FLAGS dwFlags)
381 {
382     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
383     FIXME("stub, %p (%p, 0x%x)\n", This, punk, dwFlags);
384
385     return E_NOTIMPL;
386 }
387
388 static HRESULT WINAPI IExplorerBrowser_fnRemoveAll(IExplorerBrowser *iface)
389 {
390     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
391     FIXME("stub, %p\n", This);
392
393     return E_NOTIMPL;
394 }
395
396 static HRESULT WINAPI IExplorerBrowser_fnGetCurrentView(IExplorerBrowser *iface,
397                                                         REFIID riid, void **ppv)
398 {
399     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)iface;
400     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppv);
401
402     if(!This->psv)
403         return E_FAIL;
404
405     return IShellView_QueryInterface(This->psv, riid, ppv);
406 }
407
408 static const IExplorerBrowserVtbl vt_IExplorerBrowser =
409 {
410     IExplorerBrowser_fnQueryInterface,
411     IExplorerBrowser_fnAddRef,
412     IExplorerBrowser_fnRelease,
413     IExplorerBrowser_fnInitialize,
414     IExplorerBrowser_fnDestroy,
415     IExplorerBrowser_fnSetRect,
416     IExplorerBrowser_fnSetPropertyBag,
417     IExplorerBrowser_fnSetEmptyText,
418     IExplorerBrowser_fnSetFolderSettings,
419     IExplorerBrowser_fnAdvise,
420     IExplorerBrowser_fnUnadvise,
421     IExplorerBrowser_fnSetOptions,
422     IExplorerBrowser_fnGetOptions,
423     IExplorerBrowser_fnBrowseToIDList,
424     IExplorerBrowser_fnBrowseToObject,
425     IExplorerBrowser_fnFillFromObject,
426     IExplorerBrowser_fnRemoveAll,
427     IExplorerBrowser_fnGetCurrentView
428 };
429
430 /**************************************************************************
431  * IShellBrowser Implementation
432  */
433
434 static inline ExplorerBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
435 {
436     return (ExplorerBrowserImpl *)((char*)iface - FIELD_OFFSET(ExplorerBrowserImpl, lpsbVtbl));
437 }
438
439 static HRESULT WINAPI IShellBrowser_fnQueryInterface(IShellBrowser *iface,
440                                                      REFIID riid, void **ppvObject)
441 {
442     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
443     TRACE("%p\n", This);
444     return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
445 }
446
447 static ULONG WINAPI IShellBrowser_fnAddRef(IShellBrowser *iface)
448 {
449     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
450     TRACE("%p\n", This);
451     return IUnknown_AddRef((IUnknown*) This);
452 }
453
454 static ULONG WINAPI IShellBrowser_fnRelease(IShellBrowser *iface)
455 {
456     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
457     TRACE("%p\n", This);
458     return IUnknown_Release((IUnknown*) This);
459 }
460
461 static HRESULT WINAPI IShellBrowser_fnGetWindow(IShellBrowser *iface, HWND *phwnd)
462 {
463     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
464     TRACE("%p (%p)\n", This, phwnd);
465
466     if(!This->hwnd_main)
467         return E_FAIL;
468
469     *phwnd = This->hwnd_main;
470     return S_OK;
471 }
472
473 static HRESULT WINAPI IShellBrowser_fnContextSensitiveHelp(IShellBrowser *iface,
474                                                            BOOL fEnterMode)
475 {
476     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
477     FIXME("stub, %p (%d)\n", This, fEnterMode);
478
479     return E_NOTIMPL;
480 }
481
482 static HRESULT WINAPI IShellBrowser_fnInsertMenusSB(IShellBrowser *iface,
483                                                     HMENU hmenuShared,
484                                                     LPOLEMENUGROUPWIDTHS lpMenuWidths)
485 {
486     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
487     TRACE("%p (%p, %p)\n", This, hmenuShared, lpMenuWidths);
488
489     /* Not implemented. */
490     return E_NOTIMPL;
491 }
492
493 static HRESULT WINAPI IShellBrowser_fnSetMenuSB(IShellBrowser *iface,
494                                                 HMENU hmenuShared,
495                                                 HOLEMENU holemenuReserved,
496                                                 HWND hwndActiveObject)
497 {
498     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
499     TRACE("%p (%p, %p, %p)\n", This, hmenuShared, holemenuReserved, hwndActiveObject);
500
501     /* Not implemented. */
502     return E_NOTIMPL;
503 }
504
505 static HRESULT WINAPI IShellBrowser_fnRemoveMenusSB(IShellBrowser *iface,
506                                                     HMENU hmenuShared)
507 {
508     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
509     TRACE("%p (%p)\n", This, hmenuShared);
510
511     /* Not implemented. */
512     return E_NOTIMPL;
513 }
514
515 static HRESULT WINAPI IShellBrowser_fnSetStatusTextSB(IShellBrowser *iface,
516                                                       LPCOLESTR pszStatusText)
517 {
518     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
519     FIXME("stub, %p (%s)\n", This, debugstr_w(pszStatusText));
520
521     return E_NOTIMPL;
522 }
523
524 static HRESULT WINAPI IShellBrowser_fnEnableModelessSB(IShellBrowser *iface,
525                                                        BOOL fEnable)
526 {
527     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
528     FIXME("stub, %p (%d)\n", This, fEnable);
529
530     return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI IShellBrowser_fnTranslateAcceleratorSB(IShellBrowser *iface,
534                                                              MSG *pmsg, WORD wID)
535 {
536     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
537     FIXME("stub, %p (%p, 0x%x)\n", This, pmsg, wID);
538
539     return E_NOTIMPL;
540 }
541
542 static HRESULT WINAPI IShellBrowser_fnBrowseObject(IShellBrowser *iface,
543                                                    LPCITEMIDLIST pidl, UINT wFlags)
544 {
545     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
546     FIXME("stub, %p\n", This);
547
548     return E_NOTIMPL;
549 }
550
551 static HRESULT WINAPI IShellBrowser_fnGetViewStateStream(IShellBrowser *iface,
552                                                          DWORD grfMode,
553                                                          IStream **ppStrm)
554 {
555     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
556     FIXME("stub, %p (0x%x, %p)\n", This, grfMode, ppStrm);
557
558     *ppStrm = NULL;
559     return E_FAIL;
560 }
561
562 static HRESULT WINAPI IShellBrowser_fnGetControlWindow(IShellBrowser *iface,
563                                                        UINT id, HWND *phwnd)
564 {
565     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
566     TRACE("%p (%d, %p)\n", This, id, phwnd);
567
568     /* Not implemented. */
569     return E_NOTIMPL;
570 }
571
572 static HRESULT WINAPI IShellBrowser_fnSendControlMsg(IShellBrowser *iface,
573                                                      UINT id, UINT uMsg,
574                                                      WPARAM wParam, LPARAM lParam,
575                                                      LRESULT *pret)
576 {
577     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
578     FIXME("stub, %p (%d, %d, %lx, %lx, %p)\n", This, id, uMsg, wParam, lParam, pret);
579
580     return E_NOTIMPL;
581 }
582
583 static HRESULT WINAPI IShellBrowser_fnQueryActiveShellView(IShellBrowser *iface,
584                                                            IShellView **ppshv)
585 {
586     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
587     TRACE("%p (%p)\n", This, ppshv);
588
589     if(!This->psv)
590         return E_FAIL;
591
592     *ppshv = This->psv;
593     IShellView_AddRef(This->psv);
594
595     return S_OK;
596 }
597
598 static HRESULT WINAPI IShellBrowser_fnOnViewWindowActive(IShellBrowser *iface,
599                                                          IShellView *pshv)
600 {
601     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
602     FIXME("stub, %p (%p)\n", This, pshv);
603
604     return E_NOTIMPL;
605 }
606
607 static HRESULT WINAPI IShellBrowser_fnSetToolbarItems(IShellBrowser *iface,
608                                                       LPTBBUTTONSB lpButtons,
609                                                       UINT nButtons, UINT uFlags)
610 {
611     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
612     FIXME("stub, %p (%p, %d, 0x%x)\n", This, lpButtons, nButtons, uFlags);
613
614     return E_NOTIMPL;
615 }
616
617 static const IShellBrowserVtbl vt_IShellBrowser = {
618     IShellBrowser_fnQueryInterface,
619     IShellBrowser_fnAddRef,
620     IShellBrowser_fnRelease,
621     IShellBrowser_fnGetWindow,
622     IShellBrowser_fnContextSensitiveHelp,
623     IShellBrowser_fnInsertMenusSB,
624     IShellBrowser_fnSetMenuSB,
625     IShellBrowser_fnRemoveMenusSB,
626     IShellBrowser_fnSetStatusTextSB,
627     IShellBrowser_fnEnableModelessSB,
628     IShellBrowser_fnTranslateAcceleratorSB,
629     IShellBrowser_fnBrowseObject,
630     IShellBrowser_fnGetViewStateStream,
631     IShellBrowser_fnGetControlWindow,
632     IShellBrowser_fnSendControlMsg,
633     IShellBrowser_fnQueryActiveShellView,
634     IShellBrowser_fnOnViewWindowActive,
635     IShellBrowser_fnSetToolbarItems
636 };
637
638 HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
639 {
640     ExplorerBrowserImpl *eb;
641     HRESULT ret;
642
643     TRACE("%p %s %p\n", pUnkOuter, shdebugstr_guid (riid), ppv);
644
645     if(!ppv)
646         return E_POINTER;
647     if(pUnkOuter)
648         return CLASS_E_NOAGGREGATION;
649
650     eb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExplorerBrowserImpl));
651     eb->ref = 1;
652     eb->lpVtbl = &vt_IExplorerBrowser;
653     eb->lpsbVtbl = &vt_IShellBrowser;
654
655     ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
656     IExplorerBrowser_Release((IExplorerBrowser*)eb);
657
658     TRACE("--(%p)\n", ppv);
659     return ret;
660 }