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