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