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