msxml3: Support setting unlimited nesting depth for a reader.
[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 main_on_cwm_getishellbrowser(ExplorerBrowserImpl *This)
747 {
748     return (LRESULT)&This->IShellBrowser_iface;
749 }
750
751 static LRESULT CALLBACK main_wndproc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
752 {
753     ExplorerBrowserImpl *This = (ExplorerBrowserImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
754
755     switch(uMessage)
756     {
757     case WM_CREATE:           return main_on_wm_create(hWnd, (CREATESTRUCTW*)lParam);
758     case WM_SIZE:             return main_on_wm_size(This);
759     case CWM_GETISHELLBROWSER: return main_on_cwm_getishellbrowser(This);
760     default:                  return DefWindowProcW(hWnd, uMessage, wParam, lParam);
761     }
762
763     return 0;
764 }
765
766 /**************************************************************************
767  * IExplorerBrowser Implementation
768  */
769
770 static inline ExplorerBrowserImpl *impl_from_IExplorerBrowser(IExplorerBrowser *iface)
771 {
772     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IExplorerBrowser_iface);
773 }
774
775 static HRESULT WINAPI IExplorerBrowser_fnQueryInterface(IExplorerBrowser *iface,
776                                                         REFIID riid, void **ppvObject)
777 {
778     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
779     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
780
781     *ppvObject = NULL;
782     if(IsEqualIID(riid, &IID_IExplorerBrowser) ||
783        IsEqualIID(riid, &IID_IUnknown))
784     {
785         *ppvObject = This;
786     }
787     else if(IsEqualIID(riid, &IID_IShellBrowser))
788     {
789         *ppvObject = &This->IShellBrowser_iface;
790     }
791     else if(IsEqualIID(riid, &IID_ICommDlgBrowser) ||
792             IsEqualIID(riid, &IID_ICommDlgBrowser2) ||
793             IsEqualIID(riid, &IID_ICommDlgBrowser3))
794     {
795         *ppvObject = &This->ICommDlgBrowser3_iface;
796     }
797     else if(IsEqualIID(riid, &IID_IObjectWithSite))
798     {
799         *ppvObject = &This->IObjectWithSite_iface;
800     }
801     else if(IsEqualIID(riid, &IID_IInputObject))
802     {
803         *ppvObject = &This->IInputObject_iface;
804     }
805
806     if(*ppvObject)
807     {
808         IUnknown_AddRef((IUnknown*)*ppvObject);
809         return S_OK;
810     }
811
812     return E_NOINTERFACE;
813 }
814
815 static ULONG WINAPI IExplorerBrowser_fnAddRef(IExplorerBrowser *iface)
816 {
817     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
818     LONG ref = InterlockedIncrement(&This->ref);
819     TRACE("%p - ref %d\n", This, ref);
820
821     return ref;
822 }
823
824 static ULONG WINAPI IExplorerBrowser_fnRelease(IExplorerBrowser *iface)
825 {
826     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
827     LONG ref = InterlockedDecrement(&This->ref);
828     TRACE("%p - ref %d\n", This, ref);
829
830     if(!ref)
831     {
832         TRACE("Freeing.\n");
833
834         if(!This->destroyed)
835             IExplorerBrowser_Destroy(iface);
836
837         IObjectWithSite_SetSite(&This->IObjectWithSite_iface, NULL);
838
839         HeapFree(GetProcessHeap(), 0, This);
840         return 0;
841     }
842
843     return ref;
844 }
845
846 static HRESULT WINAPI IExplorerBrowser_fnInitialize(IExplorerBrowser *iface,
847                                                     HWND hwndParent, const RECT *prc,
848                                                     const FOLDERSETTINGS *pfs)
849 {
850     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
851     WNDCLASSW wc;
852     LONG style;
853     static const WCHAR EB_CLASS_NAME[] =
854         {'E','x','p','l','o','r','e','r','B','r','o','w','s','e','r','C','o','n','t','r','o','l',0};
855
856     TRACE("%p (%p, %p, %p)\n", This, hwndParent, prc, pfs);
857
858     if(This->hwnd_main)
859         return E_UNEXPECTED;
860
861     if(!hwndParent)
862         return E_INVALIDARG;
863
864     if( !GetClassInfoW(shell32_hInstance, EB_CLASS_NAME, &wc) )
865     {
866         wc.style            = CS_HREDRAW | CS_VREDRAW;
867         wc.lpfnWndProc      = main_wndproc;
868         wc.cbClsExtra       = 0;
869         wc.cbWndExtra       = 0;
870         wc.hInstance        = shell32_hInstance;
871         wc.hIcon            = 0;
872         wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_ARROW);
873         wc.hbrBackground    = (HBRUSH)(COLOR_WINDOW + 1);
874         wc.lpszMenuName     = NULL;
875         wc.lpszClassName    = EB_CLASS_NAME;
876
877         if (!RegisterClassW(&wc)) return E_FAIL;
878     }
879
880     style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER;
881     This->hwnd_main = CreateWindowExW(WS_EX_CONTROLPARENT, EB_CLASS_NAME, NULL, style,
882                                       prc->left, prc->top,
883                                       prc->right - prc->left, prc->bottom - prc->top,
884                                       hwndParent, 0, shell32_hInstance, This);
885
886     if(!This->hwnd_main)
887     {
888         ERR("Failed to create the window.\n");
889         return E_FAIL;
890     }
891
892     This->fs.ViewMode = pfs ? pfs->ViewMode : FVM_DETAILS;
893     This->fs.fFlags = pfs ? (pfs->fFlags | FWF_NOCLIENTEDGE) : FWF_NOCLIENTEDGE;
894
895     return S_OK;
896 }
897
898 static HRESULT WINAPI IExplorerBrowser_fnDestroy(IExplorerBrowser *iface)
899 {
900     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
901     TRACE("%p\n", This);
902
903     if(This->psv)
904     {
905         IShellView_DestroyViewWindow(This->psv);
906         IShellView_Release(This->psv);
907         This->psv = NULL;
908         This->hwnd_sv = NULL;
909     }
910
911     events_unadvise_all(This);
912     travellog_remove_all_entries(This);
913
914     ILFree(This->current_pidl);
915     This->current_pidl = NULL;
916
917     DestroyWindow(This->hwnd_main);
918     This->destroyed = TRUE;
919
920     return S_OK;
921 }
922
923 static HRESULT WINAPI IExplorerBrowser_fnSetRect(IExplorerBrowser *iface,
924                                                  HDWP *phdwp, RECT rcBrowser)
925 {
926     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
927     TRACE("%p (%p, %s)\n", This, phdwp, wine_dbgstr_rect(&rcBrowser));
928
929     if(phdwp && *phdwp)
930     {
931         *phdwp = DeferWindowPos(*phdwp, This->hwnd_main, NULL, rcBrowser.left, rcBrowser.top,
932                                 rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top,
933                                 SWP_NOZORDER | SWP_NOACTIVATE);
934         if(!*phdwp)
935             return E_FAIL;
936     }
937     else
938     {
939         MoveWindow(This->hwnd_main, rcBrowser.left, rcBrowser.top,
940                    rcBrowser.right - rcBrowser.left, rcBrowser.bottom - rcBrowser.top, TRUE);
941     }
942
943     return S_OK;
944 }
945
946 static HRESULT WINAPI IExplorerBrowser_fnSetPropertyBag(IExplorerBrowser *iface,
947                                                         LPCWSTR pszPropertyBag)
948 {
949     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
950     FIXME("stub, %p (%s)\n", This, debugstr_w(pszPropertyBag));
951
952     if(!pszPropertyBag)
953         return E_INVALIDARG;
954
955     /* FIXME: This method is currently useless as we don't save any
956      * settings anywhere, but at least one application breaks if we
957      * return E_NOTIMPL.
958      */
959
960     return S_OK;
961 }
962
963 static HRESULT WINAPI IExplorerBrowser_fnSetEmptyText(IExplorerBrowser *iface,
964                                                       LPCWSTR pszEmptyText)
965 {
966     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
967     FIXME("stub, %p (%s)\n", This, debugstr_w(pszEmptyText));
968
969     return E_NOTIMPL;
970 }
971
972 static HRESULT WINAPI IExplorerBrowser_fnSetFolderSettings(IExplorerBrowser *iface,
973                                                            const FOLDERSETTINGS *pfs)
974 {
975     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
976     TRACE("%p (%p)\n", This, pfs);
977
978     if(!pfs)
979         return E_INVALIDARG;
980
981     This->fs.ViewMode = pfs->ViewMode;
982     This->fs.fFlags = pfs->fFlags | FWF_NOCLIENTEDGE;
983
984     /* Change the settings of the current view, if any. */
985     return change_viewmode(This, This->fs.ViewMode);
986 }
987
988 static HRESULT WINAPI IExplorerBrowser_fnAdvise(IExplorerBrowser *iface,
989                                                 IExplorerBrowserEvents *psbe,
990                                                 DWORD *pdwCookie)
991 {
992     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
993     event_client *client;
994     TRACE("%p (%p, %p)\n", This, psbe, pdwCookie);
995
996     client = HeapAlloc(GetProcessHeap(), 0, sizeof(event_client));
997     client->pebe = psbe;
998     client->cookie = ++This->events_next_cookie;
999
1000     IExplorerBrowserEvents_AddRef(psbe);
1001     *pdwCookie = client->cookie;
1002
1003     list_add_tail(&This->event_clients, &client->entry);
1004
1005     return S_OK;
1006 }
1007
1008 static HRESULT WINAPI IExplorerBrowser_fnUnadvise(IExplorerBrowser *iface,
1009                                                   DWORD dwCookie)
1010 {
1011     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1012     event_client *client;
1013     TRACE("%p (0x%x)\n", This, dwCookie);
1014
1015     LIST_FOR_EACH_ENTRY(client, &This->event_clients, event_client, entry)
1016     {
1017         if(client->cookie == dwCookie)
1018         {
1019             list_remove(&client->entry);
1020             IExplorerBrowserEvents_Release(client->pebe);
1021             HeapFree(GetProcessHeap(), 0, client);
1022             return S_OK;
1023         }
1024     }
1025
1026     return E_INVALIDARG;
1027 }
1028
1029 static HRESULT WINAPI IExplorerBrowser_fnSetOptions(IExplorerBrowser *iface,
1030                                                     EXPLORER_BROWSER_OPTIONS dwFlag)
1031 {
1032     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1033     static const EXPLORER_BROWSER_OPTIONS unsupported_options =
1034         EBO_ALWAYSNAVIGATE | EBO_NOWRAPPERWINDOW | EBO_HTMLSHAREPOINTVIEW;
1035
1036     TRACE("%p (0x%x)\n", This, dwFlag);
1037
1038     if(dwFlag & unsupported_options)
1039         FIXME("Flags 0x%08x contains unsupported options.\n", dwFlag);
1040
1041     This->eb_options = dwFlag;
1042
1043     return S_OK;
1044 }
1045
1046 static HRESULT WINAPI IExplorerBrowser_fnGetOptions(IExplorerBrowser *iface,
1047                                                     EXPLORER_BROWSER_OPTIONS *pdwFlag)
1048 {
1049     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1050     TRACE("%p (%p)\n", This, pdwFlag);
1051
1052     *pdwFlag = This->eb_options;
1053
1054     return S_OK;
1055 }
1056
1057 static HRESULT WINAPI IExplorerBrowser_fnBrowseToIDList(IExplorerBrowser *iface,
1058                                                         PCUIDLIST_RELATIVE pidl,
1059                                                         UINT uFlags)
1060 {
1061     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1062     LPITEMIDLIST absolute_pidl = NULL;
1063     HRESULT hr;
1064     static const UINT unsupported_browse_flags =
1065         SBSP_NEWBROWSER | EBF_SELECTFROMDATAOBJECT | EBF_NODROPTARGET;
1066     TRACE("%p (%p, 0x%x)\n", This, pidl, uFlags);
1067
1068     if(!This->hwnd_main)
1069         return E_FAIL;
1070
1071     if(This->destroyed)
1072         return HRESULT_FROM_WIN32(ERROR_BUSY);
1073
1074     if(This->current_pidl && (This->eb_options & EBO_NAVIGATEONCE))
1075         return E_FAIL;
1076
1077     if(uFlags & SBSP_EXPLOREMODE)
1078         return E_INVALIDARG;
1079
1080     if(uFlags & unsupported_browse_flags)
1081         FIXME("Argument 0x%x contains unsupported flags.\n", uFlags);
1082
1083     if(uFlags & SBSP_NAVIGATEBACK)
1084     {
1085         TRACE("SBSP_NAVIGATEBACK\n");
1086         absolute_pidl = ILClone(travellog_go_back(This));
1087         if(!absolute_pidl && !This->current_pidl)
1088             return E_FAIL;
1089         else if(!absolute_pidl)
1090             return S_OK;
1091
1092     }
1093     else if(uFlags & SBSP_NAVIGATEFORWARD)
1094     {
1095         TRACE("SBSP_NAVIGATEFORWARD\n");
1096         absolute_pidl = ILClone(travellog_go_forward(This));
1097         if(!absolute_pidl && !This->current_pidl)
1098             return E_FAIL;
1099         else if(!absolute_pidl)
1100             return S_OK;
1101
1102     }
1103     else if(uFlags & SBSP_PARENT)
1104     {
1105         if(This->current_pidl)
1106         {
1107             if(_ILIsPidlSimple(This->current_pidl))
1108             {
1109                 absolute_pidl = _ILCreateDesktop();
1110             }
1111             else
1112             {
1113                 absolute_pidl = ILClone(This->current_pidl);
1114                 ILRemoveLastID(absolute_pidl);
1115             }
1116         }
1117         if(!absolute_pidl)
1118         {
1119             ERR("Failed to get parent pidl.\n");
1120             return E_FAIL;
1121         }
1122
1123     }
1124     else if(uFlags & SBSP_RELATIVE)
1125     {
1126         /* SBSP_RELATIVE has precedence over SBSP_ABSOLUTE */
1127         TRACE("SBSP_RELATIVE\n");
1128         if(This->current_pidl)
1129         {
1130             absolute_pidl = ILCombine(This->current_pidl, pidl);
1131         }
1132         if(!absolute_pidl)
1133         {
1134             ERR("Failed to get absolute pidl.\n");
1135             return E_FAIL;
1136         }
1137     }
1138     else
1139     {
1140         TRACE("SBSP_ABSOLUTE\n");
1141         absolute_pidl = ILClone(pidl);
1142         if(!absolute_pidl && !This->current_pidl)
1143             return E_INVALIDARG;
1144         else if(!absolute_pidl)
1145             return S_OK;
1146     }
1147
1148     /* TODO: Asynchronous browsing. Return S_OK here and finish in
1149      * another thread. */
1150
1151     hr = events_NavigationPending(This, absolute_pidl);
1152     if(FAILED(hr))
1153     {
1154         TRACE("Browsing aborted.\n");
1155         ILFree(absolute_pidl);
1156         return E_FAIL;
1157     }
1158
1159     get_interfaces_from_site(This);
1160     update_panestate(This);
1161
1162     /* Only browse if the new pidl differs from the old */
1163     if(!ILIsEqual(This->current_pidl, absolute_pidl))
1164     {
1165         IShellItem *psi;
1166         hr = SHCreateItemFromIDList(absolute_pidl, &IID_IShellItem, (void**)&psi);
1167         if(SUCCEEDED(hr))
1168         {
1169             hr = create_new_shellview(This, psi);
1170             if(FAILED(hr))
1171             {
1172                 events_NavigationFailed(This, absolute_pidl);
1173                 ILFree(absolute_pidl);
1174                 IShellItem_Release(psi);
1175                 return E_FAIL;
1176             }
1177
1178             /* Add to travellog */
1179             if( !(This->eb_options & EBO_NOTRAVELLOG) &&
1180                 !(uFlags & (SBSP_NAVIGATEFORWARD|SBSP_NAVIGATEBACK)) )
1181             {
1182                 travellog_add_entry(This, absolute_pidl);
1183             }
1184
1185             IShellItem_Release(psi);
1186         }
1187     }
1188
1189     events_NavigationComplete(This, absolute_pidl);
1190     ILFree(This->current_pidl);
1191     This->current_pidl = absolute_pidl;
1192
1193     /* Expand the NameSpaceTree to the current location. */
1194     if(This->navpane.show && This->navpane.pnstc2)
1195     {
1196         IShellItem *psi;
1197         hr = SHCreateItemFromIDList(This->current_pidl, &IID_IShellItem, (void**)&psi);
1198         if(SUCCEEDED(hr))
1199         {
1200             INameSpaceTreeControl_EnsureItemVisible(This->navpane.pnstc2, psi);
1201             IShellItem_Release(psi);
1202         }
1203     }
1204
1205     return S_OK;
1206 }
1207
1208 static HRESULT WINAPI IExplorerBrowser_fnBrowseToObject(IExplorerBrowser *iface,
1209                                                         IUnknown *punk, UINT uFlags)
1210 {
1211     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1212     LPITEMIDLIST pidl;
1213     HRESULT hr;
1214     TRACE("%p (%p, 0x%x)\n", This, punk, uFlags);
1215
1216     if(!punk)
1217         return IExplorerBrowser_fnBrowseToIDList(iface, NULL, uFlags);
1218
1219     hr = SHGetIDListFromObject(punk, &pidl);
1220     if(SUCCEEDED(hr))
1221     {
1222         hr = IExplorerBrowser_BrowseToIDList(iface, pidl, uFlags);
1223         ILFree(pidl);
1224     }
1225
1226     return hr;
1227 }
1228
1229 static HRESULT WINAPI IExplorerBrowser_fnFillFromObject(IExplorerBrowser *iface,
1230                                                         IUnknown *punk,
1231                                                         EXPLORER_BROWSER_FILL_FLAGS dwFlags)
1232 {
1233     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1234     FIXME("stub, %p (%p, 0x%x)\n", This, punk, dwFlags);
1235
1236     return E_NOTIMPL;
1237 }
1238
1239 static HRESULT WINAPI IExplorerBrowser_fnRemoveAll(IExplorerBrowser *iface)
1240 {
1241     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1242     FIXME("stub, %p\n", This);
1243
1244     return E_NOTIMPL;
1245 }
1246
1247 static HRESULT WINAPI IExplorerBrowser_fnGetCurrentView(IExplorerBrowser *iface,
1248                                                         REFIID riid, void **ppv)
1249 {
1250     ExplorerBrowserImpl *This = impl_from_IExplorerBrowser(iface);
1251     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppv);
1252
1253     if(!This->psv)
1254         return E_FAIL;
1255
1256     return IShellView_QueryInterface(This->psv, riid, ppv);
1257 }
1258
1259 static const IExplorerBrowserVtbl vt_IExplorerBrowser =
1260 {
1261     IExplorerBrowser_fnQueryInterface,
1262     IExplorerBrowser_fnAddRef,
1263     IExplorerBrowser_fnRelease,
1264     IExplorerBrowser_fnInitialize,
1265     IExplorerBrowser_fnDestroy,
1266     IExplorerBrowser_fnSetRect,
1267     IExplorerBrowser_fnSetPropertyBag,
1268     IExplorerBrowser_fnSetEmptyText,
1269     IExplorerBrowser_fnSetFolderSettings,
1270     IExplorerBrowser_fnAdvise,
1271     IExplorerBrowser_fnUnadvise,
1272     IExplorerBrowser_fnSetOptions,
1273     IExplorerBrowser_fnGetOptions,
1274     IExplorerBrowser_fnBrowseToIDList,
1275     IExplorerBrowser_fnBrowseToObject,
1276     IExplorerBrowser_fnFillFromObject,
1277     IExplorerBrowser_fnRemoveAll,
1278     IExplorerBrowser_fnGetCurrentView
1279 };
1280
1281 /**************************************************************************
1282  * IShellBrowser Implementation
1283  */
1284
1285 static inline ExplorerBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
1286 {
1287     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IShellBrowser_iface);
1288 }
1289
1290 static HRESULT WINAPI IShellBrowser_fnQueryInterface(IShellBrowser *iface,
1291                                                      REFIID riid, void **ppvObject)
1292 {
1293     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1294     TRACE("%p\n", This);
1295     return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
1296 }
1297
1298 static ULONG WINAPI IShellBrowser_fnAddRef(IShellBrowser *iface)
1299 {
1300     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1301     TRACE("%p\n", This);
1302     return IUnknown_AddRef((IUnknown*) This);
1303 }
1304
1305 static ULONG WINAPI IShellBrowser_fnRelease(IShellBrowser *iface)
1306 {
1307     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1308     TRACE("%p\n", This);
1309     return IUnknown_Release((IUnknown*) This);
1310 }
1311
1312 static HRESULT WINAPI IShellBrowser_fnGetWindow(IShellBrowser *iface, HWND *phwnd)
1313 {
1314     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1315     TRACE("%p (%p)\n", This, phwnd);
1316
1317     if(!This->hwnd_main)
1318         return E_FAIL;
1319
1320     *phwnd = This->hwnd_main;
1321     return S_OK;
1322 }
1323
1324 static HRESULT WINAPI IShellBrowser_fnContextSensitiveHelp(IShellBrowser *iface,
1325                                                            BOOL fEnterMode)
1326 {
1327     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1328     FIXME("stub, %p (%d)\n", This, fEnterMode);
1329
1330     return E_NOTIMPL;
1331 }
1332
1333 static HRESULT WINAPI IShellBrowser_fnInsertMenusSB(IShellBrowser *iface,
1334                                                     HMENU hmenuShared,
1335                                                     LPOLEMENUGROUPWIDTHS lpMenuWidths)
1336 {
1337     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1338     TRACE("%p (%p, %p)\n", This, hmenuShared, lpMenuWidths);
1339
1340     /* Not implemented. */
1341     return E_NOTIMPL;
1342 }
1343
1344 static HRESULT WINAPI IShellBrowser_fnSetMenuSB(IShellBrowser *iface,
1345                                                 HMENU hmenuShared,
1346                                                 HOLEMENU holemenuReserved,
1347                                                 HWND hwndActiveObject)
1348 {
1349     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1350     TRACE("%p (%p, %p, %p)\n", This, hmenuShared, holemenuReserved, hwndActiveObject);
1351
1352     /* Not implemented. */
1353     return E_NOTIMPL;
1354 }
1355
1356 static HRESULT WINAPI IShellBrowser_fnRemoveMenusSB(IShellBrowser *iface,
1357                                                     HMENU hmenuShared)
1358 {
1359     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1360     TRACE("%p (%p)\n", This, hmenuShared);
1361
1362     /* Not implemented. */
1363     return E_NOTIMPL;
1364 }
1365
1366 static HRESULT WINAPI IShellBrowser_fnSetStatusTextSB(IShellBrowser *iface,
1367                                                       LPCOLESTR pszStatusText)
1368 {
1369     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1370     FIXME("stub, %p (%s)\n", This, debugstr_w(pszStatusText));
1371
1372     return E_NOTIMPL;
1373 }
1374
1375 static HRESULT WINAPI IShellBrowser_fnEnableModelessSB(IShellBrowser *iface,
1376                                                        BOOL fEnable)
1377 {
1378     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1379     FIXME("stub, %p (%d)\n", This, fEnable);
1380
1381     return E_NOTIMPL;
1382 }
1383
1384 static HRESULT WINAPI IShellBrowser_fnTranslateAcceleratorSB(IShellBrowser *iface,
1385                                                              MSG *pmsg, WORD wID)
1386 {
1387     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1388     FIXME("stub, %p (%p, 0x%x)\n", This, pmsg, wID);
1389
1390     return E_NOTIMPL;
1391 }
1392
1393 static HRESULT WINAPI IShellBrowser_fnBrowseObject(IShellBrowser *iface,
1394                                                    LPCITEMIDLIST pidl, UINT wFlags)
1395 {
1396     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1397     TRACE("%p (%p, %x)\n", This, pidl, wFlags);
1398
1399     return IExplorerBrowser_fnBrowseToIDList((IExplorerBrowser*)This, pidl, wFlags);
1400 }
1401
1402 static HRESULT WINAPI IShellBrowser_fnGetViewStateStream(IShellBrowser *iface,
1403                                                          DWORD grfMode,
1404                                                          IStream **ppStrm)
1405 {
1406     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1407     FIXME("stub, %p (0x%x, %p)\n", This, grfMode, ppStrm);
1408
1409     *ppStrm = NULL;
1410     return E_FAIL;
1411 }
1412
1413 static HRESULT WINAPI IShellBrowser_fnGetControlWindow(IShellBrowser *iface,
1414                                                        UINT id, HWND *phwnd)
1415 {
1416     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1417     TRACE("%p (%d, %p)\n", This, id, phwnd);
1418
1419     /* Not implemented. */
1420     return E_NOTIMPL;
1421 }
1422
1423 static HRESULT WINAPI IShellBrowser_fnSendControlMsg(IShellBrowser *iface,
1424                                                      UINT id, UINT uMsg,
1425                                                      WPARAM wParam, LPARAM lParam,
1426                                                      LRESULT *pret)
1427 {
1428     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1429     FIXME("stub, %p (%d, %d, %lx, %lx, %p)\n", This, id, uMsg, wParam, lParam, pret);
1430
1431     return E_NOTIMPL;
1432 }
1433
1434 static HRESULT WINAPI IShellBrowser_fnQueryActiveShellView(IShellBrowser *iface,
1435                                                            IShellView **ppshv)
1436 {
1437     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1438     TRACE("%p (%p)\n", This, ppshv);
1439
1440     if(!This->psv)
1441         return E_FAIL;
1442
1443     *ppshv = This->psv;
1444     IShellView_AddRef(This->psv);
1445
1446     return S_OK;
1447 }
1448
1449 static HRESULT WINAPI IShellBrowser_fnOnViewWindowActive(IShellBrowser *iface,
1450                                                          IShellView *pshv)
1451 {
1452     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1453     FIXME("stub, %p (%p)\n", This, pshv);
1454
1455     return E_NOTIMPL;
1456 }
1457
1458 static HRESULT WINAPI IShellBrowser_fnSetToolbarItems(IShellBrowser *iface,
1459                                                       LPTBBUTTONSB lpButtons,
1460                                                       UINT nButtons, UINT uFlags)
1461 {
1462     ExplorerBrowserImpl *This = impl_from_IShellBrowser(iface);
1463     FIXME("stub, %p (%p, %d, 0x%x)\n", This, lpButtons, nButtons, uFlags);
1464
1465     return E_NOTIMPL;
1466 }
1467
1468 static const IShellBrowserVtbl vt_IShellBrowser = {
1469     IShellBrowser_fnQueryInterface,
1470     IShellBrowser_fnAddRef,
1471     IShellBrowser_fnRelease,
1472     IShellBrowser_fnGetWindow,
1473     IShellBrowser_fnContextSensitiveHelp,
1474     IShellBrowser_fnInsertMenusSB,
1475     IShellBrowser_fnSetMenuSB,
1476     IShellBrowser_fnRemoveMenusSB,
1477     IShellBrowser_fnSetStatusTextSB,
1478     IShellBrowser_fnEnableModelessSB,
1479     IShellBrowser_fnTranslateAcceleratorSB,
1480     IShellBrowser_fnBrowseObject,
1481     IShellBrowser_fnGetViewStateStream,
1482     IShellBrowser_fnGetControlWindow,
1483     IShellBrowser_fnSendControlMsg,
1484     IShellBrowser_fnQueryActiveShellView,
1485     IShellBrowser_fnOnViewWindowActive,
1486     IShellBrowser_fnSetToolbarItems
1487 };
1488
1489 /**************************************************************************
1490  * ICommDlgBrowser3 Implementation
1491  */
1492
1493 static inline ExplorerBrowserImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
1494 {
1495     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, ICommDlgBrowser3_iface);
1496 }
1497
1498 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
1499                                                         REFIID riid,
1500                                                         void **ppvObject)
1501 {
1502     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1503     TRACE("%p\n", This);
1504     return IUnknown_QueryInterface((IUnknown*) This, riid, ppvObject);
1505 }
1506
1507 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
1508 {
1509     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1510     TRACE("%p\n", This);
1511     return IUnknown_AddRef((IUnknown*) This);
1512 }
1513
1514 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
1515 {
1516     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1517     TRACE("%p\n", This);
1518     return IUnknown_Release((IUnknown*) This);
1519 }
1520
1521 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
1522                                                           IShellView *shv)
1523 {
1524     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1525     IDataObject *pdo;
1526     HRESULT hr;
1527     HRESULT ret = S_FALSE;
1528
1529     TRACE("%p (%p)\n", This, shv);
1530
1531     hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&pdo);
1532     if(SUCCEEDED(hr))
1533     {
1534         FORMATETC fmt;
1535         STGMEDIUM medium;
1536
1537         fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
1538         fmt.ptd = NULL;
1539         fmt.dwAspect = DVASPECT_CONTENT;
1540         fmt.lindex = -1;
1541         fmt.tymed = TYMED_HGLOBAL;
1542
1543         hr = IDataObject_GetData(pdo, &fmt ,&medium);
1544         IDataObject_Release(pdo);
1545         if(SUCCEEDED(hr))
1546         {
1547             LPIDA pida = GlobalLock(medium.u.hGlobal);
1548             LPCITEMIDLIST pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]);
1549
1550             /* Handle folders by browsing to them. */
1551             if(_ILIsFolder(pidl_child) || _ILIsDrive(pidl_child) || _ILIsSpecialFolder(pidl_child))
1552             {
1553                 IExplorerBrowser_BrowseToIDList((IExplorerBrowser*)This, pidl_child, SBSP_RELATIVE);
1554                 ret = S_OK;
1555             }
1556             GlobalUnlock(medium.u.hGlobal);
1557             GlobalFree(medium.u.hGlobal);
1558         }
1559         else
1560             ERR("Failed to get data from IDataObject.\n");
1561     } else
1562         ERR("Failed to get IDataObject.\n");
1563
1564     /* If we didn't handle the default command, check if we have a
1565      * client that does */
1566     if(ret == S_FALSE && This->pcdb_site)
1567         return ICommDlgBrowser_OnDefaultCommand(This->pcdb_site, shv);
1568
1569     return ret;
1570 }
1571 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
1572                                                        IShellView *shv, ULONG uChange)
1573 {
1574     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1575     TRACE("%p (%p, %d)\n", This, shv, uChange);
1576
1577     if(This->pcdb_site)
1578         return ICommDlgBrowser_OnStateChange(This->pcdb_site, shv, uChange);
1579
1580     return E_NOTIMPL;
1581 }
1582 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
1583                                                        IShellView *pshv, LPCITEMIDLIST pidl)
1584 {
1585     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1586     TRACE("%p (%p, %p)\n", This, pshv, pidl);
1587
1588     if(This->pcdb_site)
1589         return ICommDlgBrowser_IncludeObject(This->pcdb_site, pshv, pidl);
1590
1591     return S_OK;
1592 }
1593
1594 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
1595                                                 IShellView *pshv,
1596                                                 DWORD dwNotifyType)
1597 {
1598     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1599     TRACE("%p (%p, 0x%x)\n", This, pshv, dwNotifyType);
1600
1601     if(This->pcdb2_site)
1602         return ICommDlgBrowser2_Notify(This->pcdb2_site, pshv, dwNotifyType);
1603
1604     return S_OK;
1605 }
1606
1607 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
1608                                                             IShellView *pshv,
1609                                                             LPWSTR pszText, int cchMax)
1610 {
1611     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1612     TRACE("%p (%p, %s, %d)\n", This, pshv, debugstr_w(pszText), cchMax);
1613
1614     if(This->pcdb2_site)
1615         return ICommDlgBrowser2_GetDefaultMenuText(This->pcdb2_site, pshv, pszText, cchMax);
1616
1617     return S_OK;
1618 }
1619
1620 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface,
1621                                                       DWORD *pdwFlags)
1622 {
1623     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1624     TRACE("%p (%p)\n", This, pdwFlags);
1625
1626     if(This->pcdb2_site)
1627         return ICommDlgBrowser2_GetViewFlags(This->pcdb2_site, pdwFlags);
1628
1629     return S_OK;
1630 }
1631
1632 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
1633                                                          IShellView *pshv, int iColumn)
1634 {
1635     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1636     TRACE("%p (%p, %d)\n", This, pshv, iColumn);
1637
1638     if(This->pcdb3_site)
1639         return ICommDlgBrowser3_OnColumnClicked(This->pcdb3_site, pshv, iColumn);
1640
1641     return S_OK;
1642 }
1643
1644 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
1645                                                           LPWSTR pszFileSpec,
1646                                                           int cchFileSpec)
1647 {
1648     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1649     TRACE("%p (%s, %d)\n", This, debugstr_w(pszFileSpec), cchFileSpec);
1650
1651     if(This->pcdb3_site)
1652         return ICommDlgBrowser3_GetCurrentFilter(This->pcdb3_site, pszFileSpec, cchFileSpec);
1653
1654     return S_OK;
1655 }
1656
1657 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
1658                                                           IShellView *pshv)
1659 {
1660     ExplorerBrowserImpl *This = impl_from_ICommDlgBrowser3(iface);
1661     TRACE("%p (%p)\n", This, pshv);
1662
1663     if(This->pcdb3_site)
1664         return ICommDlgBrowser3_OnPreviewCreated(This->pcdb3_site, pshv);
1665
1666     return S_OK;
1667 }
1668
1669 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
1670     ICommDlgBrowser3_fnQueryInterface,
1671     ICommDlgBrowser3_fnAddRef,
1672     ICommDlgBrowser3_fnRelease,
1673     ICommDlgBrowser3_fnOnDefaultCommand,
1674     ICommDlgBrowser3_fnOnStateChange,
1675     ICommDlgBrowser3_fnIncludeObject,
1676     ICommDlgBrowser3_fnNotify,
1677     ICommDlgBrowser3_fnGetDefaultMenuText,
1678     ICommDlgBrowser3_fnGetViewFlags,
1679     ICommDlgBrowser3_fnOnColumnClicked,
1680     ICommDlgBrowser3_fnGetCurrentFilter,
1681     ICommDlgBrowser3_fnOnPreviewCreated
1682 };
1683
1684 /**************************************************************************
1685  * IObjectWithSite Implementation
1686  */
1687
1688 static inline ExplorerBrowserImpl *impl_from_IObjectWithSite(IObjectWithSite *iface)
1689 {
1690     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IObjectWithSite_iface);
1691 }
1692
1693 static HRESULT WINAPI IObjectWithSite_fnQueryInterface(IObjectWithSite *iface,
1694                                                        REFIID riid, void **ppvObject)
1695 {
1696     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1697     TRACE("%p\n", This);
1698     return IUnknown_QueryInterface((IUnknown*)This, riid, ppvObject);
1699 }
1700
1701 static ULONG WINAPI IObjectWithSite_fnAddRef(IObjectWithSite *iface)
1702 {
1703     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1704     TRACE("%p\n", This);
1705     return IUnknown_AddRef((IUnknown*)This);
1706 }
1707
1708 static ULONG WINAPI IObjectWithSite_fnRelease(IObjectWithSite *iface)
1709 {
1710     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1711     TRACE("%p\n", This);
1712     return IUnknown_Release((IUnknown*)This);
1713 }
1714
1715 static HRESULT WINAPI IObjectWithSite_fnSetSite(IObjectWithSite *iface, IUnknown *punk_site)
1716 {
1717     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1718     TRACE("%p (%p)\n", This, punk_site);
1719
1720     if(This->punk_site)
1721     {
1722         IUnknown_Release(This->punk_site);
1723         This->punk_site = NULL;
1724         get_interfaces_from_site(This);
1725     }
1726
1727     This->punk_site = punk_site;
1728
1729     if(This->punk_site)
1730         IUnknown_AddRef(This->punk_site);
1731
1732     return S_OK;
1733 }
1734
1735 static HRESULT WINAPI IObjectWithSite_fnGetSite(IObjectWithSite *iface, REFIID riid, void **ppvSite)
1736 {
1737     ExplorerBrowserImpl *This = impl_from_IObjectWithSite(iface);
1738     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvSite);
1739
1740     if(!This->punk_site)
1741         return E_FAIL;
1742
1743     return IUnknown_QueryInterface(This->punk_site, riid, ppvSite);
1744 }
1745
1746 static const IObjectWithSiteVtbl vt_IObjectWithSite = {
1747     IObjectWithSite_fnQueryInterface,
1748     IObjectWithSite_fnAddRef,
1749     IObjectWithSite_fnRelease,
1750     IObjectWithSite_fnSetSite,
1751     IObjectWithSite_fnGetSite
1752 };
1753
1754 /**************************************************************************
1755  * INameSpaceTreeControlEvents Implementation
1756  */
1757 static inline ExplorerBrowserImpl *impl_from_INameSpaceTreeControlEvents(INameSpaceTreeControlEvents *iface)
1758 {
1759     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, INameSpaceTreeControlEvents_iface);
1760 }
1761
1762 static HRESULT WINAPI NSTCEvents_fnQueryInterface(INameSpaceTreeControlEvents *iface,
1763                                                   REFIID riid, void **ppvObject)
1764 {
1765     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1766     TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
1767
1768     *ppvObject = NULL;
1769     if(IsEqualIID(riid, &IID_INameSpaceTreeControlEvents) ||
1770        IsEqualIID(riid, &IID_IUnknown))
1771     {
1772         *ppvObject = iface;
1773     }
1774
1775     if(*ppvObject)
1776     {
1777         IUnknown_AddRef((IUnknown*)*ppvObject);
1778         return S_OK;
1779     }
1780
1781     return E_NOINTERFACE;
1782 }
1783
1784 static ULONG WINAPI NSTCEvents_fnAddRef(INameSpaceTreeControlEvents *iface)
1785 {
1786     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1787     TRACE("%p\n", This);
1788     return IUnknown_AddRef((IUnknown*)This);
1789 }
1790
1791 static ULONG WINAPI NSTCEvents_fnRelease(INameSpaceTreeControlEvents *iface)
1792 {
1793     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1794     TRACE("%p\n", This);
1795     return IUnknown_Release((IUnknown*)This);
1796 }
1797
1798 static HRESULT WINAPI NSTCEvents_fnOnItemClick(INameSpaceTreeControlEvents *iface,
1799                                                IShellItem *psi,
1800                                                NSTCEHITTEST nstceHitTest,
1801                                                NSTCECLICKTYPE nstceClickType)
1802 {
1803     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1804     TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstceHitTest, nstceClickType);
1805     return S_OK;
1806 }
1807
1808 static HRESULT WINAPI NSTCEvents_fnOnPropertyItemCommit(INameSpaceTreeControlEvents *iface,
1809                                                         IShellItem *psi)
1810 {
1811     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1812     TRACE("%p (%p)\n", This, psi);
1813     return E_NOTIMPL;
1814 }
1815
1816 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanging(INameSpaceTreeControlEvents *iface,
1817                                                        IShellItem *psi,
1818                                                        NSTCITEMSTATE nstcisMask,
1819                                                        NSTCITEMSTATE nstcisState)
1820 {
1821     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1822     TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstcisMask, nstcisState);
1823     return E_NOTIMPL;
1824 }
1825
1826 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanged(INameSpaceTreeControlEvents *iface,
1827                                                       IShellItem *psi,
1828                                                       NSTCITEMSTATE nstcisMask,
1829                                                       NSTCITEMSTATE nstcisState)
1830 {
1831     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1832     TRACE("%p (%p, 0x%x, 0x%x)\n", This, psi, nstcisMask, nstcisState);
1833     return E_NOTIMPL;
1834 }
1835
1836 static HRESULT WINAPI NSTCEvents_fnOnSelectionChanged(INameSpaceTreeControlEvents *iface,
1837                                                       IShellItemArray *psiaSelection)
1838 {
1839     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1840     IShellItem *psi;
1841     HRESULT hr;
1842     TRACE("%p (%p)\n", This, psiaSelection);
1843
1844     hr = IShellItemArray_GetItemAt(psiaSelection, 0, &psi);
1845     if(SUCCEEDED(hr))
1846     {
1847         hr = IExplorerBrowser_BrowseToObject((IExplorerBrowser*)This,
1848                                              (IUnknown*)psi, SBSP_DEFBROWSER);
1849         IShellItem_Release(psi);
1850     }
1851
1852     return hr;
1853 }
1854
1855 static HRESULT WINAPI NSTCEvents_fnOnKeyboardInput(INameSpaceTreeControlEvents *iface,
1856                                                    UINT uMsg, WPARAM wParam, LPARAM lParam)
1857 {
1858     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1859     TRACE("%p (%d, 0x%lx, 0x%lx)\n", This, uMsg, wParam, lParam);
1860     return S_OK;
1861 }
1862
1863 static HRESULT WINAPI NSTCEvents_fnOnBeforeExpand(INameSpaceTreeControlEvents *iface,
1864                                                   IShellItem *psi)
1865 {
1866     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1867     TRACE("%p (%p)\n", This, psi);
1868     return E_NOTIMPL;
1869 }
1870
1871 static HRESULT WINAPI NSTCEvents_fnOnAfterExpand(INameSpaceTreeControlEvents *iface,
1872                                                  IShellItem *psi)
1873 {
1874     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1875     TRACE("%p (%p)\n", This, psi);
1876     return E_NOTIMPL;
1877 }
1878
1879 static HRESULT WINAPI NSTCEvents_fnOnBeginLabelEdit(INameSpaceTreeControlEvents *iface,
1880                                                     IShellItem *psi)
1881 {
1882     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1883     TRACE("%p (%p)\n", This, psi);
1884     return E_NOTIMPL;
1885 }
1886
1887 static HRESULT WINAPI NSTCEvents_fnOnEndLabelEdit(INameSpaceTreeControlEvents *iface,
1888                                                   IShellItem *psi)
1889 {
1890     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1891     TRACE("%p (%p)\n", This, psi);
1892     return E_NOTIMPL;
1893 }
1894
1895 static HRESULT WINAPI NSTCEvents_fnOnGetToolTip(INameSpaceTreeControlEvents *iface,
1896                                                 IShellItem *psi, LPWSTR pszTip, int cchTip)
1897 {
1898     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1899     TRACE("%p (%p, %p, %d)\n", This, psi, pszTip, cchTip);
1900     return E_NOTIMPL;
1901 }
1902
1903 static HRESULT WINAPI NSTCEvents_fnOnBeforeItemDelete(INameSpaceTreeControlEvents *iface,
1904                                                       IShellItem *psi)
1905 {
1906     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1907     TRACE("%p (%p)\n", This, psi);
1908     return E_NOTIMPL;
1909 }
1910
1911 static HRESULT WINAPI NSTCEvents_fnOnItemAdded(INameSpaceTreeControlEvents *iface,
1912                                                IShellItem *psi, BOOL fIsRoot)
1913 {
1914     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1915     TRACE("%p (%p, %d)\n", This, psi, fIsRoot);
1916     return E_NOTIMPL;
1917 }
1918
1919 static HRESULT WINAPI NSTCEvents_fnOnItemDeleted(INameSpaceTreeControlEvents *iface,
1920                                                  IShellItem *psi, BOOL fIsRoot)
1921 {
1922     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1923     TRACE("%p (%p, %d)\n", This, psi, fIsRoot);
1924     return E_NOTIMPL;
1925 }
1926
1927 static HRESULT WINAPI NSTCEvents_fnOnBeforeContextMenu(INameSpaceTreeControlEvents *iface,
1928                                                        IShellItem *psi, REFIID riid, void **ppv)
1929 {
1930     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1931     TRACE("%p (%p, %s, %p)\n", This, psi, shdebugstr_guid(riid), ppv);
1932     return E_NOTIMPL;
1933 }
1934
1935 static HRESULT WINAPI NSTCEvents_fnOnAfterContextMenu(INameSpaceTreeControlEvents *iface,
1936                                                       IShellItem *psi, IContextMenu *pcmIn,
1937                                                       REFIID riid, void **ppv)
1938 {
1939     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1940     TRACE("%p (%p, %p, %s, %p)\n", This, psi, pcmIn, shdebugstr_guid(riid), ppv);
1941     return E_NOTIMPL;
1942 }
1943
1944 static HRESULT WINAPI NSTCEvents_fnOnBeforeStateImageChange(INameSpaceTreeControlEvents *iface,
1945                                                             IShellItem *psi)
1946 {
1947     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1948     TRACE("%p (%p)\n", This, psi);
1949     return E_NOTIMPL;
1950 }
1951
1952 static HRESULT WINAPI NSTCEvents_fnOnGetDefaultIconIndex(INameSpaceTreeControlEvents* iface,
1953                                                          IShellItem *psi,
1954                                                          int *piDefaultIcon, int *piOpenIcon)
1955 {
1956     ExplorerBrowserImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
1957     TRACE("%p (%p, %p, %p)\n", This, psi, piDefaultIcon, piOpenIcon);
1958     return E_NOTIMPL;
1959 }
1960
1961
1962 static const INameSpaceTreeControlEventsVtbl vt_INameSpaceTreeControlEvents =  {
1963     NSTCEvents_fnQueryInterface,
1964     NSTCEvents_fnAddRef,
1965     NSTCEvents_fnRelease,
1966     NSTCEvents_fnOnItemClick,
1967     NSTCEvents_fnOnPropertyItemCommit,
1968     NSTCEvents_fnOnItemStateChanging,
1969     NSTCEvents_fnOnItemStateChanged,
1970     NSTCEvents_fnOnSelectionChanged,
1971     NSTCEvents_fnOnKeyboardInput,
1972     NSTCEvents_fnOnBeforeExpand,
1973     NSTCEvents_fnOnAfterExpand,
1974     NSTCEvents_fnOnBeginLabelEdit,
1975     NSTCEvents_fnOnEndLabelEdit,
1976     NSTCEvents_fnOnGetToolTip,
1977     NSTCEvents_fnOnBeforeItemDelete,
1978     NSTCEvents_fnOnItemAdded,
1979     NSTCEvents_fnOnItemDeleted,
1980     NSTCEvents_fnOnBeforeContextMenu,
1981     NSTCEvents_fnOnAfterContextMenu,
1982     NSTCEvents_fnOnBeforeStateImageChange,
1983     NSTCEvents_fnOnGetDefaultIconIndex
1984 };
1985
1986 /**************************************************************************
1987  * IInputObject Implementation
1988  */
1989
1990 static inline ExplorerBrowserImpl *impl_from_IInputObject(IInputObject *iface)
1991 {
1992     return CONTAINING_RECORD(iface, ExplorerBrowserImpl, IInputObject_iface);
1993 }
1994
1995 static HRESULT WINAPI IInputObject_fnQueryInterface(IInputObject *iface,
1996                                                     REFIID riid, void **ppvObject)
1997 {
1998     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
1999     TRACE("%p\n", This);
2000     return IUnknown_QueryInterface((IUnknown*)This, riid, ppvObject);
2001 }
2002
2003 static ULONG WINAPI IInputObject_fnAddRef(IInputObject *iface)
2004 {
2005     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2006     TRACE("%p\n", This);
2007     return IUnknown_AddRef((IUnknown*)This);
2008 }
2009
2010 static ULONG WINAPI IInputObject_fnRelease(IInputObject *iface)
2011 {
2012     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2013     TRACE("%p\n", This);
2014     return IUnknown_Release((IUnknown*)This);
2015 }
2016
2017 static HRESULT WINAPI IInputObject_fnUIActivateIO(IInputObject *iface, BOOL fActivate, MSG *pMsg)
2018 {
2019     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2020     FIXME("stub, %p (%d, %p)\n", This, fActivate, pMsg);
2021     return E_NOTIMPL;
2022 }
2023
2024 static HRESULT WINAPI IInputObject_fnHasFocusIO(IInputObject *iface)
2025 {
2026     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2027     FIXME("stub, %p\n", This);
2028     return E_NOTIMPL;
2029 }
2030
2031 static HRESULT WINAPI IInputObject_fnTranslateAcceleratorIO(IInputObject *iface, MSG *pMsg)
2032 {
2033     ExplorerBrowserImpl *This = impl_from_IInputObject(iface);
2034     FIXME("stub, %p (%p)\n", This, pMsg);
2035     return E_NOTIMPL;
2036 }
2037
2038 static IInputObjectVtbl vt_IInputObject = {
2039     IInputObject_fnQueryInterface,
2040     IInputObject_fnAddRef,
2041     IInputObject_fnRelease,
2042     IInputObject_fnUIActivateIO,
2043     IInputObject_fnHasFocusIO,
2044     IInputObject_fnTranslateAcceleratorIO
2045 };
2046
2047 HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
2048 {
2049     ExplorerBrowserImpl *eb;
2050     HRESULT ret;
2051
2052     TRACE("%p %s %p\n", pUnkOuter, shdebugstr_guid (riid), ppv);
2053
2054     if(!ppv)
2055         return E_POINTER;
2056     if(pUnkOuter)
2057         return CLASS_E_NOAGGREGATION;
2058
2059     eb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ExplorerBrowserImpl));
2060     eb->ref = 1;
2061     eb->IExplorerBrowser_iface.lpVtbl = &vt_IExplorerBrowser;
2062     eb->IShellBrowser_iface.lpVtbl    = &vt_IShellBrowser;
2063     eb->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3;
2064     eb->IObjectWithSite_iface.lpVtbl  = &vt_IObjectWithSite;
2065     eb->INameSpaceTreeControlEvents_iface.lpVtbl = &vt_INameSpaceTreeControlEvents;
2066     eb->IInputObject_iface.lpVtbl     = &vt_IInputObject;
2067
2068     /* Default settings */
2069     eb->navpane.width = 150;
2070     eb->navpane.show = TRUE;
2071
2072     list_init(&eb->event_clients);
2073     list_init(&eb->travellog);
2074
2075     ret = IExplorerBrowser_QueryInterface((IExplorerBrowser*)eb, riid, ppv);
2076     IExplorerBrowser_Release((IExplorerBrowser*)eb);
2077
2078     TRACE("--(%p)\n", ppv);
2079     return ret;
2080 }