kernel32/tests: Demonstrate an input event handling peculiarity with WriteConsoleInputA.
[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 #define SPLITTER_WIDTH 2
41 #define NP_MIN_WIDTH 60
42 #define SV_MIN_WIDTH 150
43
44 typedef struct _event_client {
45     struct list entry;
46     IExplorerBrowserEvents *pebe;
47     DWORD cookie;
48 } event_client;
49
50 typedef struct _travellog_entry {
51     struct list entry;
52     LPITEMIDLIST pidl;
53 } travellog_entry;
54
55 typedef struct _ExplorerBrowserImpl {
56     IExplorerBrowser  IExplorerBrowser_iface;
57     IShellBrowser     IShellBrowser_iface;
58     ICommDlgBrowser3  ICommDlgBrowser3_iface;
59     IObjectWithSite   IObjectWithSite_iface;
60     INameSpaceTreeControlEvents INameSpaceTreeControlEvents_iface;
61     IInputObject      IInputObject_iface;
62     LONG ref;
63     BOOL destroyed;
64
65     HWND hwnd_main;
66     HWND hwnd_sv;
67
68     RECT splitter_rc;
69     struct {
70         INameSpaceTreeControl2 *pnstc2;
71         HWND hwnd_splitter, hwnd_nstc;
72         DWORD nstc_cookie;
73         UINT width;
74         BOOL show;
75         RECT rc;
76     } navpane;
77
78     EXPLORER_BROWSER_OPTIONS eb_options;
79     FOLDERSETTINGS fs;
80
81     struct list event_clients;
82     DWORD events_next_cookie;
83     struct list travellog;
84     travellog_entry *travellog_cursor;
85     int travellog_count;
86
87     IShellView *psv;
88     RECT sv_rc;
89     LPITEMIDLIST current_pidl;
90
91     IUnknown *punk_site;
92     ICommDlgBrowser *pcdb_site;
93     ICommDlgBrowser2 *pcdb2_site;
94     ICommDlgBrowser3 *pcdb3_site;
95     IExplorerPaneVisibility *pepv_site;
96 } ExplorerBrowserImpl;
97
98 static void initialize_navpane(ExplorerBrowserImpl *This, HWND hwnd_parent, RECT *rc);
99
100 /**************************************************************************
101  * Event functions.
102  */
103 static void events_unadvise_all(ExplorerBrowserImpl *This)
104 {
105     event_client *client, *curs;
106     TRACE("%p\n", This);
107
108     LIST_FOR_EACH_ENTRY_SAFE(client, curs, &This->event_clients, event_client, entry)
109     {
110         TRACE("Removing %p\n", client);
111         list_remove(&client->entry);
112         IExplorerBrowserEvents_Release(client->pebe);
113         HeapFree(GetProcessHeap(), 0, client);
114     }
115 }
116
117 static HRESULT events_NavigationPending(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
118 {
119     event_client *cursor;
120     HRESULT hres = S_OK;
121
122     TRACE("%p\n", This);
123
124     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
125     {
126         TRACE("Notifying %p\n", cursor);
127         hres = IExplorerBrowserEvents_OnNavigationPending(cursor->pebe, pidl);
128
129         /* If this failed for any reason, the browsing is supposed to be aborted. */
130         if(FAILED(hres))
131             break;
132     }
133
134     return hres;
135 }
136
137 static void events_NavigationComplete(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
138 {
139     event_client *cursor;
140
141     TRACE("%p\n", This);
142
143     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
144     {
145         TRACE("Notifying %p\n", cursor);
146         IExplorerBrowserEvents_OnNavigationComplete(cursor->pebe, pidl);
147     }
148 }
149
150 static void events_NavigationFailed(ExplorerBrowserImpl *This, PCIDLIST_ABSOLUTE pidl)
151 {
152     event_client *cursor;
153
154     TRACE("%p\n", This);
155
156     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
157     {
158         TRACE("Notifying %p\n", cursor);
159         IExplorerBrowserEvents_OnNavigationFailed(cursor->pebe, pidl);
160     }
161 }
162
163 static void events_ViewCreated(ExplorerBrowserImpl *This, IShellView *psv)
164 {
165     event_client *cursor;
166
167     TRACE("%p\n", This);
168
169     LIST_FOR_EACH_ENTRY(cursor, &This->event_clients, event_client, entry)
170     {
171         TRACE("Notifying %p\n", cursor);
172         IExplorerBrowserEvents_OnViewCreated(cursor->pebe, psv);
173     }
174 }
175
176 /**************************************************************************
177  * Travellog functions.
178  */
179 static void travellog_remove_entry(ExplorerBrowserImpl *This, travellog_entry *entry)
180 {
181     TRACE("Removing %p\n", entry);
182
183     list_remove(&entry->entry);
184     HeapFree(GetProcessHeap(), 0, entry);
185     This->travellog_count--;
186 }
187
188 static void travellog_remove_all_entries(ExplorerBrowserImpl *This)
189 {
190     travellog_entry *cursor, *cursor2;
191     TRACE("%p\n", This);
192
193     LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
194         travellog_remove_entry(This, cursor);
195
196     This->travellog_cursor = NULL;
197 }
198
199 static void travellog_add_entry(ExplorerBrowserImpl *This, LPITEMIDLIST pidl)
200 {
201     travellog_entry *new, *cursor, *cursor2;
202     TRACE("%p (old count %d)\n", pidl, This->travellog_count);
203
204     /* Replace the old tail, if any, with the new entry */
205     if(This->travellog_cursor)
206     {
207         LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, &This->travellog, travellog_entry, entry)
208         {
209             if(cursor == This->travellog_cursor)
210                 break;
211             travellog_remove_entry(This, cursor);
212         }
213     }
214
215     /* Create and add the new entry */
216     new = HeapAlloc(GetProcessHeap(), 0, sizeof(travellog_entry));
217     new->pidl = ILClone(pidl);
218     list_add_tail(&This->travellog, &new->entry);
219     This->travellog_cursor = new;
220     This->travellog_count++;
221
222     /* Remove the first few entries if the size limit is reached. */
223     if(This->travellog_count > 200)
224     {
225         UINT i = 0;
226         LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->travellog, travellog_entry, entry)
227         {
228             if(i++ > 10)
229                 break;
230             travellog_remove_entry(This, cursor);
231         }
232     }
233 }
234
235 static LPCITEMIDLIST travellog_go_back(ExplorerBrowserImpl *This)
236 {
237     travellog_entry *prev;
238     TRACE("%p, %p\n", This, This->travellog_cursor);
239
240     if(!This->travellog_cursor)
241         return NULL;
242
243     prev = LIST_ENTRY(list_prev(&This->travellog, &This->travellog_cursor->entry),
244                       travellog_entry, entry);
245     if(!prev)
246         return NULL;
247
248     This->travellog_cursor = prev;
249     return prev->pidl;
250 }
251
252 static LPCITEMIDLIST travellog_go_forward(ExplorerBrowserImpl *This)
253 {
254     travellog_entry *next;
255     TRACE("%p, %p\n", This, This->travellog_cursor);
256
257     if(!This->travellog_cursor)
258         return NULL;
259
260     next = LIST_ENTRY(list_next(&This->travellog, &This->travellog_cursor->entry),
261                       travellog_entry, entry);
262     if(!next)
263         return NULL;
264
265     This->travellog_cursor = next;
266     return next->pidl;
267 }
268
269 /**************************************************************************
270  * Helper functions
271  */
272 static void update_layout(ExplorerBrowserImpl *This)
273 {
274     RECT rc;
275     INT navpane_width_actual;
276     INT shellview_width_actual;
277     TRACE("%p (navpane: %d, EBO_SHOWFRAMES: %d)\n",
278           This, This->navpane.show, This->eb_options & EBO_SHOWFRAMES);
279
280     GetClientRect(This->hwnd_main, &rc);
281
282     if((This->eb_options & EBO_SHOWFRAMES) && This->navpane.show)
283         navpane_width_actual = This->navpane.width;
284     else
285         navpane_width_actual = 0;
286
287     shellview_width_actual = rc.right - navpane_width_actual;
288     if(shellview_width_actual < SV_MIN_WIDTH && navpane_width_actual)
289     {
290         INT missing_width = SV_MIN_WIDTH - shellview_width_actual;
291         if(missing_width < (navpane_width_actual - NP_MIN_WIDTH))
292         {
293             /* Shrink the navpane */
294             navpane_width_actual -= missing_width;
295             shellview_width_actual += missing_width;
296         }
297         else
298         {
299             /* Hide the navpane */
300             shellview_width_actual += navpane_width_actual;
301             navpane_width_actual = 0;
302         }
303     }
304
305     /**************************************************************
306      *  Calculate rectangles for the panes. All rectangles contain
307      *  the position of the panes relative to hwnd_main.
308      */
309
310     if(navpane_width_actual)
311     {
312         This->navpane.rc.left = This->navpane.rc.top = 0;
313         This->navpane.rc.right = navpane_width_actual;
314         This->navpane.rc.bottom = rc.bottom;
315
316         if(!This->navpane.hwnd_splitter)
317             initialize_navpane(This, This->hwnd_main, &This->navpane.rc);
318     }
319     else
320         ZeroMemory(&This->navpane.rc, sizeof(RECT));
321
322     This->sv_rc.left   = navpane_width_actual;
323     This->sv_rc.top    = 0;
324     This->sv_rc.right  = This->sv_rc.left + shellview_width_actual;
325     This->sv_rc.bottom = rc.bottom;
326 }
327
328 static void size_panes(ExplorerBrowserImpl *This)
329 {
330     MoveWindow(This->navpane.hwnd_splitter,
331                This->navpane.rc.right - SPLITTER_WIDTH, This->navpane.rc.top,
332                SPLITTER_WIDTH, This->navpane.rc.bottom - This->navpane.rc.top,
333                TRUE);
334
335     MoveWindow(This->hwnd_sv,
336                This->sv_rc.left, This->sv_rc.top,
337                This->sv_rc.right - This->sv_rc.left, This->sv_rc.bottom - This->sv_rc.top,
338                TRUE);
339 }
340
341 static HRESULT change_viewmode(ExplorerBrowserImpl *This, UINT viewmode)
342 {
343     IFolderView *pfv;
344     HRESULT hr;
345
346     if(!This->psv)
347         return E_FAIL;
348
349     hr = IShellView_QueryInterface(This->psv, &IID_IFolderView, (void*)&pfv);
350     if(SUCCEEDED(hr))
351     {
352         hr = IFolderView_SetCurrentViewMode(pfv, This->fs.ViewMode);
353         IFolderView_Release(pfv);
354     }
355
356     return hr;
357 }
358
359 static HRESULT create_new_shellview(ExplorerBrowserImpl *This, IShellItem *psi)
360 {
361     IShellBrowser *psb = &This->IShellBrowser_iface;
362     IShellFolder *psf;
363     IShellView *psv;
364     HWND hwnd_new;
365     HRESULT hr;
366
367     TRACE("%p, %p\n", This, psi);
368
369     hr = IShellItem_BindToHandler(psi, NULL, &BHID_SFObject, &IID_IShellFolder, (void**)&psf);
370     if(SUCCEEDED(hr))
371     {
372         hr = IShellFolder_CreateViewObject(psf, This->hwnd_main, &IID_IShellView, (void**)&psv);
373         if(SUCCEEDED(hr))
374         {
375             if(This->hwnd_sv)
376             {
377                 IShellView_DestroyViewWindow(This->psv);
378                 This->hwnd_sv = NULL;
379             }
380
381             hr = IShellView_CreateViewWindow(psv, This->psv, &This->fs, psb, &This->sv_rc, &hwnd_new);
382             if(SUCCEEDED(hr))
383             {
384                 /* Replace the old shellview */
385                 if(This->psv) IShellView_Release(This->psv);
386
387                 This->psv = psv;
388                 This->hwnd_sv = hwnd_new;
389                 events_ViewCreated(This, psv);
390             }
391             else
392             {
393                 ERR("CreateViewWindow failed (0x%x)\n", hr);
394                 IShellView_Release(psv);
395             }
396         }
397         else
398             ERR("CreateViewObject failed (0x%x)\n", hr);
399
400         IShellFolder_Release(psf);
401     }
402     else
403         ERR("SI::BindToHandler failed (0x%x)\n", hr);
404
405     return hr;
406 }
407
408 static void get_interfaces_from_site(ExplorerBrowserImpl *This)
409 {
410     IServiceProvider *psp;
411     HRESULT hr;
412
413     /* Calling this with This->punk_site set to NULL should properly
414      * release any previously fetched interfaces.
415      */
416
417     if(This->pcdb_site)
418     {
419         IUnknown_Release(This->pcdb_site);
420         if(This->pcdb2_site) IUnknown_Release(This->pcdb2_site);
421         if(This->pcdb3_site) IUnknown_Release(This->pcdb3_site);
422
423         This->pcdb_site = NULL;
424         This->pcdb2_site = NULL;
425         This->pcdb3_site = NULL;
426     }
427
428     if(This->pepv_site)
429     {
430         IExplorerPaneVisibility_Release(This->pepv_site);
431         This->pepv_site = NULL;
432     }
433
434     if(!This->punk_site)
435         return;
436
437     hr = IUnknown_QueryInterface(This->punk_site, &IID_IServiceProvider, (void**)&psp);
438     if(FAILED(hr))
439     {
440         ERR("Failed to get IServiceProvider from site.\n");
441         return;
442     }
443
444     /* ICommDlgBrowser */
445     IServiceProvider_QueryService(psp, &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser,
446                                   (void**)&This->pcdb_site);
447     IServiceProvider_QueryService(psp, &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser2,
448                                   (void**)&This->pcdb2_site);
449     IServiceProvider_QueryService(psp, &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser3,
450                                   (void**)&This->pcdb3_site);
451
452     /* IExplorerPaneVisibility */
453     IServiceProvider_QueryService(psp, &SID_ExplorerPaneVisibility, &IID_IExplorerPaneVisibility,
454                                   (void**)&This->pepv_site);
455
456     IServiceProvider_Release(psp);
457 }
458
459 /**************************************************************************
460  * General pane functionality.
461  */
462 static void update_panestate(ExplorerBrowserImpl *This)
463 {
464     EXPLORERPANESTATE eps = EPS_DONTCARE;
465     BOOL show_navpane;
466     TRACE("%p\n", This);
467
468     if(!This->pepv_site) return;
469
470     IExplorerPaneVisibility_GetPaneState(This->pepv_site, (REFEXPLORERPANE) &EP_NavPane, &eps);
471     if( !(eps & EPS_DEFAULT_OFF) )
472         show_navpane = TRUE;
473     else
474         show_navpane = FALSE;
475
476     if(This->navpane.show != show_navpane)
477     {
478         update_layout(This);
479         size_panes(This);
480     }
481
482     This->navpane.show = show_navpane;
483 }
484
485 static void splitter_draw(HWND hwnd, RECT *rc)
486 {
487     HDC hdc = GetDC(hwnd);
488     InvertRect(hdc, rc);
489     ReleaseDC(hwnd, hdc);
490 }
491
492 /**************************************************************************
493  * The Navigation Pane.
494  */
495 static LRESULT navpane_splitter_beginresize(ExplorerBrowserImpl *This, HWND hwnd, LPARAM lParam)
496 {
497     TRACE("\n");
498
499     SetCapture(hwnd);
500
501     CopyRect(&This->splitter_rc, &This->navpane.rc);
502     This->splitter_rc.left = This->splitter_rc.right - SPLITTER_WIDTH;
503
504     splitter_draw(GetParent(hwnd), &This->splitter_rc);
505
506     return TRUE;
507 }
508
509 static LRESULT navpane_splitter_resizing(ExplorerBrowserImpl *This, HWND hwnd, LPARAM lParam)
510 {
511     int new_width, dx;
512     RECT rc;
513
514     if(GetCapture() != hwnd) return FALSE;
515
516     dx = (SHORT)LOWORD(lParam);
517     TRACE("%d.\n", dx);
518
519     CopyRect(&rc, &This->navpane.rc);
520
521     new_width = This->navpane.width + dx;
522     if(new_width > NP_MIN_WIDTH && This->sv_rc.right - new_width > SV_MIN_WIDTH)
523     {
524         rc.right = new_width;
525         rc.left = rc.right - SPLITTER_WIDTH;
526         splitter_draw(GetParent(hwnd), &This->splitter_rc);
527         splitter_draw(GetParent(hwnd), &rc);
528         CopyRect(&This->splitter_rc, &rc);
529     }
530
531     return TRUE;
532 }
533
534 static LRESULT navpane_splitter_endresize(ExplorerBrowserImpl *This, HWND hwnd, LPARAM lParam)
535 {
536     int new_width, dx;
537
538     if(GetCapture() != hwnd) return FALSE;
539
540     dx = (SHORT)LOWORD(lParam);
541     TRACE("%d.\n", dx);
542
543     splitter_draw(GetParent(hwnd), &This->splitter_rc);
544
545     new_width = This->navpane.width + dx;
546     if(new_width < NP_MIN_WIDTH)
547         new_width = NP_MIN_WIDTH;
548     else if(This->sv_rc.right - new_width < SV_MIN_WIDTH)
549         new_width = This->sv_rc.right - SV_MIN_WIDTH;
550
551     This->navpane.width = new_width;
552
553     update_layout(This);
554     size_panes(This);
555
556     ReleaseCapture();
557
558     return TRUE;
559 }
560
561 static LRESULT navpane_on_wm_create(HWND hwnd, CREATESTRUCTW *crs)
562 {
563     ExplorerBrowserImpl *This = crs->lpCreateParams;
564     INameSpaceTreeControl2 *pnstc2;
565     DWORD style;
566     HRESULT hr;
567
568     TRACE("%p\n", This);
569     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
570     This->navpane.hwnd_splitter = hwnd;
571
572     hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
573                           &IID_INameSpaceTreeControl2, (void**)&pnstc2);
574
575     if(SUCCEEDED(hr))
576     {
577         style = NSTCS_HASEXPANDOS | NSTCS_ROOTHASEXPANDO | NSTCS_SHOWSELECTIONALWAYS;
578         hr = INameSpaceTreeControl2_Initialize(pnstc2, GetParent(hwnd), NULL, style);
579         if(SUCCEEDED(hr))
580         {
581             INameSpaceTreeControlEvents *pnstce;
582             IShellFolder *psfdesktop;
583             IShellItem *psi;
584             IOleWindow *pow;
585             LPITEMIDLIST pidl;
586             DWORD cookie, style2 = NSTCS2_DISPLAYPADDING;
587
588             hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFF, style2);
589             if(FAILED(hr))
590                 ERR("SetControlStyle2 failed (0x%08x)\n", hr);
591
592             hr = INameSpaceTreeControl2_QueryInterface(pnstc2, &IID_IOleWindow, (void**)&pow);
593             if(SUCCEEDED(hr))
594             {
595                 IOleWindow_GetWindow(pow, &This->navpane.hwnd_nstc);
596                 IOleWindow_Release(pow);
597             }
598             else
599                 ERR("QueryInterface(IOleWindow) failed (0x%08x)\n", hr);
600
601             pnstce = &This->INameSpaceTreeControlEvents_iface;
602             hr = INameSpaceTreeControl2_TreeAdvise(pnstc2, (IUnknown*)pnstce, &cookie);
603             if(FAILED(hr))
604                 ERR("TreeAdvise failed. (0x%08x).\n", hr);
605
606             /*
607              * Add the default roots
608              */
609
610             /* TODO: This should be FOLDERID_Links */
611             hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
612             if(SUCCEEDED(hr))
613             {
614                 hr = SHCreateShellItem(NULL, NULL, pidl, &psi);
615                 if(SUCCEEDED(hr))
616                 {
617                     hr = INameSpaceTreeControl2_AppendRoot(pnstc2, psi, SHCONTF_NONFOLDERS, NSTCRS_VISIBLE, NULL);
618                     IShellItem_Release(psi);
619                 }
620                 ILFree(pidl);
621             }
622
623             SHGetDesktopFolder(&psfdesktop);
624             hr = SHGetItemFromObject((IUnknown*)psfdesktop, &IID_IShellItem, (void**)&psi);
625             IShellFolder_Release(psfdesktop);
626             if(SUCCEEDED(hr))
627             {
628                 hr = INameSpaceTreeControl2_AppendRoot(pnstc2, psi, SHCONTF_FOLDERS, NSTCRS_EXPANDED, NULL);
629                 IShellItem_Release(psi);
630             }
631
632             /* TODO:
633              * We should advertise IID_INameSpaceTreeControl to the site of the
634              * host through its IProfferService interface, if any.
635              */
636
637             This->navpane.pnstc2 = pnstc2;
638             This->navpane.nstc_cookie = cookie;
639
640             return TRUE;
641         }
642     }
643
644     This->navpane.pnstc2 = NULL;
645     ERR("Failed (0x%08x)\n", hr);
646
647     return FALSE;
648 }
649
650 static LRESULT navpane_on_wm_size_move(ExplorerBrowserImpl *This)
651 {
652     UINT height, width;
653     TRACE("%p\n", This);
654
655     width = This->navpane.rc.right - This->navpane.rc.left - SPLITTER_WIDTH;
656     height = This->navpane.rc.bottom - This->navpane.rc.top;
657
658     MoveWindow(This->navpane.hwnd_nstc,
659                This->navpane.rc.left, This->navpane.rc.top,
660                width, height,
661                TRUE);
662
663     return FALSE;
664 }
665
666 static LRESULT navpane_on_wm_destroy(ExplorerBrowserImpl *This)
667 {
668     INameSpaceTreeControl_TreeUnadvise(This->navpane.pnstc2, This->navpane.nstc_cookie);
669     INameSpaceTreeControl_Release(This->navpane.pnstc2);
670     This->navpane.pnstc2 = NULL;
671     return TRUE;
672 }
673
674 static LRESULT CALLBACK navpane_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
675 {
676     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
677
678     switch(uMessage) {
679     case WM_CREATE:           return navpane_on_wm_create(hWnd, (CREATESTRUCTW*)lParam);
680     case WM_MOVE:             /* Fall through */
681     case WM_SIZE:             return navpane_on_wm_size_move(This);
682     case WM_DESTROY:          return navpane_on_wm_destroy(This);
683     case WM_LBUTTONDOWN:      return navpane_splitter_beginresize(This, hWnd, lParam);
684     case WM_MOUSEMOVE:        return navpane_splitter_resizing(This, hWnd, lParam);
685     case WM_LBUTTONUP:        return navpane_splitter_endresize(This, hWnd, lParam);
686     default:
687         return DefWindowProcW(hWnd, uMessage, wParam, lParam);
688     }
689     return 0;
690 }
691
692 static void initialize_navpane(ExplorerBrowserImpl *This, HWND hwnd_parent, RECT *rc)
693 {
694     WNDCLASSW wc;
695     HWND splitter;
696     static const WCHAR navpane_classname[] = {'e','b','_','n','a','v','p','a','n','e',0};
697
698     if( !GetClassInfoW(shell32_hInstance, navpane_classname, &wc) )
699     {
700         wc.style            = CS_HREDRAW | CS_VREDRAW;
701         wc.lpfnWndProc      = navpane_wndproc;
702         wc.cbClsExtra       = 0;
703         wc.cbWndExtra       = 0;
704         wc.hInstance        = shell32_hInstance;
705         wc.hIcon            = 0;
706         wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_SIZEWE);
707         wc.hbrBackground    = (HBRUSH)(COLOR_HIGHLIGHT + 1);
708         wc.lpszMenuName     = NULL;
709         wc.lpszClassName    = navpane_classname;
710
711         if (!RegisterClassW(&wc)) return;
712     }
713
714     splitter = CreateWindowExW(0, navpane_classname, NULL,
715                                WS_CHILD | WS_TABSTOP | WS_VISIBLE,
716                                rc->right - SPLITTER_WIDTH, rc->top,
717                                SPLITTER_WIDTH, rc->bottom - rc->top,
718                                hwnd_parent, 0, shell32_hInstance, This);
719     if(!splitter)
720         ERR("Failed to create navpane : %d.\n", GetLastError());
721 }
722
723 /**************************************************************************
724  * Main window related functions.
725  */
726 static LRESULT main_on_wm_create(HWND hWnd, CREATESTRUCTW *crs)
727 {
728     ExplorerBrowserImpl *This = crs->lpCreateParams;
729     TRACE("%p\n", This);
730
731     SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LPARAM)This);
732     This->hwnd_main = hWnd;
733
734     return TRUE;
735 }
736
737 static LRESULT main_on_wm_size(ExplorerBrowserImpl *This)
738 {
739     update_layout(This);
740     size_panes(This);
741
742     return TRUE;
743 }
744
745 static LRESULT CALLBACK main_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
746 {
747     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
748
749     switch(uMessage)
750     {
751     case WM_CREATE:           return main_on_wm_create(hWnd, (CREATESTRUCTW*)lParam);
752     case WM_SIZE:             return main_on_wm_size(This);
753     default:                  return DefWindowProcW(hWnd, uMessage, wParam, lParam);
754     }
755
756     return 0;
757 }
758
759 /**************************************************************************
760  * IExplorerBrowser Implementation
761  */
762
763 static inline ExplorerBrowserImpl *impl_from_IExplorerBrowser(IExplorerBrowser *iface)
764 {
765     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IExplorerBrowser_iface);
766 }
767
768 static HRESULT WINAPI IExplorerBrowser_fnQueryInterface(IExplorerBrowser *iface,
769                                                         REFIID riid, void **ppvObject)
770 {
771     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
772     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
773
774     *ppvObject = NULL;
775     if(IsEqualIID(riid, &IID_IExplorerBrowser) ||
776        IsEqualIID(riid, &IID_IUnknown))
777     {
778         *ppvObject = This;
779     }
780     else if(IsEqualIID(riid, &IID_IShellBrowser))
781     {
782         *ppvObject = &This->IShellBrowser_iface;
783     }
784     else if(IsEqualIID(riid, &IID_ICommDlgBrowser) ||
785             IsEqualIID(riid, &IID_ICommDlgBrowser2) ||
786             IsEqualIID(riid, &IID_ICommDlgBrowser3))
787     {
788         *ppvObject = &This->ICommDlgBrowser3_iface;
789     }
790     else if(IsEqualIID(riid, &IID_IObjectWithSite))
791     {
792         *ppvObject = &This->IObjectWithSite_iface;
793     }
794     else if(IsEqualIID(riid, &IID_IInputObject))
795     {
796         *ppvObject = &This->IInputObject_iface;
797     }
798
799     if(*ppvObject)
800     {
801         IUnknown_AddRef((IUnknown*)*ppvObject);
802         return S_OK;
803     }
804
805     return E_NOINTERFACE;
806 }
807
808 static ULONG WINAPI IExplorerBrowser_fnAddRef(IExplorerBrowser *iface)
809 {
810     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
811     LONG ref = InterlockedIncrement(&This->ref);
812     TRACE("%p - ref %d\n", This, ref);
813
814     return ref;
815 }
816
817 static ULONG WINAPI IExplorerBrowser_fnRelease(IExplorerBrowser *iface)
818 {
819     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
820     LONG ref = InterlockedDecrement(&This->ref);
821     TRACE("%p - ref %d\n", This, ref);
822
823     if(!ref)
824     {
825         TRACE("Freeing.\n");
826
827         if(!This->destroyed)
828             IExplorerBrowser_Destroy(iface);
829
830         IObjectWithSite_SetSite(&This->IObjectWithSite_iface, NULL);
831
832         HeapFree(GetProcessHeap(), 0, This);
833         return 0;
834     }
835
836     return ref;
837 }
838
839 static HRESULT WINAPI IExplorerBrowser_fnInitialize(IExplorerBrowser *iface,
840                                                     HWND hwndParent, const RECT *prc,
841                                                     const FOLDERSETTINGS *pfs)
842 {
843     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
844     WNDCLASSW wc;
845     LONG style;
846     static const WCHAR EB_CLASS_NAME[] =
847         {'E','x','p','l','o','r','e','r','B','r','o','w','s','e','r','C','o','n','t','r','o','l',0};
848
849     TRACE("%p (%p, %p, %p)\n", This, hwndParent, prc, pfs);
850
851     if(This->hwnd_main)
852         return E_UNEXPECTED;
853
854     if(!hwndParent)
855         return E_INVALIDARG;
856
857     if( !GetClassInfoW(shell32_hInstance, EB_CLASS_NAME, &wc) )
858     {
859         wc.style            = CS_HREDRAW | CS_VREDRAW;
860         wc.lpfnWndProc      = main_wndproc;
861         wc.cbClsExtra       = 0;
862         wc.cbWndExtra       = 0;
863         wc.hInstance        = shell32_hInstance;
864         wc.hIcon            = 0;
865         wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_ARROW);
866         wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
867         wc.lpszMenuName     = NULL;
868         wc.lpszClassName    = EB_CLASS_NAME;
869
870         if (!RegisterClassW(&wc)) return E_FAIL;
871     }
872
873     style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER;
874     This->hwnd_main = CreateWindowExW(WS_EX_CONTROLPARENT, EB_CLASS_NAME, NULL, style,
875                                       prc->left, prc->top,
876                                       prc->right - prc->left, prc->bottom - prc->top,
877                                       hwndParent, 0, shell32_hInstance, This);
878
879     if(!This->hwnd_main)
880     {
881         ERR("Failed to create the window.\n");
882         return E_FAIL;
883     }
884
885     This->fs.ViewMode = pfs ? pfs->ViewMode : FVM_DETAILS;
886     This->fs.fFlags = pfs ? (pfs->fFlags | FWF_NOCLIENTEDGE) : FWF_NOCLIENTEDGE;
887
888     return S_OK;
889 }
890
891 static HRESULT WINAPI IExplorerBrowser_fnDestroy(IExplorerBrowser *iface)
892 {
893     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
894     TRACE("%p\n", This);
895
896     if(This->psv)
897     {
898         IShellView_DestroyViewWindow(This->psv);
899         IShellView_Release(This->psv);
900         This->psv = NULL;
901         This->hwnd_sv = NULL;
902     }
903
904     events_unadvise_all(This);
905     travellog_remove_all_entries(This);
906
907     ILFree(This->current_pidl);
908     This->current_pidl = NULL;
909
910     DestroyWindow(This->hwnd_main);
911     This->destroyed = TRUE;
912
913     return S_OK;
914 }
915
916 static HRESULT WINAPI IExplorerBrowser_fnSetRect(IExplorerBrowser *iface,
917                                                  HDWP *phdwp, RECT rcBrowser)
918 {
919     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
920     TRACE("%p (%p, %s)\n", This, phdwp, wine_dbgstr_rect(&rcBrowser));
921
922     if(phdwp && *phdwp)
923     {
924         *phdwp = DeferWindowPos(*phdwp, This->hwnd_main, NULL, rcBrowser.left, rcBrowser.top,
925                                 rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top,
926                                 SWP_NOZORDER | SWP_NOACTIVATE);
927         if(!*phdwp)
928             return E_FAIL;
929     }
930     else
931     {
932         MoveWindow(This->hwnd_main, rcBrowser.left, rcBrowser.top,
933                    rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top, TRUE);
934     }
935
936     return S_OK;
937 }
938
939 static HRESULT WINAPI IExplorerBrowser_fnSetPropertyBag(IExplorerBrowser *iface,
940                                                         LPCWSTR pszPropertyBag)
941 {
942     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
943     FIXME("stub, %p (%s)\n", This, debugstr_w(pszPropertyBag));
944
945     if(!pszPropertyBag)
946         return E_INVALIDARG;
947
948     /* FIXME: This method is currently useless as we don't save any
949      * settings anywhere, but at least one application breaks if we
950      * return E_NOTIMPL.
951      */
952
953     return S_OK;
954 }
955
956 static HRESULT WINAPI IExplorerBrowser_fnSetEmptyText(IExplorerBrowser *iface,
957                                                       LPCWSTR pszEmptyText)
958 {
959     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
960     FIXME("stub, %p (%s)\n", This, debugstr_w(pszEmptyText));
961
962     return E_NOTIMPL;
963 }
964
965 static HRESULT WINAPI IExplorerBrowser_fnSetFolderSettings(IExplorerBrowser *iface,
966                                                            const FOLDERSETTINGS *pfs)
967 {
968     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
969     TRACE("%p (%p)\n", This, pfs);
970
971     if(!pfs)
972         return E_INVALIDARG;
973
974     This->fs.ViewMode = pfs->ViewMode;
975     This->fs.fFlags = pfs->fFlags | FWF_NOCLIENTEDGE;
976
977     /* Change the settings of the current view, if any. */
978     return change_viewmode(This, This->fs.ViewMode);
979 }
980
981 static HRESULT WINAPI IExplorerBrowser_fnAdvise(IExplorerBrowser *iface,
982                                                 IExplorerBrowserEvents *psbe,
983                                                 DWORD *pdwCookie)
984 {
985     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
986     event_client *client;
987     TRACE("%p (%p, %p)\n", This, psbe, pdwCookie);
988
989     client = HeapAlloc(GetProcessHeap(), 0, sizeof(event_client));
990     client->pebe = psbe;
991     client->cookie = ++This->events_next_cookie;
992
993     IExplorerBrowserEvents_AddRef(psbe);
994     *pdwCookie = client->cookie;
995
996     list_add_tail(&This->event_clients, &client->entry);
997
998     return S_OK;
999 }
1000
1001 static HRESULT WINAPI IExplorerBrowser_fnUnadvise(IExplorerBrowser *iface,
1002                                                   DWORD dwCookie)
1003 {
1004     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1005     event_client *client;
1006     TRACE("%p (0x%x)\n", This, dwCookie);
1007
1008     LIST_FOR_EACH_ENTRY(client, &This->event_clients, event_client, entry)
1009     {
1010         if(client->cookie == dwCookie)
1011         {
1012             list_remove(&client->entry);
1013             IExplorerBrowserEvents_Release(client->pebe);
1014             HeapFree(GetProcessHeap(), 0, client);
1015             return S_OK;
1016         }
1017     }
1018
1019     return E_INVALIDARG;
1020 }
1021
1022 static HRESULT WINAPI IExplorerBrowser_fnSetOptions(IExplorerBrowser *iface,
1023                                                     EXPLORER_BROWSER_OPTIONS dwFlag)
1024 {
1025     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1026     static const EXPLORER_BROWSER_OPTIONS unsupported_options =
1027         EBO_ALWAYSNAVIGATE | EBO_NOWRAPPERWINDOW | EBO_HTMLSHAREPOINTVIEW;
1028
1029     TRACE("%p (0x%x)\n", This, dwFlag);
1030
1031     if(dwFlag & unsupported_options)
1032         FIXME("Flags 0x%08x contains unsupported options.\n", dwFlag);
1033
1034     This->eb_options = dwFlag;
1035
1036     return S_OK;
1037 }
1038
1039 static HRESULT WINAPI IExplorerBrowser_fnGetOptions(IExplorerBrowser *iface,
1040                                                     EXPLORER_BROWSER_OPTIONS *pdwFlag)
1041 {
1042     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1043     TRACE("%p (%p)\n", This, pdwFlag);
1044
1045     *pdwFlag = This->eb_options;
1046
1047     return S_OK;
1048 }
1049
1050 static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
1051                                                         PCUIDLIST_RELATIVE pidl,
1052                                                         UINT uFlags)
1053 {
1054     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1055     LPITEMIDLIST absolute_pidl = NULL;
1056     HRESULT hr;
1057     static const UINT unsupported_browse_flags =
1058         SBSP_NEWBROWSER | EBF_SELECTFROMDATAOBJECT | EBF_NODROPTARGET;
1059     TRACE("%p (%p, 0x%x)\n", This, pidl, uFlags);
1060
1061     if(!This->hwnd_main)
1062         return E_FAIL;
1063
1064     if(This->destroyed)
1065         return HRESULT_FROM_WIN32(ERROR_BUSY);
1066
1067     if(This->current_pidl && (This->eb_options & EBO_NAVIGATEONCE))
1068         return E_FAIL;
1069
1070     if(uFlags & SBSP_EXPLOREMODE)
1071         return E_INVALIDARG;
1072
1073     if(uFlags & unsupported_browse_flags)
1074         FIXME("Argument 0x%x contains unsupported flags.\n", uFlags);
1075
1076     if(uFlags & SBSP_NAVIGATEBACK)
1077     {
1078         TRACE("SBSP_NAVIGATEBACK\n");
1079         absolute_pidl = ILClone(travellog_go_back(This));
1080         if(!absolute_pidl && !This->current_pidl)
1081             return E_FAIL;
1082         else if(!absolute_pidl)
1083             return S_OK;
1084
1085     }
1086     else if(uFlags & SBSP_NAVIGATEFORWARD)
1087     {
1088         TRACE("SBSP_NAVIGATEFORWARD\n");
1089         absolute_pidl = ILClone(travellog_go_forward(This));
1090         if(!absolute_pidl && !This->current_pidl)
1091             return E_FAIL;
1092         else if(!absolute_pidl)
1093             return S_OK;
1094
1095     }
1096     else if(uFlags & SBSP_PARENT)
1097     {
1098         if(This->current_pidl)
1099         {
1100             if(_ILIsPidlSimple(This->current_pidl))
1101             {
1102                 absolute_pidl = _ILCreateDesktop();
1103             }
1104             else
1105             {
1106                 absolute_pidl = ILClone(This->current_pidl);
1107                 ILRemoveLastID(absolute_pidl);
1108             }
1109         }
1110         if(!absolute_pidl)
1111         {
1112             ERR("Failed to get parent pidl.\n");
1113             return E_FAIL;
1114         }
1115
1116     }
1117     else if(uFlags & SBSP_RELATIVE)
1118     {
1119         /* SBSP_RELATIVE has precedence over SBSP_ABSOLUTE */
1120         TRACE("SBSP_RELATIVE\n");
1121         if(This->current_pidl)
1122         {
1123             absolute_pidl = ILCombine(This->current_pidl, pidl);
1124         }
1125         if(!absolute_pidl)
1126         {
1127             ERR("Failed to get absolute pidl.\n");
1128             return E_FAIL;
1129         }
1130     }
1131     else
1132     {
1133         TRACE("SBSP_ABSOLUTE\n");
1134         absolute_pidl = ILClone(pidl);
1135         if(!absolute_pidl && !This->current_pidl)
1136             return E_INVALIDARG;
1137         else if(!absolute_pidl)
1138             return S_OK;
1139     }
1140
1141     /* TODO: Asynchronous browsing. Return S_OK here and finish in
1142      * another thread. */
1143
1144     hr = events_NavigationPending(This, absolute_pidl);
1145     if(FAILED(hr))
1146     {
1147         TRACE("Browsing aborted.\n");
1148         ILFree(absolute_pidl);
1149         return E_FAIL;
1150     }
1151
1152     get_interfaces_from_site(This);
1153     update_panestate(This);
1154
1155     /* Only browse if the new pidl differs from the old */
1156     if(!ILIsEqual(This->current_pidl, absolute_pidl))
1157     {
1158         IShellItem *psi;
1159         hr = SHCreateItemFromIDList(absolute_pidl, &IID_IShellItem, (void**)&psi);
1160         if(SUCCEEDED(hr))
1161         {
1162             hr = create_new_shellview(This, psi);
1163             if(FAILED(hr))
1164             {
1165                 events_NavigationFailed(This, absolute_pidl);
1166                 ILFree(absolute_pidl);
1167                 IShellItem_Release(psi);
1168                 return E_FAIL;
1169             }
1170
1171             /* Add to travellog */
1172             if( !(This->eb_options & EBO_NOTRAVELLOG) &&
1173                 !(uFlags & (SBSP_NAVIGATEFORWARD|SBSP_NAVIGATEBACK)) )
1174             {
1175                 travellog_add_entry(This, absolute_pidl);
1176             }
1177
1178             IShellItem_Release(psi);
1179         }
1180     }
1181
1182     events_NavigationComplete(This, absolute_pidl);
1183     ILFree(This->current_pidl);
1184     This->current_pidl = absolute_pidl;
1185
1186     /* Expand the NameSpaceTree to the current location. */
1187     if(This->navpane.show && This->navpane.pnstc2)
1188     {
1189         IShellItem *psi;
1190         hr = SHCreateItemFromIDList(This->current_pidl, &IID_IShellItem, (void**)&psi);
1191         if(SUCCEEDED(hr))
1192         {
1193             INameSpaceTreeControl_EnsureItemVisible(This->navpane.pnstc2, psi);
1194             IShellItem_Release(psi);
1195         }
1196     }
1197
1198     return S_OK;
1199 }
1200
1201 static HRESULT WINAPI IExplorerBrowser_fnBrowseToObject(IExplorerBrowser *iface,
1202                                                         IUnknown *punk, UINT uFlags)
1203 {
1204     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1205     LPITEMIDLIST pidl;
1206     HRESULT hr;
1207     TRACE("%p (%p, 0x%x)\n", This, punk, uFlags);
1208
1209     if(!punk)
1210         return IExplorerBrowser_fnBrowseToIDList(iface, NULL, uFlags);
1211
1212     hr = SHGetIDListFromObject(punk, &pidl);
1213     if(SUCCEEDED(hr))
1214     {
1215         hr = IExplorerBrowser_BrowseToIDList(iface, pidl, uFlags);
1216         ILFree(pidl);
1217     }
1218
1219     return hr;
1220 }
1221
1222 static HRESULT WINAPI IExplorerBrowser_fnFillFromObject(IExplorerBrowser *iface,
1223                                                         IUnknown *punk,
1224                                                         EXPLORER_BROWSER_FILL_FLAGS dwFlags)
1225 {
1226     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1227     FIXME("stub, %p (%p, 0x%x)\n", This, punk, dwFlags);
1228
1229     return E_NOTIMPL;
1230 }
1231
1232 static HRESULT WINAPI IExplorerBrowser_fnRemoveAll(IExplorerBrowser *iface)
1233 {
1234     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1235     FIXME("stub, %p\n", This);
1236
1237     return E_NOTIMPL;
1238 }
1239
1240 static HRESULT WINAPI IExplorerBrowser_fnGetCurrentView(IExplorerBrowser *iface,
1241                                                         REFIID riid, void **ppv)
1242 {
1243     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1244     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppv);
1245
1246     if(!This->psv)
1247         return E_FAIL;
1248
1249     return IShellView_QueryInterface(This->psv, riid, ppv);
1250 }
1251
1252 static const IExplorerBrowserVtbl vt_IExplorerBrowser =
1253 {
1254     IExplorerBrowser_fnQueryInterface,
1255     IExplorerBrowser_fnAddRef,
1256     IExplorerBrowser_fnRelease,
1257     IExplorerBrowser_fnInitialize,
1258     IExplorerBrowser_fnDestroy,
1259     IExplorerBrowser_fnSetRect,
1260     IExplorerBrowser_fnSetPropertyBag,
1261     IExplorerBrowser_fnSetEmptyText,
1262     IExplorerBrowser_fnSetFolderSettings,
1263     IExplorerBrowser_fnAdvise,
1264     IExplorerBrowser_fnUnadvise,
1265     IExplorerBrowser_fnSetOptions,
1266     IExplorerBrowser_fnGetOptions,
1267     IExplorerBrowser_fnBrowseToIDList,
1268     IExplorerBrowser_fnBrowseToObject,
1269     IExplorerBrowser_fnFillFromObject,
1270     IExplorerBrowser_fnRemoveAll,
1271     IExplorerBrowser_fnGetCurrentView
1272 };
1273
1274 /**************************************************************************
1275  * IShellBrowser Implementation
1276  */
1277
1278 static inline ExplorerBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
1279 {
1280     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IShellBrowser_iface);
1281 }
1282
1283 static HRESULT WINAPI IShellBrowser_fnQueryInterface(IShellBrowser *iface,
1284                                                      REFIID riid, void **ppvObject)
1285 {
1286     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1287     TRACE("%p\n", This);
1288     return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
1289 }
1290
1291 static ULONG WINAPI IShellBrowser_fnAddRef(IShellBrowser *iface)
1292 {
1293     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1294     TRACE("%p\n", This);
1295     return IUnknown_AddRef((IUnknown*) This);
1296 }
1297
1298 static ULONG WINAPI IShellBrowser_fnRelease(IShellBrowser *iface)
1299 {
1300     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1301     TRACE("%p\n", This);
1302     return IUnknown_Release((IUnknown*) This);
1303 }
1304
1305 static HRESULT WINAPI IShellBrowser_fnGetWindow(IShellBrowser *iface, HWND *phwnd)
1306 {
1307     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1308     TRACE("%p (%p)\n", This, phwnd);
1309
1310     if(!This->hwnd_main)
1311         return E_FAIL;
1312
1313     *phwnd = This->hwnd_main;
1314     return S_OK;
1315 }
1316
1317 static HRESULT WINAPI IShellBrowser_fnContextSensitiveHelp(IShellBrowser *iface,
1318                                                            BOOL fEnterMode)
1319 {
1320     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1321     FIXME("stub, %p (%d)\n", This, fEnterMode);
1322
1323     return E_NOTIMPL;
1324 }
1325
1326 static HRESULT WINAPI IShellBrowser_fnInsertMenusSB(IShellBrowser *iface,
1327                                                     HMENU hmenuShared,
1328                                                     LPOLEMENUGROUPWIDTHS lpMenuWidths)
1329 {
1330     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1331     TRACE("%p (%p, %p)\n", This, hmenuShared, lpMenuWidths);
1332
1333     /* Not implemented. */
1334     return E_NOTIMPL;
1335 }
1336
1337 static HRESULT WINAPI IShellBrowser_fnSetMenuSB(IShellBrowser *iface,
1338                                                 HMENU hmenuShared,
1339                                                 HOLEMENU holemenuReserved,
1340                                                 HWND hwndActiveObject)
1341 {
1342     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1343     TRACE("%p (%p, %p, %p)\n", This, hmenuShared, holemenuReserved, hwndActiveObject);
1344
1345     /* Not implemented. */
1346     return E_NOTIMPL;
1347 }
1348
1349 static HRESULT WINAPI IShellBrowser_fnRemoveMenusSB(IShellBrowser *iface,
1350                                                     HMENU hmenuShared)
1351 {
1352     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1353     TRACE("%p (%p)\n", This, hmenuShared);
1354
1355     /* Not implemented. */
1356     return E_NOTIMPL;
1357 }
1358
1359 static HRESULT WINAPI IShellBrowser_fnSetStatusTextSB(IShellBrowser *iface,
1360                                                       LPCOLESTR pszStatusText)
1361 {
1362     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1363     FIXME("stub, %p (%s)\n", This, debugstr_w(pszStatusText));
1364
1365     return E_NOTIMPL;
1366 }
1367
1368 static HRESULT WINAPI IShellBrowser_fnEnableModelessSB(IShellBrowser *iface,
1369                                                        BOOL fEnable)
1370 {
1371     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1372     FIXME("stub, %p (%d)\n", This, fEnable);
1373
1374     return E_NOTIMPL;
1375 }
1376
1377 static HRESULT WINAPI IShellBrowser_fnTranslateAcceleratorSB(IShellBrowser *iface,
1378                                                              MSG *pmsg, WORD wID)
1379 {
1380     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1381     FIXME("stub, %p (%p, 0x%x)\n", This, pmsg, wID);
1382
1383     return E_NOTIMPL;
1384 }
1385
1386 static HRESULT WINAPI IShellBrowser_fnBrowseObject(IShellBrowser *iface,
1387                                                    LPCITEMIDLIST pidl, UINT wFlags)
1388 {
1389     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1390     TRACE("%p (%p, %x)\n", This, pidl, wFlags);
1391
1392     return IExplorerBrowser_fnBrowseToIDList((IExplorerBrowser*)This, pidl, wFlags);
1393 }
1394
1395 static HRESULT WINAPI IShellBrowser_fnGetViewStateStream(IShellBrowser *iface,
1396                                                          DWORD grfMode,
1397                                                          IStream **ppStrm)
1398 {
1399     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1400     FIXME("stub, %p (0x%x, %p)\n", This, grfMode, ppStrm);
1401
1402     *ppStrm = NULL;
1403     return E_FAIL;
1404 }
1405
1406 static HRESULT WINAPI IShellBrowser_fnGetControlWindow(IShellBrowser *iface,
1407                                                        UINT id, HWND *phwnd)
1408 {
1409     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1410     TRACE("%p (%d, %p)\n", This, id, phwnd);
1411
1412     /* Not implemented. */
1413     return E_NOTIMPL;
1414 }
1415
1416 static HRESULT WINAPI IShellBrowser_fnSendControlMsg(IShellBrowser *iface,
1417                                                      UINT id, UINT uMsg,
1418                                                      WPARAM wParam, LPARAM lParam,
1419                                                      LRESULT *pret)
1420 {
1421     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1422     FIXME("stub, %p (%d, %d, %lx, %lx, %p)\n", This, id, uMsg, wParam, lParam, pret);
1423
1424     return E_NOTIMPL;
1425 }
1426
1427 static HRESULT WINAPI IShellBrowser_fnQueryActiveShellView(IShellBrowser *iface,
1428                                                            IShellView **ppshv)
1429 {
1430     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1431     TRACE("%p (%p)\n", This, ppshv);
1432
1433     if(!This->psv)
1434         return E_FAIL;
1435
1436     *ppshv = This->psv;
1437     IShellView_AddRef(This->psv);
1438
1439     return S_OK;
1440 }
1441
1442 static HRESULT WINAPI IShellBrowser_fnOnViewWindowActive(IShellBrowser *iface,
1443                                                          IShellView *pshv)
1444 {
1445     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1446     FIXME("stub, %p (%p)\n", This, pshv);
1447
1448     return E_NOTIMPL;
1449 }
1450
1451 static HRESULT WINAPI IShellBrowser_fnSetToolbarItems(IShellBrowser *iface,
1452                                                       LPTBBUTTONSB lpButtons,
1453                                                       UINT nButtons, UINT uFlags)
1454 {
1455     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1456     FIXME("stub, %p (%p, %d, 0x%x)\n", This, lpButtons, nButtons, uFlags);
1457
1458     return E_NOTIMPL;
1459 }
1460
1461 static const IShellBrowserVtbl vt_IShellBrowser = {
1462     IShellBrowser_fnQueryInterface,
1463     IShellBrowser_fnAddRef,
1464     IShellBrowser_fnRelease,
1465     IShellBrowser_fnGetWindow,
1466     IShellBrowser_fnContextSensitiveHelp,
1467     IShellBrowser_fnInsertMenusSB,
1468     IShellBrowser_fnSetMenuSB,
1469     IShellBrowser_fnRemoveMenusSB,
1470     IShellBrowser_fnSetStatusTextSB,
1471     IShellBrowser_fnEnableModelessSB,
1472     IShellBrowser_fnTranslateAcceleratorSB,
1473     IShellBrowser_fnBrowseObject,
1474     IShellBrowser_fnGetViewStateStream,
1475     IShellBrowser_fnGetControlWindow,
1476     IShellBrowser_fnSendControlMsg,
1477     IShellBrowser_fnQueryActiveShellView,
1478     IShellBrowser_fnOnViewWindowActive,
1479     IShellBrowser_fnSetToolbarItems
1480 };
1481
1482 /**************************************************************************
1483  * ICommDlgBrowser3 Implementation
1484  */
1485
1486 static inline ExplorerBrowserImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
1487 {
1488     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, ICommDlgBrowser3_iface);
1489 }
1490
1491 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
1492                                                         REFIID riid,
1493                                                         void **ppvObject)
1494 {
1495     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1496     TRACE("%p\n", This);
1497     return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
1498 }
1499
1500 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
1501 {
1502     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1503     TRACE("%p\n", This);
1504     return IUnknown_AddRef((IUnknown*) This);
1505 }
1506
1507 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
1508 {
1509     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1510     TRACE("%p\n", This);
1511     return IUnknown_Release((IUnknown*) This);
1512 }
1513
1514 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
1515                                                           IShellView *shv)
1516 {
1517     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1518     IDataObject *pdo;
1519     HRESULT hr;
1520     HRESULT ret = S_FALSE;
1521
1522     TRACE("%p (%p)\n", This, shv);
1523
1524     hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&pdo);
1525     if(SUCCEEDED(hr))
1526     {
1527         FORMATETC fmt;
1528         STGMEDIUM medium;
1529
1530         fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
1531         fmt.ptd = NULL;
1532         fmt.dwAspect = DVASPECT_CONTENT;
1533         fmt.lindex = -1;
1534         fmt.tymed = TYMED_HGLOBAL;
1535
1536         hr = IDataObject_GetData(pdo, &fmt ,&medium);
1537         IDataObject_Release(pdo);
1538         if(SUCCEEDED(hr))
1539         {
1540             LPIDA pida = GlobalLock(medium.u.hGlobal);
1541             LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]);
1542
1543             /* Handle folders by browsing to them. */
1544             if(_ILIsFolder(pidl_child) || _ILIsDrive(pidl_child) || _ILIsSpecialFolder(pidl_child))
1545             {
1546                 IExplorerBrowser_BrowseToIDList((IExplorerBrowser*)This, pidl_child, SBSP_RELATIVE);
1547                 ret = S_OK;
1548             }
1549             GlobalUnlock(medium.u.hGlobal);
1550             GlobalFree(medium.u.hGlobal);
1551         }
1552         else
1553             ERR("Failed to get data from IDataObject.\n");
1554     } else
1555         ERR("Failed to get IDataObject.\n");
1556
1557     /* If we didn't handle the default command, check if we have a
1558      * client that does */
1559     if(ret == S_FALSE && This->pcdb_site)
1560         return ICommDlgBrowser_OnDefaultCommand(This->pcdb_site, shv);
1561
1562     return ret;
1563 }
1564 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
1565                                                        IShellView *shv, ULONG uChange)
1566 {
1567     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1568     TRACE("%p (%p, %d)\n", This, shv, uChange);
1569
1570     if(This->pcdb_site)
1571         return ICommDlgBrowser_OnStateChange(This->pcdb_site, shv, uChange);
1572
1573     return E_NOTIMPL;
1574 }
1575 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
1576                                                        IShellView *pshv, LPCITEMIDLIST pidl)
1577 {
1578     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1579     TRACE("%p (%p, %p)\n", This, pshv, pidl);
1580
1581     if(This->pcdb_site)
1582         return ICommDlgBrowser_IncludeObject(This->pcdb_site, pshv, pidl);
1583
1584     return S_OK;
1585 }
1586
1587 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
1588                                                 IShellView *pshv,
1589                                                 DWORD dwNotifyType)
1590 {
1591     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1592     TRACE("%p (%p, 0x%x)\n", This, pshv, dwNotifyType);
1593
1594     if(This->pcdb2_site)
1595         return ICommDlgBrowser2_Notify(This->pcdb2_site, pshv, dwNotifyType);
1596
1597     return S_OK;
1598 }
1599
1600 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
1601                                                             IShellView *pshv,
1602                                                             LPWSTR pszText, int cchMax)
1603 {
1604     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1605     TRACE("%p (%p, %s, %d)\n", This, pshv, debugstr_w(pszText), cchMax);
1606
1607     if(This->pcdb2_site)
1608         return ICommDlgBrowser2_GetDefaultMenuText(This->pcdb2_site, pshv, pszText, cchMax);
1609
1610     return S_OK;
1611 }
1612
1613 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface,
1614                                                       DWORD *pdwFlags)
1615 {
1616     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1617     TRACE("%p (%p)\n", This, pdwFlags);
1618
1619     if(This->pcdb2_site)
1620         return ICommDlgBrowser2_GetViewFlags(This->pcdb2_site, pdwFlags);
1621
1622     return S_OK;
1623 }
1624
1625 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
1626                                                          IShellView *pshv, int iColumn)
1627 {
1628     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1629     TRACE("%p (%p, %d)\n", This, pshv, iColumn);
1630
1631     if(This->pcdb3_site)
1632         return ICommDlgBrowser3_OnColumnClicked(This->pcdb3_site, pshv, iColumn);
1633
1634     return S_OK;
1635 }
1636
1637 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
1638                                                           LPWSTR pszFileSpec,
1639                                                           int cchFileSpec)
1640 {
1641     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1642     TRACE("%p (%s, %d)\n", This, debugstr_w(pszFileSpec), cchFileSpec);
1643
1644     if(This->pcdb3_site)
1645         return ICommDlgBrowser3_GetCurrentFilter(This->pcdb3_site, pszFileSpec, cchFileSpec);
1646
1647     return S_OK;
1648 }
1649
1650 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
1651                                                           IShellView *pshv)
1652 {
1653     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1654     TRACE("%p (%p)\n", This, pshv);
1655
1656     if(This->pcdb3_site)
1657         return ICommDlgBrowser3_OnPreviewCreated(This->pcdb3_site, pshv);
1658
1659     return S_OK;
1660 }
1661
1662 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
1663     ICommDlgBrowser3_fnQueryInterface,
1664     ICommDlgBrowser3_fnAddRef,
1665     ICommDlgBrowser3_fnRelease,
1666     ICommDlgBrowser3_fnOnDefaultCommand,
1667     ICommDlgBrowser3_fnOnStateChange,
1668     ICommDlgBrowser3_fnIncludeObject,
1669     ICommDlgBrowser3_fnNotify,
1670     ICommDlgBrowser3_fnGetDefaultMenuText,
1671     ICommDlgBrowser3_fnGetViewFlags,
1672     ICommDlgBrowser3_fnOnColumnClicked,
1673     ICommDlgBrowser3_fnGetCurrentFilter,
1674     ICommDlgBrowser3_fnOnPreviewCreated
1675 };
1676
1677 /**************************************************************************
1678  * IObjectWithSite Implementation
1679  */
1680
1681 static inline ExplorerBrowserImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
1682 {
1683     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IObjectWithSite_iface);
1684 }
1685
1686 static HRESULT WINAPI IObjectWithSite_fnQueryInterface(IObjectWithSite *iface,
1687                                                        REFIID riid, void **ppvObject)
1688 {
1689     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1690     TRACE("%p\n", This);
1691     return IUnknown_QueryInterface((IUnknown*)This, riid, ppvObject);
1692 }
1693
1694 static ULONG WINAPI IObjectWithSite_fnAddRef(IObjectWithSite *iface)
1695 {
1696     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1697     TRACE("%p\n", This);
1698     return IUnknown_AddRef((IUnknown*)This);
1699 }
1700
1701 static ULONG WINAPI IObjectWithSite_fnRelease(IObjectWithSite *iface)
1702 {
1703     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1704     TRACE("%p\n", This);
1705     return IUnknown_Release((IUnknown*)This);
1706 }
1707
1708 static HRESULT WINAPI IObjectWithSite_fnSetSite(IObjectWithSite *iface, IUnknown *punk_site)
1709 {
1710     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1711     TRACE("%p (%p)\n", This, punk_site);
1712
1713     if(This->punk_site)
1714     {
1715         IUnknown_Release(This->punk_site);
1716         This->punk_site = NULL;
1717         get_interfaces_from_site(This);
1718     }
1719
1720     This->punk_site = punk_site;
1721
1722     if(This->punk_site)
1723         IUnknown_AddRef(This->punk_site);
1724
1725     return S_OK;
1726 }
1727
1728 static HRESULT WINAPI IObjectWithSite_fnGetSite(IObjectWithSite *iface, REFIID riid, void **ppvSite)
1729 {
1730     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1731     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvSite);
1732
1733     if(!This->punk_site)
1734         return E_FAIL;
1735
1736     return IUnknown_QueryInterface(This->punk_site, riid, ppvSite);
1737 }
1738
1739 static const IObjectWithSiteVtbl vt_IObjectWithSite = {
1740     IObjectWithSite_fnQueryInterface,
1741     IObjectWithSite_fnAddRef,
1742     IObjectWithSite_fnRelease,
1743     IObjectWithSite_fnSetSite,
1744     IObjectWithSite_fnGetSite
1745 };
1746
1747 /**************************************************************************
1748  * INameSpaceTreeControlEvents Implementation
1749  */
1750 static inline ExplorerBrowserImpl *impl_from_INameSpaceTreeControlEvents(INameSpaceTreeControlEvents *iface)
1751 {
1752     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, INameSpaceTreeControlEvents_iface);
1753 }
1754
1755 static HRESULT WINAPI NSTCEvents_fnQueryInterface(INameSpaceTreeControlEvents *iface,
1756                                                   REFIID riid, void **ppvObject)
1757 {
1758     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1759     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
1760
1761     *ppvObject = NULL;
1762     if(IsEqualIID(riid, &IID_INameSpaceTreeControlEvents) ||
1763        IsEqualIID(riid, &IID_IUnknown))
1764     {
1765         *ppvObject = iface;
1766     }
1767
1768     if(*ppvObject)
1769     {
1770         IUnknown_AddRef((IUnknown*)*ppvObject);
1771         return S_OK;
1772     }
1773
1774     return E_NOINTERFACE;
1775 }
1776
1777 static ULONG WINAPI NSTCEvents_fnAddRef(INameSpaceTreeControlEvents *iface)
1778 {
1779     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1780     TRACE("%p\n", This);
1781     return IUnknown_AddRef((IUnknown*)This);
1782 }
1783
1784 static ULONG WINAPI NSTCEvents_fnRelease(INameSpaceTreeControlEvents *iface)
1785 {
1786     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1787     TRACE("%p\n", This);
1788     return IUnknown_Release((IUnknown*)This);
1789 }
1790
1791 static HRESULT WINAPI NSTCEvents_fnOnItemClick(INameSpaceTreeControlEvents *iface,
1792                                                IShellItem *psi,
1793                                                NSTCEHITTEST nstceHitTest,
1794                                                NSTCECLICKTYPE nstceClickType)
1795 {
1796     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1797     TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstceHitTest, nstceClickType);
1798     return S_OK;
1799 }
1800
1801 static HRESULT WINAPI NSTCEvents_fnOnPropertyItemCommit(INameSpaceTreeControlEvents *iface,
1802                                                         IShellItem *psi)
1803 {
1804     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1805     TRACE("%p (%p)\n", This, psi);
1806     return E_NOTIMPL;
1807 }
1808
1809 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanging(INameSpaceTreeControlEvents *iface,
1810                                                        IShellItem *psi,
1811                                                        NSTCITEMSTATE nstcisMask,
1812                                                        NSTCITEMSTATE nstcisState)
1813 {
1814     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1815     TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstcisMask, nstcisState);
1816     return E_NOTIMPL;
1817 }
1818
1819 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanged(INameSpaceTreeControlEvents *iface,
1820                                                       IShellItem *psi,
1821                                                       NSTCITEMSTATE nstcisMask,
1822                                                       NSTCITEMSTATE nstcisState)
1823 {
1824     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1825     TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstcisMask, nstcisState);
1826     return E_NOTIMPL;
1827 }
1828
1829 static HRESULT WINAPI NSTCEvents_fnOnSelectionChanged(INameSpaceTreeControlEvents *iface,
1830                                                       IShellItemArray *psiaSelection)
1831 {
1832     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1833     IShellItem *psi;
1834     HRESULT hr;
1835     TRACE("%p (%p)\n", This, psiaSelection);
1836
1837     hr = IShellItemArray_GetItemAt(psiaSelection, 0, &psi);
1838     if(SUCCEEDED(hr))
1839     {
1840         hr = IExplorerBrowser_BrowseToObject((IExplorerBrowser*)This,
1841                                              (IUnknown*)psi, SBSP_DEFBROWSER);
1842         IShellItem_Release(psi);
1843     }
1844
1845     return hr;
1846 }
1847
1848 static HRESULT WINAPI NSTCEvents_fnOnKeyboardInput(INameSpaceTreeControlEvents *iface,
1849                                                    UINT uMsg, WPARAM wParam, LPARAM lParam)
1850 {
1851     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1852     TRACE("%p (%d, 0x%lx, 0x%lx)\n", This, uMsg, wParam, lParam);
1853     return S_OK;
1854 }
1855
1856 static HRESULT WINAPI NSTCEvents_fnOnBeforeExpand(INameSpaceTreeControlEvents *iface,
1857                                                   IShellItem *psi)
1858 {
1859     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1860     TRACE("%p (%p)\n", This, psi);
1861     return E_NOTIMPL;
1862 }
1863
1864 static HRESULT WINAPI NSTCEvents_fnOnAfterExpand(INameSpaceTreeControlEvents *iface,
1865                                                  IShellItem *psi)
1866 {
1867     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1868     TRACE("%p (%p)\n", This, psi);
1869     return E_NOTIMPL;
1870 }
1871
1872 static HRESULT WINAPI NSTCEvents_fnOnBeginLabelEdit(INameSpaceTreeControlEvents *iface,
1873                                                     IShellItem *psi)
1874 {
1875     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1876     TRACE("%p (%p)\n", This, psi);
1877     return E_NOTIMPL;
1878 }
1879
1880 static HRESULT WINAPI NSTCEvents_fnOnEndLabelEdit(INameSpaceTreeControlEvents *iface,
1881                                                   IShellItem *psi)
1882 {
1883     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1884     TRACE("%p (%p)\n", This, psi);
1885     return E_NOTIMPL;
1886 }
1887
1888 static HRESULT WINAPI NSTCEvents_fnOnGetToolTip(INameSpaceTreeControlEvents *iface,
1889                                                 IShellItem *psi, LPWSTR pszTip, int cchTip)
1890 {
1891     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1892     TRACE("%p (%p, %p, %d)\n", This, psi, pszTip, cchTip);
1893     return E_NOTIMPL;
1894 }
1895
1896 static HRESULT WINAPI NSTCEvents_fnOnBeforeItemDelete(INameSpaceTreeControlEvents *iface,
1897                                                       IShellItem *psi)
1898 {
1899     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1900     TRACE("%p (%p)\n", This, psi);
1901     return E_NOTIMPL;
1902 }
1903
1904 static HRESULT WINAPI NSTCEvents_fnOnItemAdded(INameSpaceTreeControlEvents *iface,
1905                                                IShellItem *psi, BOOL fIsRoot)
1906 {
1907     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1908     TRACE("%p (%p, %d)\n", This, psi, fIsRoot);
1909     return E_NOTIMPL;
1910 }
1911
1912 static HRESULT WINAPI NSTCEvents_fnOnItemDeleted(INameSpaceTreeControlEvents *iface,
1913                                                  IShellItem *psi, BOOL fIsRoot)
1914 {
1915     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1916     TRACE("%p (%p, %d)\n", This, psi, fIsRoot);
1917     return E_NOTIMPL;
1918 }
1919
1920 static HRESULT WINAPI NSTCEvents_fnOnBeforeContextMenu(INameSpaceTreeControlEvents *iface,
1921                                                        IShellItem *psi, REFIID riid, void **ppv)
1922 {
1923     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1924     TRACE("%p (%p, %s, %p)\n", This, psi, shdebugstr_guid(riid), ppv);
1925     return E_NOTIMPL;
1926 }
1927
1928 static HRESULT WINAPI NSTCEvents_fnOnAfterContextMenu(INameSpaceTreeControlEvents *iface,
1929                                                       IShellItem *psi, IContextMenu *pcmIn,
1930                                                       REFIID riid, void **ppv)
1931 {
1932     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1933     TRACE("%p (%p, %p, %s, %p)\n", This, psi, pcmIn, shdebugstr_guid(riid), ppv);
1934     return E_NOTIMPL;
1935 }
1936
1937 static HRESULT WINAPI NSTCEvents_fnOnBeforeStateImageChange(INameSpaceTreeControlEvents *iface,
1938                                                             IShellItem *psi)
1939 {
1940     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1941     TRACE("%p (%p)\n", This, psi);
1942     return E_NOTIMPL;
1943 }
1944
1945 static HRESULT WINAPI NSTCEvents_fnOnGetDefaultIconIndex(INameSpaceTreeControlEvents* iface,
1946                                                          IShellItem *psi,
1947                                                          int *piDefaultIcon, int *piOpenIcon)
1948 {
1949     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1950     TRACE("%p (%p, %p, %p)\n", This, psi, piDefaultIcon, piOpenIcon);
1951     return E_NOTIMPL;
1952 }
1953
1954
1955 const INameSpaceTreeControlEventsVtbl vt_INameSpaceTreeControlEvents =  {
1956     NSTCEvents_fnQueryInterface,
1957     NSTCEvents_fnAddRef,
1958     NSTCEvents_fnRelease,
1959     NSTCEvents_fnOnItemClick,
1960     NSTCEvents_fnOnPropertyItemCommit,
1961     NSTCEvents_fnOnItemStateChanging,
1962     NSTCEvents_fnOnItemStateChanged,
1963     NSTCEvents_fnOnSelectionChanged,
1964     NSTCEvents_fnOnKeyboardInput,
1965     NSTCEvents_fnOnBeforeExpand,
1966     NSTCEvents_fnOnAfterExpand,
1967     NSTCEvents_fnOnBeginLabelEdit,
1968     NSTCEvents_fnOnEndLabelEdit,
1969     NSTCEvents_fnOnGetToolTip,
1970     NSTCEvents_fnOnBeforeItemDelete,
1971     NSTCEvents_fnOnItemAdded,
1972     NSTCEvents_fnOnItemDeleted,
1973     NSTCEvents_fnOnBeforeContextMenu,
1974     NSTCEvents_fnOnAfterContextMenu,
1975     NSTCEvents_fnOnBeforeStateImageChange,
1976     NSTCEvents_fnOnGetDefaultIconIndex
1977 };
1978
1979 /**************************************************************************
1980  * IInputObject Implementation
1981  */
1982
1983 static inline ExplorerBrowserImpl *impl_from_IInputObject(IInputObject *iface)
1984 {
1985     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IInputObject_iface);
1986 }
1987
1988 static HRESULT WINAPI IInputObject_fnQueryInterface(IInputObject *iface,
1989                                                     REFIID riid, void **ppvObject)
1990 {
1991     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
1992     TRACE("%p\n", This);
1993     return IUnknown_QueryInterface((IUnknown*)This, riid, ppvObject);
1994 }
1995
1996 static ULONG WINAPI IInputObject_fnAddRef(IInputObject *iface)
1997 {
1998     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
1999     TRACE("%p\n", This);
2000     return IUnknown_AddRef((IUnknown*)This);
2001 }
2002
2003 static ULONG WINAPI IInputObject_fnRelease(IInputObject *iface)
2004 {
2005     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2006     TRACE("%p\n", This);
2007     return IUnknown_Release((IUnknown*)This);
2008 }
2009
2010 static HRESULT WINAPI IInputObject_fnUIActivateIO(IInputObject *iface, BOOL fActivate, MSG *pMsg)
2011 {
2012     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2013     FIXME("stub, %p (%d, %p)\n", This, fActivate, pMsg);
2014     return E_NOTIMPL;
2015 }
2016
2017 static HRESULT WINAPI IInputObject_fnHasFocusIO(IInputObject *iface)
2018 {
2019     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2020     FIXME("stub, %p\n", This);
2021     return E_NOTIMPL;
2022 }
2023
2024 static HRESULT WINAPI IInputObject_fnTranslateAcceleratorIO(IInputObject *iface, MSG *pMsg)
2025 {
2026     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2027     FIXME("stub, %p (%p)\n", This, pMsg);
2028     return E_NOTIMPL;
2029 }
2030
2031 static IInputObjectVtbl vt_IInputObject = {
2032     IInputObject_fnQueryInterface,
2033     IInputObject_fnAddRef,
2034     IInputObject_fnRelease,
2035     IInputObject_fnUIActivateIO,
2036     IInputObject_fnHasFocusIO,
2037     IInputObject_fnTranslateAcceleratorIO
2038 };
2039
2040 HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
2041 {
2042     ExplorerBrowserImpl *eb;
2043     HRESULT ret;
2044
2045     TRACE("%p %s %p\n", pUnkOuter, shdebugstr_guid (riid), ppv);
2046
2047     if(!ppv)
2048         return E_POINTER;
2049     if(pUnkOuter)
2050         return CLASS_E_NOAGGREGATION;
2051
2052     eb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExplorerBrowserImpl));
2053     eb->ref = 1;
2054     eb->IExplorerBrowser_iface.lpVtbl = &vt_IExplorerBrowser;
2055     eb->IShellBrowser_iface.lpVtbl    = &vt_IShellBrowser;
2056     eb->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3;
2057     eb->IObjectWithSite_iface.lpVtbl  = &vt_IObjectWithSite;
2058     eb->INameSpaceTreeControlEvents_iface.lpVtbl = &vt_INameSpaceTreeControlEvents;
2059     eb->IInputObject_iface.lpVtbl     = &vt_IInputObject;
2060
2061     /* Default settings */
2062     eb->navpane.width = 150;
2063     eb->navpane.show = TRUE;
2064
2065     list_init(&eb->event_clients);
2066     list_init(&eb->travellog);
2067
2068     ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
2069     IExplorerBrowser_Release((IExplorerBrowser*)eb);
2070
2071     TRACE("--(%p)\n", ppv);
2072     return ret;
2073 }