shell32: Get ExplorerPaneVisibility from site of the ExplorerBrowser control.
[wine] / dlls / shell32 / tests / ebrowser.c
1 /*
2  *    Unit tests for the Explorer Browser control
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 <stdio.h>
22
23 #define COBJMACROS
24
25 #include "shlobj.h"
26 #include "shlwapi.h"
27
28 #include "wine/test.h"
29
30 #include "initguid.h"
31 #include "mshtml.h"
32
33 /**********************************************************************
34  * Some IID's for test_SetSite.
35  */
36 DEFINE_GUID(IID_IBrowserSettings,     0xDD1E21CC, 0xE2C7, 0x402C, 0xBF,0x05, 0x10,0x32,0x8D,0x3F,0x6B,0xAD);
37 DEFINE_GUID(IID_IShellBrowserService, 0xDFBC7E30, 0xF9E5, 0x455F, 0x88,0xF8, 0xFA,0x98,0xC1,0xE4,0x94,0xCA);
38 DEFINE_GUID(IID_IShellTaskScheduler,  0x6CCB7BE0, 0x6807, 0x11D0, 0xB8,0x10, 0x00,0xC0,0x4F,0xD7,0x06,0xEC);
39 DEFINE_GUID(IID_IBrowserWithActivationNotification,
40                                       0x6DB89131, 0x7B4C, 0x4E1C, 0x8B,0x01, 0x5D,0x31,0x2C,0x9C,0x73,0x88);
41 DEFINE_GUID(IID_ILayoutModifier,      0x90B4135A, 0x95BA, 0x46EA, 0x8C,0xAA, 0xE0,0x5B,0x45,0xCD,0x80,0x1E);
42 DEFINE_GUID(CLSID_Desktop,            0x00021400, 0x0000, 0x0000, 0xC0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46);
43 DEFINE_GUID(IID_IFileDialogPrivate,   0xAC92FFC5, 0xF0E9, 0x455A, 0x90,0x6B, 0x4A,0x83,0xE7,0x4A,0x80,0x3B);
44 DEFINE_GUID(IID_IWebbrowserApp,       0x0002df05, 0x0000, 0x0000, 0xc0,0x00, 0x00,0x00,0x00,0x00,0x00,0x46);
45 DEFINE_GUID(IID_IBrowserSettings_Vista, 0xF81B80BC, 0x29D1, 0x4734, 0xB5,0x15, 0x77,0x24,0xBF,0xF1,0x60,0x01);
46 DEFINE_GUID(IID_IFolderTypeModifier,    0x04BA120E, 0xAD52, 0x4A2D, 0x98,0x07, 0x2D,0xA1,0x78,0xD0,0xC3,0xE1);
47 DEFINE_GUID(IID_IShellBrowserService_Vista, 0xF5A24314, 0x5B8B, 0x44FA, 0xBC,0x2E, 0x31,0x28,0x55,0x44,0xB5,0x20);
48 DEFINE_GUID(IID_IFileDialogPrivate_Vista, 0x2539E31C, 0x857F, 0x43C4, 0x88,0x72, 0x45,0xBD,0x6A,0x02,0x48,0x92);
49 DEFINE_GUID(SID_SMenuBandParent,      0x8C278EEC, 0x3EAB, 0x11D1, 0x8C,0xB0 ,0x00,0xC0,0x4F,0xD9,0x18,0xD0);
50 DEFINE_GUID(SID_SMenuPopup,           0xD1E7AFEB, 0x6A2E, 0x11D0, 0x8C,0x78, 0x00,0xC0,0x4F,0xD9,0x18,0xB4);
51 DEFINE_GUID(IID_IShellMenu,           0xEE1F7637, 0xE138, 0x11D1, 0x83,0x79, 0x00,0xC0,0x4F,0xD9,0x18,0xD0);
52
53 DEFINE_GUID(IID_UnknownInterface1,    0x3934E4C2, 0x8143, 0x4E4C, 0xA1,0xDC, 0x71,0x8F,0x85,0x63,0xF3,0x37);
54 DEFINE_GUID(IID_UnknownInterface2,    0x3E24A11C, 0x15B2, 0x4F71, 0xB8,0x1E, 0x00,0x8F,0x77,0x99,0x8E,0x9F);
55 DEFINE_GUID(IID_UnknownInterface3,    0xE38FE0F3, 0x3DB0, 0x47EE, 0xA3,0x14, 0x25,0xCF,0x7F,0x4B,0xF5,0x21);
56 DEFINE_GUID(IID_UnknownInterface4,    0xFAD451C2, 0xAF58, 0x4161, 0xB9,0xFF, 0x57,0xAF,0xBB,0xED,0x0A,0xD2);
57 DEFINE_GUID(IID_UnknownInterface5,    0xF80C2137, 0x5829, 0x4CE9, 0x9F,0x81, 0xA9,0x5E,0x15,0x9D,0xD8,0xD5);
58 DEFINE_GUID(IID_UnknownInterface6,    0xD7F81F62, 0x491F, 0x49BC, 0x89,0x1D, 0x56,0x65,0x08,0x5D,0xF9,0x69);
59 DEFINE_GUID(IID_UnknownInterface7,    0x68A4FDBA, 0xA48A, 0x4A86, 0xA3,0x29, 0x1B,0x69,0xB9,0xB1,0x9E,0x89);
60 DEFINE_GUID(IID_UnknownInterface8,    0xD3B1CAF5, 0xEC4F, 0x4B2E, 0xBC,0xB0, 0x60,0xD7,0x15,0xC9,0x3C,0xB2);
61 DEFINE_GUID(IID_UnknownInterface9,    0x9536CA39, 0x1ACB, 0x4AE6, 0xAD,0x27, 0x24,0x03,0xD0,0x4C,0xA2,0x8F);
62 DEFINE_GUID(IID_UnknownInterface10,   0xB722BE00, 0x4E68, 0x101B, 0xA2,0xBC, 0x00,0xAA,0x00,0x40,0x47,0x70);
63
64 static HWND hwnd;
65
66 static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
67 static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*);
68
69 static void init_function_pointers(void)
70 {
71     HMODULE hmod;
72
73     hmod = GetModuleHandleA("shell32.dll");
74     pSHCreateShellItem = (void*)GetProcAddress(hmod, "SHCreateShellItem");
75     pSHParseDisplayName = (void*)GetProcAddress(hmod, "SHParseDisplayName");
76 }
77
78 /*********************************************************************
79  * Some simple helpers
80  */
81 static HRESULT ebrowser_instantiate(IExplorerBrowser **peb)
82 {
83     return CoCreateInstance(&CLSID_ExplorerBrowser, NULL, CLSCTX_INPROC_SERVER,
84                             &IID_IExplorerBrowser, (void**)peb);
85 }
86
87 static HRESULT ebrowser_initialize(IExplorerBrowser *peb)
88 {
89     RECT rc;
90     rc.top = rc.left = 0; rc.bottom = rc.right = 500;
91     return IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
92 }
93
94 static HRESULT ebrowser_browse_to_desktop(IExplorerBrowser *peb)
95 {
96     LPITEMIDLIST pidl_desktop;
97     SHGetSpecialFolderLocation (hwnd, CSIDL_DESKTOP, &pidl_desktop);
98     return IExplorerBrowser_BrowseToIDList(peb, pidl_desktop, 0);
99 }
100
101 /* Process some messages */
102 static void process_msgs(void)
103 {
104     MSG msg;
105     while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
106     {
107         TranslateMessage(&msg);
108         DispatchMessage(&msg);
109     }
110 }
111
112 static void dbg_print_guid(const GUID *guid) {
113     WCHAR buf[MAX_PATH];
114
115     StringFromGUID2(guid, buf, MAX_PATH);
116     printf("guid:[%s]\n", wine_dbgstr_wn(buf, lstrlenW(buf)));
117 }
118
119 /*********************************************************************
120  * IExplorerBrowserEvents implementation
121  */
122 typedef struct {
123     const IExplorerBrowserEventsVtbl *lpVtbl;
124     LONG ref;
125     UINT pending, created, completed, failed;
126 } IExplorerBrowserEventsImpl;
127
128 static IExplorerBrowserEventsImpl ebev;
129
130 static HRESULT WINAPI IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents *iface,
131                                                               REFIID riid, void **ppvObj)
132 {
133     ok(0, "Never called.\n");
134     return E_NOINTERFACE;
135 }
136
137 static ULONG WINAPI IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents *iface)
138 {
139     IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
140     return InterlockedIncrement(&This->ref);
141 }
142
143 static ULONG WINAPI IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents *iface)
144 {
145     IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
146     return InterlockedDecrement(&This->ref);
147 }
148
149 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents *iface,
150                                                                    PCIDLIST_ABSOLUTE pidlFolder)
151 {
152     IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
153     This->pending++;
154     return S_OK;
155 }
156
157 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents *iface,
158                                                                     PCIDLIST_ABSOLUTE pidlFolder)
159 {
160     IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
161     This->completed++;
162     return S_OK;
163 }
164 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents *iface,
165                                                                   PCIDLIST_ABSOLUTE pidlFolder)
166 {
167     IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
168     This->failed++;
169     return S_OK;
170 }
171 static HRESULT WINAPI IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents *iface,
172                                                              IShellView *psv)
173 {
174     IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
175     This->created++;
176     return S_OK;
177 }
178
179 static const IExplorerBrowserEventsVtbl ebevents =
180 {
181     IExplorerBrowserEvents_fnQueryInterface,
182     IExplorerBrowserEvents_fnAddRef,
183     IExplorerBrowserEvents_fnRelease,
184     IExplorerBrowserEvents_fnOnNavigationPending,
185     IExplorerBrowserEvents_fnOnViewCreated,
186     IExplorerBrowserEvents_fnOnNavigationComplete,
187     IExplorerBrowserEvents_fnOnNavigationFailed
188 };
189
190 /*********************************************************************
191  * IExplorerPaneVisibility implementation
192  */
193 typedef struct
194 {
195     const IExplorerPaneVisibilityVtbl *lpVtbl;
196     LONG ref;
197     LONG count;
198     LONG np, cp, cp_o, cp_v, dp, pp, qp, aqp, unk; /* The panes */
199 } IExplorerPaneVisibilityImpl;
200
201 static HRESULT WINAPI IExplorerPaneVisibility_fnQueryInterface(IExplorerPaneVisibility *iface,
202                                                                REFIID riid, LPVOID *ppvObj)
203 {
204     ok(0, "Not called.\n");
205     trace("REFIID:"); dbg_print_guid(riid);
206     *ppvObj = NULL;
207     return E_NOINTERFACE;
208 }
209
210 static ULONG WINAPI IExplorerPaneVisibility_fnAddRef(IExplorerPaneVisibility *iface)
211 {
212     IExplorerPaneVisibilityImpl *This = (IExplorerPaneVisibilityImpl *)iface;
213     return InterlockedIncrement(&This->ref);
214 }
215
216 static ULONG WINAPI IExplorerPaneVisibility_fnRelease(IExplorerPaneVisibility *iface)
217 {
218     IExplorerPaneVisibilityImpl *This = (IExplorerPaneVisibilityImpl *)iface;
219     ULONG ref = InterlockedDecrement(&This->ref);
220
221     if(!ref)
222         HeapFree(GetProcessHeap(), 0, This);
223
224     return ref;
225 }
226
227 static HRESULT WINAPI IExplorerPaneVisibility_fnGetPaneState(IExplorerPaneVisibility *iface,
228                                                              REFEXPLORERPANE ep,
229                                                              EXPLORERPANESTATE *peps)
230 {
231     IExplorerPaneVisibilityImpl *This = (IExplorerPaneVisibilityImpl *)iface;
232     This->count++;
233
234     ok(ep != NULL, "ep is NULL.\n");
235     ok(peps != NULL, "peps is NULL.\n");
236     ok(*peps == 0, "got %d\n", *peps);
237
238     *peps = EPS_FORCE;
239     if(IsEqualGUID(&EP_NavPane, ep))                 This->np++;
240     else if(IsEqualGUID(&EP_Commands, ep))           This->cp++;
241     else if(IsEqualGUID(&EP_Commands_Organize, ep))  This->cp_o++;
242     else if(IsEqualGUID(&EP_Commands_View, ep))      This->cp_v++;
243     else if(IsEqualGUID(&EP_DetailsPane, ep))        This->dp++;
244     else if(IsEqualGUID(&EP_PreviewPane, ep))        This->pp++;
245     else if(IsEqualGUID(&EP_QueryPane, ep))          This->qp++;
246     else if(IsEqualGUID(&EP_AdvQueryPane, ep))       This->aqp++;
247     else
248     {
249         trace("Unknown explorer pane: "); dbg_print_guid(ep);
250         This->unk++;
251     }
252
253     return S_OK;
254 }
255
256 static const IExplorerPaneVisibilityVtbl epvvt =
257 {
258     IExplorerPaneVisibility_fnQueryInterface,
259     IExplorerPaneVisibility_fnAddRef,
260     IExplorerPaneVisibility_fnRelease,
261     IExplorerPaneVisibility_fnGetPaneState
262 };
263
264 static IExplorerPaneVisibilityImpl *create_explorerpanevisibility(void)
265 {
266     IExplorerPaneVisibilityImpl *epv;
267
268     epv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IExplorerPaneVisibilityImpl));
269     epv->lpVtbl = &epvvt;
270     epv->ref = 1;
271
272     return epv;
273 }
274
275 /*********************************************************************
276  * ICommDlgBrowser3 implementation
277  */
278 typedef struct
279 {
280     const ICommDlgBrowser3Vtbl *lpVtbl;
281     LONG ref;
282     UINT OnDefaultCommand, OnStateChange, IncludeObject;
283     UINT Notify, GetDefaultMenuText, GetViewFlags;
284     UINT OnColumnClicked, GetCurrentFilter, OnPreviewCreated;
285 } ICommDlgBrowser3Impl;
286
287 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface, REFIID riid, LPVOID *ppvObj)
288 {
289     ok(0, "Not called.\n");
290     trace("riid:");    dbg_print_guid(riid);
291     *ppvObj = NULL;
292     return E_NOINTERFACE;
293 }
294
295 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
296 {
297     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
298     return InterlockedIncrement(&This->ref);
299 }
300
301 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
302 {
303     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
304     ULONG ref = InterlockedDecrement(&This->ref);
305
306     if(!ref)
307         HeapFree(GetProcessHeap(), 0, This);
308
309     return ref;
310 }
311
312 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3* iface, IShellView *shv)
313 {
314     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
315     This->OnDefaultCommand++;
316     return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(
320     ICommDlgBrowser3* iface,
321     IShellView *shv,
322     ULONG uChange)
323 {
324     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
325     This->OnStateChange++;
326     return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(
330     ICommDlgBrowser3* iface,
331     IShellView *shv,
332     LPCITEMIDLIST pidl)
333 {
334     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
335     This->IncludeObject++;
336     return S_OK;
337 }
338
339 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(
340     ICommDlgBrowser3* iface,
341     IShellView *ppshv,
342     DWORD dwNotifyType)
343 {
344     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
345     This->Notify++;
346     return E_NOTIMPL;
347 }
348
349 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(
350     ICommDlgBrowser3* iface,
351     IShellView *ppshv,
352     LPWSTR pszText,
353     int cchMax)
354 {
355     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
356     This->GetDefaultMenuText++;
357     return E_NOTIMPL;
358 }
359
360 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(
361     ICommDlgBrowser3* iface,
362     DWORD *pdwFlags)
363 {
364     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
365     This->GetViewFlags++;
366     return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(
370     ICommDlgBrowser3* iface,
371     IShellView *ppshv,
372     int iColumn)
373 {
374     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
375     This->OnColumnClicked++;
376     return E_NOTIMPL;
377 }
378
379 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(
380     ICommDlgBrowser3* iface,
381     LPWSTR pszFileSpec,
382     int cchFileSpec)
383 {
384     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
385     This->GetCurrentFilter++;
386     return E_NOTIMPL;
387 }
388
389 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(
390     ICommDlgBrowser3* iface,
391     IShellView *ppshv)
392 {
393     ICommDlgBrowser3Impl *This = (ICommDlgBrowser3Impl *)iface;
394     This->OnPreviewCreated++;
395     return E_NOTIMPL;
396 }
397
398 static const ICommDlgBrowser3Vtbl cdbvtbl =
399 {
400     ICommDlgBrowser3_fnQueryInterface,
401     ICommDlgBrowser3_fnAddRef,
402     ICommDlgBrowser3_fnRelease,
403     ICommDlgBrowser3_fnOnDefaultCommand,
404     ICommDlgBrowser3_fnOnStateChange,
405     ICommDlgBrowser3_fnIncludeObject,
406     ICommDlgBrowser3_fnNotify,
407     ICommDlgBrowser3_fnGetDefaultMenuText,
408     ICommDlgBrowser3_fnGetViewFlags,
409     ICommDlgBrowser3_fnOnColumnClicked,
410     ICommDlgBrowser3_fnGetCurrentFilter,
411     ICommDlgBrowser3_fnOnPreviewCreated
412 };
413
414 ICommDlgBrowser3Impl *create_commdlgbrowser3(void)
415 {
416     ICommDlgBrowser3Impl *cdb;
417
418     cdb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ICommDlgBrowser3Impl));
419     cdb->lpVtbl = &cdbvtbl;
420     cdb->ref = 1;
421
422     return cdb;
423 }
424
425 /*********************************************************************
426  * IServiceProvider Implementation
427  */
428 typedef struct {
429     const IServiceProviderVtbl *lpVtbl;
430     LONG ref;
431     struct services {
432         REFGUID service;
433         REFIID id;
434         int count;
435         void *punk;
436     } *interfaces;
437 } IServiceProviderImpl;
438
439 static HRESULT WINAPI IServiceProvider_fnQueryInterface(IServiceProvider *iface, REFIID riid, LPVOID *ppvObj)
440 {
441     *ppvObj = NULL;
442     if(IsEqualIID(riid, &IID_IServiceProvider))
443     {
444         *ppvObj = iface;
445         IServiceProvider_AddRef((IServiceProvider*)iface);
446         return S_OK;
447     }
448
449     if(IsEqualIID(riid, &IID_IOleCommandTarget))
450     {
451         /* Windows Vista. */
452         return E_NOINTERFACE;
453     }
454
455     ok(0, "Unexpected interface requested.\n");
456     trace("riid: "); dbg_print_guid(riid);
457     return E_NOINTERFACE;
458 }
459
460 static ULONG WINAPI IServiceProvider_fnAddRef(IServiceProvider *iface)
461 {
462     IServiceProviderImpl *This = (IServiceProviderImpl*)iface;
463     return InterlockedIncrement(&This->ref);
464 }
465
466 static ULONG WINAPI IServiceProvider_fnRelease(IServiceProvider *iface)
467 {
468     IServiceProviderImpl *This = (IServiceProviderImpl*)iface;
469     LONG ref = InterlockedDecrement(&This->ref);
470
471     if(!ref)
472         HeapFree(GetProcessHeap(), 0, This);
473
474     return ref;
475 }
476
477 static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface,
478                                                       REFGUID guidService,
479                                                       REFIID riid,
480                                                       void **ppv)
481 {
482     IServiceProviderImpl *This = (IServiceProviderImpl*)iface;
483     BOOL was_in_list = FALSE;
484     IUnknown *punk = NULL;
485     UINT i;
486
487     *ppv = NULL;
488     for(i = 0; This->interfaces[i].service != NULL; i++)
489     {
490         if(IsEqualGUID(This->interfaces[i].service, guidService) &&
491            IsEqualIID(This->interfaces[i].id, riid))
492         {
493             was_in_list = TRUE;
494             This->interfaces[i].count++;
495             punk = This->interfaces[i].punk;
496             break;
497         }
498     }
499
500     ok(was_in_list, "-- Unknown service requested --\n");
501     if(!was_in_list)
502     {
503         trace("guidService: "); dbg_print_guid(guidService);
504         trace("riid: "); dbg_print_guid(riid);
505     }
506
507     /* Give back an interface, if any. */
508     if(punk)
509     {
510         *ppv = punk;
511         IUnknown_AddRef((IUnknown*)punk);
512         return S_OK;
513     }
514
515     return E_NOINTERFACE;
516 }
517
518 static const IServiceProviderVtbl spvtbl =
519 {
520     IServiceProvider_fnQueryInterface,
521     IServiceProvider_fnAddRef,
522     IServiceProvider_fnRelease,
523     IServiceProvider_fnQueryService
524 };
525
526 static IServiceProviderImpl *create_serviceprovider(void)
527 {
528     IServiceProviderImpl *sp = HeapAlloc(GetProcessHeap(), 0, sizeof(IServiceProviderImpl));
529     sp->lpVtbl = &spvtbl;
530     sp->ref = 1;
531     return sp;
532 }
533
534 static void test_QueryInterface(void)
535 {
536     IExplorerBrowser *peb;
537     IUnknown *punk;
538     HRESULT hr;
539     LONG lres;
540
541     hr = ebrowser_instantiate(&peb);
542     ok(hr == S_OK, "Got 0x%08x\n", hr);
543
544 #define test_qinterface(iid, exp)                                       \
545     do {                                                                \
546         hr = IExplorerBrowser_QueryInterface(peb, &iid, (void**)&punk); \
547         ok(hr == exp, "(%s:)Expected (0x%08x), got (0x%08x)\n",         \
548            #iid, exp, hr);                                              \
549         if(SUCCEEDED(hr)) IUnknown_Release(punk);                       \
550     } while(0)
551
552     test_qinterface(IID_IUnknown, S_OK);
553     test_qinterface(IID_IExplorerBrowser, S_OK);
554     test_qinterface(IID_IShellBrowser, S_OK);
555     todo_wine test_qinterface(IID_IOleWindow, S_OK);
556     test_qinterface(IID_ICommDlgBrowser, S_OK);
557     test_qinterface(IID_ICommDlgBrowser2, S_OK);
558     test_qinterface(IID_ICommDlgBrowser3, S_OK);
559     todo_wine test_qinterface(IID_IServiceProvider, S_OK);
560     test_qinterface(IID_IObjectWithSite, S_OK);
561     todo_wine test_qinterface(IID_IConnectionPointContainer, S_OK);
562     test_qinterface(IID_IOleObject, E_NOINTERFACE);
563     test_qinterface(IID_IViewObject, E_NOINTERFACE);
564     test_qinterface(IID_IViewObject2, E_NOINTERFACE);
565     test_qinterface(IID_IViewObjectEx, E_NOINTERFACE);
566     test_qinterface(IID_IConnectionPoint, E_NOINTERFACE);
567     test_qinterface(IID_IShellView, E_NOINTERFACE);
568     test_qinterface(IID_INameSpaceTreeControlEvents, E_NOINTERFACE);
569
570 #undef test_qinterface
571
572     lres = IExplorerBrowser_Release(peb);
573     ok(lres == 0, "Got %d\n", lres);
574 }
575
576 static void test_SB_misc(void)
577 {
578     IExplorerBrowser *peb;
579     IShellBrowser *psb;
580     IUnknown *punk;
581     HRESULT hr;
582     HWND retHwnd;
583     LRESULT lres;
584     LONG ref;
585
586     ebrowser_instantiate(&peb);
587     hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
588     ok(hr == S_OK, "Got 0x%08x\n", hr);
589     if(FAILED(hr))
590     {
591         skip("Failed to get IShellBrowser interface.\n");
592         return;
593     }
594
595     /* Some unimplemented methods */
596     retHwnd = (HWND)0xDEADBEEF;
597     hr = IShellBrowser_GetControlWindow(psb, FCW_TOOLBAR, &retHwnd);
598     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
599     ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
600
601     hr = IShellBrowser_GetControlWindow(psb, FCW_STATUS, &retHwnd);
602     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
603     ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
604
605     hr = IShellBrowser_GetControlWindow(psb, FCW_TREE, &retHwnd);
606     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
607     ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
608
609     hr = IShellBrowser_GetControlWindow(psb, FCW_PROGRESS, &retHwnd);
610     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
611     ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
612
613     /* ::InsertMenuSB */
614     hr = IShellBrowser_InsertMenusSB(psb, NULL, NULL);
615     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
616
617     /* ::RemoveMenusSB */
618     hr = IShellBrowser_RemoveMenusSB(psb, NULL);
619     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
620
621     /* ::SetMenuSB */
622     hr = IShellBrowser_SetMenuSB(psb, NULL, NULL, NULL);
623     ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
624
625     /***** Before EB::Initialize *****/
626
627     /* ::GetWindow */
628     retHwnd = (HWND)0xDEADBEEF;
629     hr = IShellBrowser_GetWindow(psb, &retHwnd);
630     ok(hr == E_FAIL, "got (0x%08x)\n", hr);
631     ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
632
633     todo_wine
634     {
635
636         /* ::SendControlMsg */
637         lres = 0xDEADBEEF;
638         hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, &lres);
639         ok(hr == S_OK, "got (0x%08x)\n", hr);
640         ok(lres == 0, "lres was %ld\n", lres);
641
642         lres = 0xDEADBEEF;
643         hr = IShellBrowser_SendControlMsg(psb, FCW_TOOLBAR, TB_CHECKBUTTON,
644                                           FCIDM_TB_SMALLICON, TRUE, &lres);
645         ok(hr == S_OK, "got (0x%08x)\n", hr);
646         ok(lres == 0, "lres was %ld\n", lres);
647
648         hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, NULL);
649         ok(hr == S_OK, "got (0x%08x)\n", hr);
650
651         hr = IShellBrowser_SendControlMsg(psb, FCW_TREE, 0, 0, 0, NULL);
652         ok(hr == S_OK, "got (0x%08x)\n", hr);
653
654         hr = IShellBrowser_SendControlMsg(psb, FCW_PROGRESS, 0, 0, 0, NULL);
655         ok(hr == S_OK, "got (0x%08x)\n", hr);
656     }
657
658     /* ::QueryActiveShellView */
659     hr = IShellBrowser_QueryActiveShellView(psb, (IShellView**)&punk);
660     ok(hr == E_FAIL, "got (0x%08x)\n", hr);
661
662     /* Initialize ExplorerBrowser */
663     ebrowser_initialize(peb);
664
665     /***** After EB::Initialize *****/
666
667     /* ::GetWindow */
668     hr = IShellBrowser_GetWindow(psb, &retHwnd);
669     ok(hr == S_OK, "got (0x%08x)\n", hr);
670     ok(GetParent(retHwnd) == hwnd, "The HWND returned is not our child.\n");
671
672     todo_wine
673     {
674         /* ::SendControlMsg */
675         hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, NULL);
676         ok(hr == S_OK, "got (0x%08x)\n", hr);
677
678         lres = 0xDEADBEEF;
679         hr = IShellBrowser_SendControlMsg(psb, FCW_TOOLBAR, 0, 0, 0, &lres);
680         ok(hr == S_OK, "got (0x%08x)\n", hr);
681         ok(lres == 0, "lres was %ld\n", lres);
682
683         lres = 0xDEADBEEF;
684         hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, &lres);
685         ok(hr == S_OK, "got (0x%08x)\n", hr);
686         ok(lres == 0, "lres was %ld\n", lres);
687
688         lres = 0xDEADBEEF;
689         hr = IShellBrowser_SendControlMsg(psb, 1234, 0, 0, 0, &lres);
690         ok(hr == S_OK, "got (0x%08x)\n", hr);
691         ok(lres == 0, "lres was %ld\n", lres);
692
693         /* Returns S_OK */
694         hr = IShellBrowser_SetStatusTextSB(psb, NULL);
695         ok(hr == S_OK, "got (0x%08x)\n", hr);
696
697         hr = IShellBrowser_ContextSensitiveHelp(psb, FALSE);
698         ok(hr == S_OK, "got (0x%08x)\n", hr);
699
700         hr = IShellBrowser_EnableModelessSB(psb, TRUE);
701         ok(hr == S_OK, "got (0x%08x)\n", hr);
702
703         hr = IShellBrowser_SetToolbarItems(psb, NULL, 1, 1);
704         ok(hr == S_OK, "got (0x%08x)\n", hr);
705     }
706
707     hr = IShellBrowser_QueryActiveShellView(psb, (IShellView**)&punk);
708     ok(hr == E_FAIL, "got (0x%08x)\n", hr);
709
710     IShellBrowser_Release(psb);
711     IExplorerBrowser_Destroy(peb);
712     IExplorerBrowser_Release(peb);
713
714     /* Browse to the desktop. */
715     ebrowser_instantiate(&peb);
716     ebrowser_initialize(peb);
717     IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
718
719     process_msgs();
720     hr = ebrowser_browse_to_desktop(peb);
721     ok(hr == S_OK, "got (0x%08x)\n", hr);
722     process_msgs();
723
724     /****** After Browsing *****/
725
726     hr = IShellBrowser_QueryActiveShellView(psb, (IShellView**)&punk);
727     ok(hr == S_OK, "got (0x%08x)\n", hr);
728     if(SUCCEEDED(hr)) IUnknown_Release(punk);
729
730     IShellBrowser_Release(psb);
731     IExplorerBrowser_Destroy(peb);
732     ref = IExplorerBrowser_Release(peb);
733     ok(ref == 0, "Got %d\n", ref);
734 }
735
736 static void test_initialization(void)
737 {
738     IExplorerBrowser *peb;
739     IShellBrowser *psb;
740     HRESULT hr;
741     ULONG lres;
742     RECT rc;
743
744     ebrowser_instantiate(&peb);
745
746     if(0)
747     {
748         /* Crashes on Windows 7 */
749         hr = IExplorerBrowser_Initialize(peb, NULL, NULL, NULL);
750         hr = IExplorerBrowser_Initialize(peb, hwnd, NULL, NULL);
751     }
752
753     ZeroMemory(&rc, sizeof(RECT));
754
755     hr = IExplorerBrowser_Initialize(peb, NULL, &rc, NULL);
756     ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
757
758     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
759     ok(hr == S_OK, "got (0x%08x)\n", hr);
760
761     /* Initialize twice */
762     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
763     ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
764
765     hr = IExplorerBrowser_Destroy(peb);
766     ok(hr == S_OK, "got (0x%08x)\n", hr);
767
768     /* Initialize again */
769     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
770     ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
771
772     /* Destroy again */
773     hr = IExplorerBrowser_Destroy(peb);
774     ok(hr == S_OK, "got (0x%08x)\n", hr);
775     lres = IExplorerBrowser_Release(peb);
776     ok(lres == 0, "Got %d\n", lres);
777
778     /* Initialize with a few different rectangles */
779     peb = NULL;
780     ebrowser_instantiate(&peb);
781     rc.left = 50; rc.top = 20; rc.right = 100; rc.bottom = 80;
782     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
783     ok(hr == S_OK, "got (0x%08x)\n", hr);
784     hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
785     ok(hr == S_OK, "Got 0x%08x\n", hr);
786     if(SUCCEEDED(hr))
787     {
788         HWND eb_hwnd;
789         RECT eb_rc;
790         char buf[1024];
791         LONG style, expected_style;
792         static const RECT exp_rc = {0, 0, 48, 58};
793
794         hr = IShellBrowser_GetWindow(psb, &eb_hwnd);
795         ok(hr == S_OK, "Got 0x%08x\n", hr);
796
797         GetClientRect(eb_hwnd, &eb_rc);
798         ok(EqualRect(&eb_rc, &exp_rc), "Got client rect (%d, %d)-(%d, %d)\n",
799            eb_rc.left, eb_rc.top, eb_rc.right, eb_rc.bottom);
800
801         GetWindowRect(eb_hwnd, &eb_rc);
802         ok(eb_rc.right - eb_rc.left == 50, "Got window width %d\n", eb_rc.right - eb_rc.left);
803         ok(eb_rc.bottom - eb_rc.top == 60, "Got window height %d\n", eb_rc.bottom - eb_rc.top);
804
805         buf[0] = '\0';
806         GetClassNameA(eb_hwnd, buf, 1024);
807         ok(!lstrcmpA(buf, "ExplorerBrowserControl"), "Unexpected classname %s\n", buf);
808
809         expected_style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER;
810         style = GetWindowLongPtrW(eb_hwnd, GWL_STYLE);
811         todo_wine ok(style == expected_style, "Got style 0x%08x, expected 0x%08x\n", style, expected_style);
812
813         expected_style = WS_EX_CONTROLPARENT;
814         style = GetWindowLongPtrW(eb_hwnd, GWL_EXSTYLE);
815         ok(style == expected_style, "Got exstyle 0x%08x, expected 0x%08x\n", style, expected_style);
816
817         ok(GetParent(eb_hwnd) == hwnd, "GetParent returns %p\n", GetParent(eb_hwnd));
818
819         /* ::Destroy() destroys the window. */
820         ok(IsWindow(eb_hwnd), "eb_hwnd invalid.\n");
821         IExplorerBrowser_Destroy(peb);
822         ok(!IsWindow(eb_hwnd), "eb_hwnd valid.\n");
823
824         IShellBrowser_Release(psb);
825         lres = IExplorerBrowser_Release(peb);
826         ok(lres == 0, "Got refcount %d\n", lres);
827     }
828     else
829     {
830         skip("Skipping some tests.\n");
831
832         IExplorerBrowser_Destroy(peb);
833         lres = IExplorerBrowser_Release(peb);
834         ok(lres == 0, "Got refcount %d\n", lres);
835     }
836
837     ebrowser_instantiate(&peb);
838     rc.left = 0; rc.top = 0; rc.right = 0; rc.bottom = 0;
839     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
840     ok(hr == S_OK, "got (0x%08x)\n", hr);
841     IExplorerBrowser_Destroy(peb);
842     lres = IExplorerBrowser_Release(peb);
843     ok(lres == 0, "Got refcount %d\n", lres);
844
845     ebrowser_instantiate(&peb);
846     rc.left = -1; rc.top = -1; rc.right = 1; rc.bottom = 1;
847     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
848     ok(hr == S_OK, "got (0x%08x)\n", hr);
849     IExplorerBrowser_Destroy(peb);
850     lres = IExplorerBrowser_Release(peb);
851     ok(lres == 0, "Got refcount %d\n", lres);
852
853     ebrowser_instantiate(&peb);
854     rc.left = 10; rc.top = 10; rc.right = 5; rc.bottom = 5;
855     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
856     ok(hr == S_OK, "got (0x%08x)\n", hr);
857     IExplorerBrowser_Destroy(peb);
858     lres = IExplorerBrowser_Release(peb);
859     ok(lres == 0, "Got refcount %d\n", lres);
860
861     ebrowser_instantiate(&peb);
862     rc.left = 10; rc.top = 10; rc.right = 5; rc.bottom = 5;
863     hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
864     ok(hr == S_OK, "got (0x%08x)\n", hr);
865     IExplorerBrowser_Destroy(peb);
866     lres = IExplorerBrowser_Release(peb);
867     ok(lres == 0, "Got refcount %d\n", lres);
868 }
869
870 static void test_SetSite(void)
871 {
872     IExplorerBrowser *peb;
873     IServiceProviderImpl *spimpl = create_serviceprovider();
874     ICommDlgBrowser3Impl *cdbimpl = create_commdlgbrowser3();
875     IExplorerPaneVisibilityImpl *epvimpl = create_explorerpanevisibility();
876     IObjectWithSite *pow;
877     HRESULT hr;
878     LONG ref;
879     UINT i;
880     struct services expected[] = {
881         /* Win 7 */
882         { &SID_STopLevelBrowser,        &IID_ICommDlgBrowser2, 0, cdbimpl },
883         { &SID_STopLevelBrowser,        &IID_IShellBrowserService, 0, NULL },
884         { &SID_STopLevelBrowser,        &IID_IShellBrowser, 0, NULL },
885         { &SID_STopLevelBrowser,        &IID_UnknownInterface8, 0, NULL },
886         { &SID_STopLevelBrowser,        &IID_IConnectionPointContainer, 0, NULL },
887         { &SID_STopLevelBrowser,        &IID_IProfferService, 0, NULL },
888         { &SID_STopLevelBrowser,        &IID_UnknownInterface9, 0, NULL },
889         { &SID_ExplorerPaneVisibility,  &IID_IExplorerPaneVisibility, 0, epvimpl },
890         { &SID_SExplorerBrowserFrame,   &IID_ICommDlgBrowser2, 0, cdbimpl },
891         { &SID_SExplorerBrowserFrame,   &IID_ICommDlgBrowser3, 0, cdbimpl },
892         { &IID_IFileDialogPrivate,      &IID_IFileDialogPrivate, 0, NULL },
893         { &IID_IFileDialogPrivate,      &IID_IFileDialog, 0, NULL },
894         { &IID_IShellTaskScheduler,     &IID_IShellTaskScheduler, 0, NULL },
895         { &IID_IShellTaskScheduler,     &IID_UnknownInterface2, 0, NULL },
896         { &IID_IWebbrowserApp,          &IID_IConnectionPointContainer, 0, NULL },
897         { &IID_IFolderView,             &IID_IFolderView, 0, NULL },
898         { &IID_ILayoutModifier,         &IID_ILayoutModifier, 0, NULL },
899         { &IID_IBrowserSettings,        &IID_IBrowserSettings, 0, NULL },
900         { &CLSID_Desktop,               &IID_IUnknown, 0, NULL },
901         { &IID_UnknownInterface1,       &IID_UnknownInterface1, 0, NULL },
902         { &IID_UnknownInterface3,       &IID_UnknownInterface3, 0, NULL },
903         { &IID_UnknownInterface4,       &IID_IUnknown, 0, NULL },
904         { &IID_UnknownInterface6,       &IID_UnknownInterface7, 0, NULL },
905         { &IID_IBrowserWithActivationNotification, &IID_IBrowserWithActivationNotification, 0, NULL },
906
907         /* Other services requested in Vista, Windows 2008 but not in Windows 7 */
908         { &IID_IBrowserSettings_Vista,  &IID_IBrowserSettings_Vista, 0, NULL },
909         { &IID_IFolderTypeModifier,     &IID_IFolderTypeModifier, 0, NULL },
910         { &SID_STopLevelBrowser,        &IID_IShellBrowserService_Vista, 0, NULL },
911         { &IID_UnknownInterface5,       &IID_UnknownInterface5, 0, NULL },
912         { &IID_ICommDlgBrowser,         &IID_ICommDlgBrowser, 0, cdbimpl },
913         { &IID_IFileDialogPrivate_Vista,&IID_IFileDialogPrivate_Vista, 0, NULL},
914         { &IID_IFileDialogPrivate_Vista,&IID_IFileDialog, 0, NULL},
915         { &IID_UnknownInterface10,      &IID_IHTMLDocument2, 0, NULL},
916         { &SID_SMenuBandParent,         &IID_IOleCommandTarget, 0, NULL},
917         { &SID_SMenuBandParent,         &IID_IShellMenu, 0, NULL},
918         { &SID_STopLevelBrowser,        &IID_IOleWindow, 0, NULL},
919         { &SID_SMenuPopup,              &IID_IOleCommandTarget, 0, NULL},
920         { NULL }
921     };
922
923     ebrowser_instantiate(&peb);
924     IExplorerBrowser_SetOptions(peb, EBO_SHOWFRAMES);
925
926     hr = IExplorerBrowser_QueryInterface(peb, &IID_IObjectWithSite, (void**)&pow);
927     ok(hr == S_OK, "Got 0x%08x\n", hr);
928     if(SUCCEEDED(hr))
929     {
930         spimpl->interfaces = expected;
931
932         hr = IObjectWithSite_SetSite(pow, (IUnknown*)spimpl);
933         ok(hr == S_OK, "Got 0x%08x\n", hr);
934
935         if(FAILED(hr))
936             IObjectWithSite_Release(pow);
937     }
938
939     if(FAILED(hr))
940     {
941         skip("Failed to set site.\n");
942
943         IServiceProvider_Release((IServiceProvider*)spimpl);
944         ICommDlgBrowser3_Release((ICommDlgBrowser3*)cdbimpl);
945         IExplorerPaneVisibility_Release((IExplorerPaneVisibility*)epvimpl);
946         IExplorerBrowser_Destroy(peb);
947         ref = IExplorerBrowser_Release(peb);
948         ok(ref == 0, "Got ref %d\n", ref);
949
950         return;
951     }
952
953     ShowWindow(hwnd, TRUE);
954     ebrowser_initialize(peb);
955     ebrowser_browse_to_desktop(peb);
956
957     for(i = 0; i < 10; i++)
958     {
959         Sleep(100);
960         process_msgs();
961     }
962     ShowWindow(hwnd, FALSE);
963
964     /* ICommDlgBrowser3 */
965     ok(!cdbimpl->OnDefaultCommand, "Got %d\n", cdbimpl->OnDefaultCommand);
966     todo_wine ok(cdbimpl->OnStateChange, "Got %d\n", cdbimpl->OnStateChange);
967     ok(cdbimpl->IncludeObject, "Got %d\n", cdbimpl->IncludeObject);
968     ok(!cdbimpl->Notify, "Got %d\n", cdbimpl->Notify);
969     ok(!cdbimpl->GetDefaultMenuText, "Got %d\n", cdbimpl->GetDefaultMenuText);
970     todo_wine ok(cdbimpl->GetViewFlags, "Got %d\n", cdbimpl->GetViewFlags);
971     ok(!cdbimpl->OnColumnClicked, "Got %d\n", cdbimpl->OnColumnClicked);
972     ok(!cdbimpl->GetCurrentFilter, "Got %d\n", cdbimpl->GetCurrentFilter);
973     todo_wine ok(cdbimpl->OnPreviewCreated, "Got %d\n", cdbimpl->OnPreviewCreated);
974
975     /* IExplorerPaneVisibility */
976     todo_wine ok(epvimpl->np, "Got %d\n", epvimpl->np);
977     todo_wine ok(epvimpl->cp, "Got %d\n", epvimpl->cp);
978     todo_wine ok(epvimpl->cp_o, "Got %d\n", epvimpl->cp_o);
979     todo_wine ok(epvimpl->cp_v, "Got %d\n", epvimpl->cp_v);
980     todo_wine ok(epvimpl->dp, "Got %d\n", epvimpl->dp);
981     todo_wine ok(epvimpl->pp, "Got %d\n", epvimpl->pp);
982     ok(!epvimpl->qp, "Got %d\n", epvimpl->qp);
983     ok(!epvimpl->aqp, "Got %d\n", epvimpl->aqp);
984     ok(!epvimpl->unk, "Got %d\n", epvimpl->unk);
985
986     if(0)
987     {
988         for(i = 0; expected[i].service != NULL; i++)
989             if(!expected[i].count) trace("count %d was 0.\n", i);
990     }
991
992     /* Test when IServiceProvider is released. */
993     IServiceProvider_AddRef((IServiceProvider*)spimpl);
994     ref = IServiceProvider_Release((IServiceProvider*)spimpl);
995     ok(ref == 2, "Got ref %d\n", ref);
996
997     hr = IObjectWithSite_SetSite(pow, NULL);
998     ok(hr == S_OK, "Got 0x%08x\n", hr);
999
1000     IServiceProvider_AddRef((IServiceProvider*)spimpl);
1001     ref = IServiceProvider_Release((IServiceProvider*)spimpl);
1002     ok(ref == 1, "Got ref %d\n", ref);
1003
1004     hr = IObjectWithSite_SetSite(pow, (IUnknown*)spimpl);
1005     ok(hr == S_OK, "Got 0x%08x\n", hr);
1006
1007     IServiceProvider_AddRef((IServiceProvider*)spimpl);
1008     ref = IServiceProvider_Release((IServiceProvider*)spimpl);
1009     ok(ref == 2, "Got ref %d\n", ref);
1010
1011     IExplorerBrowser_Destroy(peb);
1012
1013     IServiceProvider_AddRef((IServiceProvider*)spimpl);
1014     ref = IServiceProvider_Release((IServiceProvider*)spimpl);
1015     ok(ref == 2, "Got ref %d\n", ref);
1016
1017     IObjectWithSite_Release(pow);
1018     ref = IExplorerBrowser_Release(peb);
1019     ok(ref == 0, "Got ref %d\n", ref);
1020
1021     ref = IServiceProvider_Release((IServiceProvider*)spimpl);
1022     ok(ref == 0, "Got ref %d\n", ref);
1023
1024     ref = ICommDlgBrowser3_Release((ICommDlgBrowser3*)cdbimpl);
1025     ok(ref == 0, "Got ref %d\n", ref);
1026     ref = IExplorerPaneVisibility_Release((IExplorerPaneVisibility*)epvimpl);
1027     ok(ref == 0, "Got ref %d\n", ref);
1028 }
1029
1030 static void test_basics(void)
1031 {
1032     IExplorerBrowser *peb;
1033     IShellBrowser *psb;
1034     FOLDERSETTINGS fs;
1035     ULONG lres;
1036     DWORD flags;
1037     HDWP hdwp;
1038     RECT rc;
1039     HRESULT hr;
1040
1041     ebrowser_instantiate(&peb);
1042     ebrowser_initialize(peb);
1043
1044     /* SetRect */
1045     rc.left = 0; rc.top = 0; rc.right = 0; rc.bottom = 0;
1046     hr = IExplorerBrowser_SetRect(peb, NULL, rc);
1047     ok(hr == S_OK, "got (0x%08x)\n", hr);
1048
1049     rc.left = 100; rc.top = 100; rc.right = 10; rc.bottom = 10;
1050     hr = IExplorerBrowser_SetRect(peb, NULL, rc);
1051     ok(hr == S_OK, "got (0x%08x)\n", hr);
1052
1053     /* SetRect with DeferWindowPos */
1054     rc.left = rc.top = 0; rc.right = rc.bottom = 10;
1055     hdwp = BeginDeferWindowPos(1);
1056     hr = IExplorerBrowser_SetRect(peb, &hdwp, rc);
1057     ok(hr == S_OK, "got (0x%08x)\n", hr);
1058     lres = EndDeferWindowPos(hdwp);
1059     ok(lres, "EndDeferWindowPos failed.\n");
1060
1061     hdwp = NULL;
1062     hr = IExplorerBrowser_SetRect(peb, &hdwp, rc);
1063     ok(hr == S_OK, "got (0x%08x)\n", hr);
1064     ok(hdwp == NULL, "got %p\n", hdwp);
1065     lres = EndDeferWindowPos(hdwp);
1066     ok(!lres, "EndDeferWindowPos succeeded unexpectedly.\n");
1067
1068     /* Test positioning */
1069     rc.left = 10; rc.top = 20; rc.right = 50; rc.bottom = 50;
1070     hr = IExplorerBrowser_SetRect(peb, NULL, rc);
1071     ok(hr == S_OK, "got (0x%08x)\n", hr);
1072     hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
1073     ok(hr == S_OK, "Got 0x%08x\n", hr);
1074     if(SUCCEEDED(hr))
1075     {
1076         HWND eb_hwnd;
1077         RECT eb_rc;
1078         static const RECT exp_rc = {11, 21, 49, 49};
1079
1080         hr = IShellBrowser_GetWindow(psb, &eb_hwnd);
1081         ok(hr == S_OK, "Got 0x%08x\n", hr);
1082
1083         GetClientRect(eb_hwnd, &eb_rc);
1084         MapWindowPoints(eb_hwnd, hwnd, (POINT*)&eb_rc, 2);
1085         ok(EqualRect(&eb_rc, &exp_rc), "Got rect (%d, %d) - (%d, %d)\n",
1086            eb_rc.left, eb_rc.top, eb_rc.right, eb_rc.bottom);
1087
1088         IShellBrowser_Release(psb);
1089     }
1090
1091     IExplorerBrowser_Destroy(peb);
1092     IExplorerBrowser_Release(peb);
1093
1094     /* GetOptions/SetOptions*/
1095     ebrowser_instantiate(&peb);
1096
1097     if(0) {
1098         /* Crashes on Windows 7 */
1099         IExplorerBrowser_GetOptions(peb, NULL);
1100     }
1101
1102     hr = IExplorerBrowser_GetOptions(peb, &flags);
1103     ok(hr == S_OK, "got (0x%08x)\n", hr);
1104     ok(flags == 0, "got (0x%08x)\n", flags);
1105
1106     /* Settings preserved through Initialize. */
1107     hr = IExplorerBrowser_SetOptions(peb, 0xDEADBEEF);
1108     ok(hr == S_OK, "got (0x%08x)\n", hr);
1109
1110     ebrowser_initialize(peb);
1111
1112     hr = IExplorerBrowser_GetOptions(peb, &flags);
1113     ok(flags == 0xDEADBEEF, "got (0x%08x)\n", flags);
1114     ok(hr == S_OK, "got (0x%08x)\n", hr);
1115
1116     IExplorerBrowser_Destroy(peb);
1117     IExplorerBrowser_Release(peb);
1118
1119     ebrowser_instantiate(&peb);
1120     ebrowser_initialize(peb);
1121
1122     /* SetFolderSettings */
1123     hr = IExplorerBrowser_SetFolderSettings(peb, NULL);
1124     ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
1125     fs.ViewMode = 0; fs.fFlags = 0;
1126     hr = IExplorerBrowser_SetFolderSettings(peb, &fs);
1127     todo_wine ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
1128
1129     /* TODO: Test after browsing somewhere. */
1130
1131     IExplorerBrowser_Destroy(peb);
1132     lres = IExplorerBrowser_Release(peb);
1133     ok(lres == 0, "Got %d\n", lres);
1134 }
1135
1136 static void test_Advise(void)
1137 {
1138     IExplorerBrowser *peb;
1139     IExplorerBrowserEvents *pebe;
1140     DWORD cookies[10];
1141     HRESULT hr;
1142     UINT i, ref;
1143
1144     /* Set up our IExplorerBrowserEvents implementation */
1145     ebev.lpVtbl = &ebevents;
1146     pebe = (IExplorerBrowserEvents*) &ebev;
1147
1148     ebrowser_instantiate(&peb);
1149
1150     if(0)
1151     {
1152         /* Crashes on Windows 7 */
1153         IExplorerBrowser_Advise(peb, pebe, NULL);
1154         IExplorerBrowser_Advise(peb, NULL, &cookies[0]);
1155     }
1156
1157     /* Using Unadvise with a cookie that has yet to be given out
1158      * results in E_INVALIDARG */
1159     hr = IExplorerBrowser_Unadvise(peb, 11);
1160     ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
1161
1162     /* Add some before initialization */
1163     for(i = 0; i < 5; i++)
1164     {
1165         hr = IExplorerBrowser_Advise(peb, pebe, &cookies[i]);
1166         ok(hr == S_OK, "got (0x%08x)\n", hr);
1167     }
1168
1169     ebrowser_initialize(peb);
1170
1171     /* Add some after initialization */
1172     for(i = 5; i < 10; i++)
1173     {
1174         hr = IExplorerBrowser_Advise(peb, pebe, &cookies[i]);
1175         ok(hr == S_OK, "got (0x%08x)\n", hr);
1176     }
1177
1178     ok(ebev.ref == 10, "Got %d\n", ebev.ref);
1179
1180     ebev.completed = 0;
1181     ebrowser_browse_to_desktop(peb);
1182     process_msgs();
1183     ok(ebev.completed == 10, "Got %d\n", ebev.completed);
1184
1185     /* Remove a bunch somewhere in the middle */
1186     for(i = 4; i < 8; i++)
1187     {
1188         hr = IExplorerBrowser_Unadvise(peb, cookies[i]);
1189         ok(hr == S_OK, "got (0x%08x)\n", hr);
1190     }
1191
1192     ebev.completed = 0;
1193     ebrowser_browse_to_desktop(peb);
1194     process_msgs();
1195     ok(ebev.completed == 6, "Got %d\n", ebev.completed);
1196
1197     if(0)
1198     {
1199         /* Using unadvise with a previously unadvised cookie results
1200          * in a crash. */
1201         hr = IExplorerBrowser_Unadvise(peb, cookies[5]);
1202     }
1203
1204     /* Remove the rest. */
1205     for(i = 0; i < 10; i++)
1206     {
1207         if(i<4||i>7)
1208         {
1209             hr = IExplorerBrowser_Unadvise(peb, cookies[i]);
1210             ok(hr == S_OK, "%d: got (0x%08x)\n", i, hr);
1211         }
1212     }
1213
1214     ok(ebev.ref == 0, "Got %d\n", ebev.ref);
1215
1216     ebev.completed = 0;
1217     ebrowser_browse_to_desktop(peb);
1218     process_msgs();
1219     ok(ebev.completed == 0, "Got %d\n", ebev.completed);
1220
1221     /* ::Destroy implies ::Unadvise. */
1222     hr = IExplorerBrowser_Advise(peb, pebe, &cookies[0]);
1223     ok(hr == S_OK, "Got 0x%08x\n", hr);
1224     ok(ebev.ref == 1, "Got %d\n", ebev.ref);
1225
1226     hr = IExplorerBrowser_Destroy(peb);
1227     ok(hr == S_OK, "Got 0x%08x\n", hr);
1228     ok(ebev.ref == 0, "Got %d\n", ebev.ref);
1229
1230     ref = IExplorerBrowser_Release(peb);
1231     ok(!ref, "Got %d\n", ref);
1232 }
1233
1234 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
1235 static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
1236 {
1237   size_t iLen;
1238
1239   if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH)
1240     return NULL;
1241
1242   if (iLen)
1243   {
1244     lpszPath += iLen;
1245     if (lpszPath[-1] != '\\')
1246     {
1247       *lpszPath++ = '\\';
1248       *lpszPath = '\0';
1249     }
1250   }
1251   return lpszPath;
1252 }
1253
1254 static void test_browse_pidl_(IExplorerBrowser *peb, IExplorerBrowserEventsImpl *ebev,
1255                               LPITEMIDLIST pidl, UINT uFlags,
1256                               HRESULT hr_exp, UINT pending, UINT created, UINT failed, UINT completed,
1257                               const char *file, int line)
1258 {
1259     HRESULT hr;
1260     ebev->completed = ebev->created = ebev->pending = ebev->failed = 0;
1261
1262     hr = IExplorerBrowser_BrowseToIDList(peb, pidl, uFlags);
1263     ok_(file, line) (hr == hr_exp, "BrowseToIDList returned 0x%08x\n", hr);
1264     process_msgs();
1265
1266     ok_(file, line)
1267         (ebev->pending == pending && ebev->created == created &&
1268          ebev->failed == failed && ebev->completed == completed,
1269          "Events occurred: %d, %d, %d, %d\n",
1270          ebev->pending, ebev->created, ebev->failed, ebev->completed);
1271 }
1272 #define test_browse_pidl(peb, ebev, pidl, uFlags, hr, p, cr, f, co)     \
1273     test_browse_pidl_(peb, ebev, pidl, uFlags, hr, p, cr, f, co, __FILE__, __LINE__)
1274
1275 static void test_browse_pidl_sb_(IExplorerBrowser *peb, IExplorerBrowserEventsImpl *ebev,
1276                                  LPITEMIDLIST pidl, UINT uFlags,
1277                                  HRESULT hr_exp, UINT pending, UINT created, UINT failed, UINT completed,
1278                                  const char *file, int line)
1279 {
1280     IShellBrowser *psb;
1281     HRESULT hr;
1282
1283     hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
1284     ok_(file, line) (hr == S_OK, "QueryInterface returned 0x%08x\n", hr);
1285     if(SUCCEEDED(hr))
1286     {
1287         ebev->completed = ebev->created = ebev->pending = ebev->failed = 0;
1288
1289         hr = IShellBrowser_BrowseObject(psb, pidl, uFlags);
1290         ok_(file, line) (hr == hr_exp, "BrowseObject returned 0x%08x\n", hr);
1291         process_msgs();
1292
1293         ok_(file, line)
1294             (ebev->pending == pending && ebev->created == created &&
1295              ebev->failed == failed && ebev->completed == completed,
1296              "Events occurred: %d, %d, %d, %d\n",
1297              ebev->pending, ebev->created, ebev->failed, ebev->completed);
1298
1299         IShellBrowser_Release(psb);
1300     }
1301 }
1302 #define test_browse_pidl_sb(peb, ebev, pidl, uFlags, hr, p, cr, f, co)  \
1303     test_browse_pidl_sb_(peb, ebev, pidl, uFlags, hr, p, cr, f, co, __FILE__, __LINE__)
1304
1305 static void test_navigation(void)
1306 {
1307     IExplorerBrowser *peb, *peb2;
1308     IFolderView *pfv;
1309     IShellItem *psi;
1310     IShellFolder *psf;
1311     LPITEMIDLIST pidl_current, pidl_child;
1312     DWORD cookie, cookie2;
1313     HRESULT hr;
1314     LONG lres;
1315     WCHAR current_path[MAX_PATH];
1316     WCHAR child_path[MAX_PATH];
1317     static const WCHAR testfolderW[] =
1318         {'w','i','n','e','t','e','s','t','f','o','l','d','e','r','\0'};
1319
1320     ok(pSHParseDisplayName != NULL, "pSHParseDisplayName unexpectedly missing.\n");
1321     ok(pSHCreateShellItem != NULL, "pSHCreateShellItem unexpectedly missing.\n");
1322
1323     GetCurrentDirectoryW(MAX_PATH, current_path);
1324     if(!lstrlenW(current_path))
1325     {
1326         skip("Failed to create test-directory.\n");
1327         return;
1328     }
1329
1330     lstrcpyW(child_path, current_path);
1331     myPathAddBackslashW(child_path);
1332     lstrcatW(child_path, testfolderW);
1333
1334     CreateDirectoryW(child_path, NULL);
1335
1336     pSHParseDisplayName(current_path, NULL, &pidl_current, 0, NULL);
1337     pSHParseDisplayName(child_path, NULL, &pidl_child, 0, NULL);
1338
1339     ebrowser_instantiate(&peb);
1340     ebrowser_initialize(peb);
1341
1342     ebrowser_instantiate(&peb2);
1343     ebrowser_initialize(peb2);
1344
1345     /* Set up our IExplorerBrowserEvents implementation */
1346     ebev.lpVtbl = &ebevents;
1347
1348     IExplorerBrowser_Advise(peb, (IExplorerBrowserEvents*)&ebev, &cookie);
1349     IExplorerBrowser_Advise(peb2, (IExplorerBrowserEvents*)&ebev, &cookie2);
1350
1351     /* These should all fail */
1352     test_browse_pidl(peb, &ebev, 0, SBSP_ABSOLUTE | SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1353     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_ABSOLUTE | SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1354     test_browse_pidl(peb, &ebev, 0, SBSP_ABSOLUTE, E_INVALIDARG, 0, 0, 0, 0);
1355     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_ABSOLUTE, E_INVALIDARG, 0, 0, 0, 0);
1356     test_browse_pidl(peb, &ebev, 0, SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1357     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1358     test_browse_pidl(peb, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
1359     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
1360     test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, E_FAIL, 0, 0, 0, 0);
1361     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, E_FAIL, 0, 0, 0, 0);
1362     test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, E_FAIL, 0, 0, 0, 0);
1363     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, E_FAIL, 0, 0, 0, 0);
1364
1365     /* "The first browse is synchronous" */
1366     test_browse_pidl(peb, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
1367     test_browse_pidl_sb(peb2, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
1368
1369     /* Navigate empty history */
1370     test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 0, 0, 0, 0);
1371     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 0, 0, 0, 0);
1372     test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 0, 0, 0, 0);
1373     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 0, 0, 0, 0);
1374
1375     /* Navigate history */
1376     test_browse_pidl(peb, &ebev, 0, SBSP_PARENT, S_OK, 1, 1, 0, 1);
1377     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_PARENT, S_OK, 1, 1, 0, 1);
1378     test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 1, 1, 0, 1);
1379     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 1, 1, 0, 1);
1380     test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 1, 1, 0, 1);
1381     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 1, 1, 0, 1);
1382     test_browse_pidl(peb, &ebev, 0, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1383     test_browse_pidl_sb(peb2, &ebev, 0, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1384
1385     /* Relative navigation */
1386     test_browse_pidl(peb, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 0, 0, 1);
1387     test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 0, 0, 1);
1388
1389     hr = IExplorerBrowser_GetCurrentView(peb, &IID_IFolderView, (void**)&pfv);
1390     ok(hr == S_OK, "Got 0x%08x\n", hr);
1391     if(SUCCEEDED(hr))
1392     {
1393         LPITEMIDLIST pidl_relative;
1394
1395         hr = IFolderView_GetFolder(pfv, &IID_IShellFolder, (void**)&psf);
1396         ok(hr == S_OK, "Got 0x%08x\n", hr);
1397         hr = IShellFolder_ParseDisplayName(psf, NULL, NULL, (LPWSTR)testfolderW,
1398                                            NULL, &pidl_relative, NULL);
1399         ok(hr == S_OK, "Got 0x%08x\n", hr);
1400
1401         /* Browsing to another location here before using the
1402          * pidl_relative would make ExplorerBrowser in Windows 7 show a
1403          * not-available dialog. Also, passing a relative pidl without
1404          * specifying SBSP_RELATIVE makes it look for the pidl on the
1405          * desktop
1406          */
1407
1408         test_browse_pidl(peb, &ebev, pidl_relative, SBSP_RELATIVE, S_OK, 1, 1, 0, 1);
1409         test_browse_pidl_sb(peb2, &ebev, pidl_relative, SBSP_RELATIVE, S_OK, 1, 1, 0, 1);
1410
1411         ILFree(pidl_relative);
1412         /* IShellFolder_Release(psf); */
1413         IFolderView_Release(pfv);
1414     }
1415
1416     /* misc **/
1417     test_browse_pidl(peb, &ebev, NULL, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1418     test_browse_pidl_sb(peb2, &ebev, NULL, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1419     test_browse_pidl(peb, &ebev, NULL, SBSP_DEFBROWSER, S_OK, 0, 0, 0, 0);
1420     test_browse_pidl_sb(peb2, &ebev, NULL, SBSP_DEFBROWSER, S_OK, 0, 0, 0, 0);
1421     test_browse_pidl(peb, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 1, 0, 1);
1422     test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 1, 0, 1);
1423     test_browse_pidl(peb, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 0, 0, 1);
1424     test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 0, 0, 1);
1425
1426     test_browse_pidl(peb, &ebev, pidl_current, SBSP_EXPLOREMODE, E_INVALIDARG, 0, 0, 0, 0);
1427     test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_EXPLOREMODE, E_INVALIDARG, 0, 0, 0, 0);
1428     test_browse_pidl(peb, &ebev, pidl_current, SBSP_OPENMODE, S_OK, 1, 0, 0, 1);
1429     test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_OPENMODE, S_OK, 1, 0, 0, 1);
1430
1431     /* SBSP_NEWBROWSER will return E_INVALIDARG, claims MSDN, but in
1432      * reality it works as one would expect (Windows 7 only?).
1433      */
1434     if(0)
1435     {
1436         IExplorerBrowser_BrowseToIDList(peb, NULL, SBSP_NEWBROWSER);
1437     }
1438
1439     hr = IExplorerBrowser_Unadvise(peb, cookie);
1440     ok(hr == S_OK, "Got 0x%08x\n", hr);
1441     IExplorerBrowser_Destroy(peb);
1442     process_msgs();
1443     hr = IExplorerBrowser_Unadvise(peb2, cookie2);
1444     ok(hr == S_OK, "Got 0x%08x\n", hr);
1445     IExplorerBrowser_Destroy(peb2);
1446     process_msgs();
1447
1448     /* Attempt browsing after destroyed */
1449     test_browse_pidl(peb, &ebev, pidl_child, SBSP_ABSOLUTE, HRESULT_FROM_WIN32(ERROR_BUSY), 0, 0, 0, 0);
1450     test_browse_pidl_sb(peb2, &ebev, pidl_child, SBSP_ABSOLUTE, HRESULT_FROM_WIN32(ERROR_BUSY), 0, 0, 0, 0);
1451
1452     lres = IExplorerBrowser_Release(peb);
1453     ok(lres == 0, "Got lres %d\n", lres);
1454     lres = IExplorerBrowser_Release(peb2);
1455     ok(lres == 0, "Got lres %d\n", lres);
1456
1457     /******************************************/
1458     /* Test some options that affect browsing */
1459
1460     ebrowser_instantiate(&peb);
1461     hr = IExplorerBrowser_Advise(peb, (IExplorerBrowserEvents*)&ebev, &cookie);
1462     ok(hr == S_OK, "Got 0x%08x\n", hr);
1463     hr = IExplorerBrowser_SetOptions(peb, EBO_NAVIGATEONCE);
1464     ok(hr == S_OK, "got (0x%08x)\n", hr);
1465     ebrowser_initialize(peb);
1466
1467     test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 1, 0, 1);
1468     test_browse_pidl(peb, &ebev, pidl_current, 0, E_FAIL, 0, 0, 0, 0);
1469
1470     hr = IExplorerBrowser_SetOptions(peb, 0);
1471     ok(hr == S_OK, "got (0x%08x)\n", hr);
1472
1473     test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1474     test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1475
1476     /* Difference in behavior lies where? */
1477     hr = IExplorerBrowser_SetOptions(peb, EBO_ALWAYSNAVIGATE);
1478     ok(hr == S_OK, "got (0x%08x)\n", hr);
1479
1480     test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1481     test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1482
1483     hr = IExplorerBrowser_Unadvise(peb, cookie);
1484     ok(hr == S_OK, "Got 0x%08x\n", hr);
1485
1486     IExplorerBrowser_Destroy(peb);
1487     lres = IExplorerBrowser_Release(peb);
1488     ok(lres == 0, "Got lres %d\n", lres);
1489
1490     /* BrowseToObject tests */
1491     ebrowser_instantiate(&peb);
1492     ebrowser_initialize(peb);
1493
1494     /* Browse to the desktop by passing an IShellFolder */
1495     hr = SHGetDesktopFolder(&psf);
1496     ok(hr == S_OK, "Got 0x%08x\n", hr);
1497     if(SUCCEEDED(hr))
1498     {
1499         hr = IExplorerBrowser_BrowseToObject(peb, (IUnknown*)psf, SBSP_DEFBROWSER);
1500         ok(hr == S_OK, "got (0x%08x)\n", hr);
1501         if(hr == S_OK) process_msgs();
1502
1503         IShellFolder_Release(psf);
1504     }
1505
1506     /* Browse to the current directory by passing a ShellItem */
1507     hr = pSHCreateShellItem(NULL, NULL, pidl_current, &psi);
1508     ok(hr == S_OK, "Got 0x%08x\n", hr);
1509     if(SUCCEEDED(hr))
1510     {
1511         hr = IExplorerBrowser_BrowseToObject(peb, (IUnknown*)psi, SBSP_DEFBROWSER);
1512         ok(hr == S_OK, "got (0x%08x)\n", hr);
1513         process_msgs();
1514
1515         IShellItem_Release(psi);
1516     }
1517
1518     IExplorerBrowser_Destroy(peb);
1519     lres = IExplorerBrowser_Release(peb);
1520     ok(lres == 0, "Got lres %d\n", lres);
1521
1522     /* Cleanup */
1523     RemoveDirectoryW(child_path);
1524     ILFree(pidl_current);
1525     ILFree(pidl_child);
1526 }
1527
1528 static void test_GetCurrentView(void)
1529 {
1530     IExplorerBrowser *peb;
1531     IUnknown *punk;
1532     HRESULT hr;
1533
1534     /* GetCurrentView */
1535     ebrowser_instantiate(&peb);
1536
1537     if(0)
1538     {
1539         /* Crashes under Windows 7 */
1540         hr = IExplorerBrowser_GetCurrentView(peb, NULL, NULL);
1541     }
1542     hr = IExplorerBrowser_GetCurrentView(peb, NULL, (void**)&punk);
1543     ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1544
1545 #define test_gcv(iid, exp)                                              \
1546     do {                                                                \
1547         hr = IExplorerBrowser_GetCurrentView(peb, &iid, (void**)&punk); \
1548         ok(hr == exp, "(%s:)Expected (0x%08x), got: (0x%08x)\n",        \
1549            #iid ,exp, hr);                                              \
1550         if(SUCCEEDED(hr)) IUnknown_Release(punk);                       \
1551     } while(0)
1552
1553     test_gcv(IID_IUnknown, E_FAIL);
1554     test_gcv(IID_IUnknown, E_FAIL);
1555     test_gcv(IID_IShellView, E_FAIL);
1556     test_gcv(IID_IShellView2, E_FAIL);
1557     test_gcv(IID_IFolderView, E_FAIL);
1558     test_gcv(IID_IPersistFolder, E_FAIL);
1559     test_gcv(IID_IPersistFolder2, E_FAIL);
1560     test_gcv(IID_ICommDlgBrowser, E_FAIL);
1561     test_gcv(IID_ICommDlgBrowser2, E_FAIL);
1562     test_gcv(IID_ICommDlgBrowser3, E_FAIL);
1563
1564     ebrowser_initialize(peb);
1565     ebrowser_browse_to_desktop(peb);
1566
1567     test_gcv(IID_IUnknown, S_OK);
1568     test_gcv(IID_IUnknown, S_OK);
1569     test_gcv(IID_IShellView, S_OK);
1570     test_gcv(IID_IShellView2, S_OK);
1571     test_gcv(IID_IFolderView, S_OK);
1572     todo_wine test_gcv(IID_IPersistFolder, S_OK);
1573     test_gcv(IID_IPersistFolder2, E_NOINTERFACE);
1574     test_gcv(IID_ICommDlgBrowser, E_NOINTERFACE);
1575     test_gcv(IID_ICommDlgBrowser2, E_NOINTERFACE);
1576     test_gcv(IID_ICommDlgBrowser3, E_NOINTERFACE);
1577
1578 #undef test_gcv
1579
1580     IExplorerBrowser_Destroy(peb);
1581     IExplorerBrowser_Release(peb);
1582 }
1583
1584 static BOOL test_instantiate_control(void)
1585 {
1586     IExplorerBrowser *peb;
1587     HRESULT hr;
1588
1589     hr = ebrowser_instantiate(&peb);
1590     ok(hr == S_OK || hr == REGDB_E_CLASSNOTREG, "Got (0x%08x)\n", hr);
1591     if(FAILED(hr))
1592         return FALSE;
1593
1594     IExplorerBrowser_Release(peb);
1595     return TRUE;
1596 }
1597
1598 static void setup_window(void)
1599 {
1600     WNDCLASSW wc;
1601     static const WCHAR ebtestW[] = {'e','b','t','e','s','t',0};
1602
1603     ZeroMemory(&wc, sizeof(WNDCLASSW));
1604     wc.lpfnWndProc      = DefWindowProcW;
1605     wc.lpszClassName    = ebtestW;
1606     RegisterClassW(&wc);
1607     hwnd = CreateWindowExW(0, ebtestW, NULL, 0,
1608                            0, 0, 500, 500,
1609                            NULL, 0, 0, NULL);
1610     ok(hwnd != NULL, "Failed to create window for tests.\n");
1611 }
1612
1613 START_TEST(ebrowser)
1614 {
1615     OleInitialize(NULL);
1616
1617     if(!test_instantiate_control())
1618     {
1619         win_skip("No ExplorerBrowser control..\n");
1620         OleUninitialize();
1621         return;
1622     }
1623
1624     setup_window();
1625     init_function_pointers();
1626
1627     test_QueryInterface();
1628     test_SB_misc();
1629     test_initialization();
1630     test_basics();
1631     test_Advise();
1632     test_navigation();
1633     test_GetCurrentView();
1634     test_SetSite();
1635
1636     DestroyWindow(hwnd);
1637     OleUninitialize();
1638 }