shell32: Add IObjectWithSite implementation to the ExplorerBrowser control.
[wine.git] / dlls / shell32 / tests / ebrowser.c
blobe98ced63cde0d6f731529eb93f5c1a3e6d22b0e7
1 /*
2 * Unit tests for the Explorer Browser control
4 * Copyright 2010 David Hedberg
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.
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.
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
21 #include <stdio.h>
23 #define COBJMACROS
25 #include "shlobj.h"
26 #include "shlwapi.h"
28 #include "wine/test.h"
30 #include "initguid.h"
31 #include "mshtml.h"
33 /**********************************************************************
34 * Some IID's for test_SetSite.
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);
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);
64 static HWND hwnd;
66 static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
67 static HRESULT (WINAPI *pSHParseDisplayName)(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*);
69 static void init_function_pointers(void)
71 HMODULE hmod;
73 hmod = GetModuleHandleA("shell32.dll");
74 pSHCreateShellItem = (void*)GetProcAddress(hmod, "SHCreateShellItem");
75 pSHParseDisplayName = (void*)GetProcAddress(hmod, "SHParseDisplayName");
78 /*********************************************************************
79 * Some simple helpers
81 static HRESULT ebrowser_instantiate(IExplorerBrowser **peb)
83 return CoCreateInstance(&CLSID_ExplorerBrowser, NULL, CLSCTX_INPROC_SERVER,
84 &IID_IExplorerBrowser, (void**)peb);
87 static HRESULT ebrowser_initialize(IExplorerBrowser *peb)
89 RECT rc;
90 rc.top = rc.left = 0; rc.bottom = rc.right = 500;
91 return IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
94 static HRESULT ebrowser_browse_to_desktop(IExplorerBrowser *peb)
96 LPITEMIDLIST pidl_desktop;
97 SHGetSpecialFolderLocation (hwnd, CSIDL_DESKTOP, &pidl_desktop);
98 return IExplorerBrowser_BrowseToIDList(peb, pidl_desktop, 0);
101 /* Process some messages */
102 static void process_msgs(void)
104 MSG msg;
105 while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
107 TranslateMessage(&msg);
108 DispatchMessage(&msg);
112 static void dbg_print_guid(const GUID *guid) {
113 WCHAR buf[MAX_PATH];
115 StringFromGUID2(guid, buf, MAX_PATH);
116 printf("guid:[%s]\n", wine_dbgstr_wn(buf, lstrlenW(buf)));
119 /*********************************************************************
120 * IExplorerBrowserEvents implementation
122 typedef struct {
123 const IExplorerBrowserEventsVtbl *lpVtbl;
124 LONG ref;
125 UINT pending, created, completed, failed;
126 } IExplorerBrowserEventsImpl;
128 static IExplorerBrowserEventsImpl ebev;
130 static HRESULT WINAPI IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents *iface,
131 REFIID riid, void **ppvObj)
133 ok(0, "Never called.\n");
134 return E_NOINTERFACE;
137 static ULONG WINAPI IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents *iface)
139 IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
140 return InterlockedIncrement(&This->ref);
143 static ULONG WINAPI IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents *iface)
145 IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
146 return InterlockedDecrement(&This->ref);
149 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents *iface,
150 PCIDLIST_ABSOLUTE pidlFolder)
152 IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
153 This->pending++;
154 return S_OK;
157 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents *iface,
158 PCIDLIST_ABSOLUTE pidlFolder)
160 IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
161 This->completed++;
162 return S_OK;
164 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents *iface,
165 PCIDLIST_ABSOLUTE pidlFolder)
167 IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
168 This->failed++;
169 return S_OK;
171 static HRESULT WINAPI IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents *iface,
172 IShellView *psv)
174 IExplorerBrowserEventsImpl *This = (IExplorerBrowserEventsImpl*)iface;
175 This->created++;
176 return S_OK;
179 static const IExplorerBrowserEventsVtbl ebevents =
181 IExplorerBrowserEvents_fnQueryInterface,
182 IExplorerBrowserEvents_fnAddRef,
183 IExplorerBrowserEvents_fnRelease,
184 IExplorerBrowserEvents_fnOnNavigationPending,
185 IExplorerBrowserEvents_fnOnViewCreated,
186 IExplorerBrowserEvents_fnOnNavigationComplete,
187 IExplorerBrowserEvents_fnOnNavigationFailed
190 /*********************************************************************
191 * IServiceProvider Implementation
193 typedef struct {
194 const IServiceProviderVtbl *lpVtbl;
195 LONG ref;
196 struct services {
197 REFGUID service;
198 REFIID id;
199 int count;
200 void *punk;
201 } *interfaces;
202 } IServiceProviderImpl;
204 static HRESULT WINAPI IServiceProvider_fnQueryInterface(IServiceProvider *iface, REFIID riid, LPVOID *ppvObj)
206 *ppvObj = NULL;
207 if(IsEqualIID(riid, &IID_IServiceProvider))
209 *ppvObj = iface;
210 IServiceProvider_AddRef((IServiceProvider*)iface);
211 return S_OK;
214 if(IsEqualIID(riid, &IID_IOleCommandTarget))
216 /* Windows Vista. */
217 return E_NOINTERFACE;
220 ok(0, "Unexpected interface requested.\n");
221 trace("riid: "); dbg_print_guid(riid);
222 return E_NOINTERFACE;
225 static ULONG WINAPI IServiceProvider_fnAddRef(IServiceProvider *iface)
227 IServiceProviderImpl *This = (IServiceProviderImpl*)iface;
228 return InterlockedIncrement(&This->ref);
231 static ULONG WINAPI IServiceProvider_fnRelease(IServiceProvider *iface)
233 IServiceProviderImpl *This = (IServiceProviderImpl*)iface;
234 LONG ref = InterlockedDecrement(&This->ref);
236 if(!ref)
237 HeapFree(GetProcessHeap(), 0, This);
239 return ref;
242 static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface,
243 REFGUID guidService,
244 REFIID riid,
245 void **ppv)
247 IServiceProviderImpl *This = (IServiceProviderImpl*)iface;
248 BOOL was_in_list = FALSE;
249 IUnknown *punk = NULL;
250 UINT i;
252 *ppv = NULL;
253 for(i = 0; This->interfaces[i].service != NULL; i++)
255 if(IsEqualGUID(This->interfaces[i].service, guidService) &&
256 IsEqualIID(This->interfaces[i].id, riid))
258 was_in_list = TRUE;
259 This->interfaces[i].count++;
260 punk = This->interfaces[i].punk;
261 break;
265 ok(was_in_list, "-- Unknown service requested --\n");
266 if(!was_in_list)
268 trace("guidService: "); dbg_print_guid(guidService);
269 trace("riid: "); dbg_print_guid(riid);
272 /* Give back an interface, if any. */
273 if(punk)
275 *ppv = punk;
276 IUnknown_AddRef((IUnknown*)punk);
277 return S_OK;
280 return E_NOINTERFACE;
283 static const IServiceProviderVtbl spvtbl =
285 IServiceProvider_fnQueryInterface,
286 IServiceProvider_fnAddRef,
287 IServiceProvider_fnRelease,
288 IServiceProvider_fnQueryService
291 static IServiceProviderImpl *create_serviceprovider(void)
293 IServiceProviderImpl *sp = HeapAlloc(GetProcessHeap(), 0, sizeof(IServiceProviderImpl));
294 sp->lpVtbl = &spvtbl;
295 sp->ref = 1;
296 return sp;
299 static void test_QueryInterface(void)
301 IExplorerBrowser *peb;
302 IUnknown *punk;
303 HRESULT hr;
304 LONG lres;
306 hr = ebrowser_instantiate(&peb);
307 ok(hr == S_OK, "Got 0x%08x\n", hr);
309 #define test_qinterface(iid, exp) \
310 do { \
311 hr = IExplorerBrowser_QueryInterface(peb, &iid, (void**)&punk); \
312 ok(hr == exp, "(%s:)Expected (0x%08x), got (0x%08x)\n", \
313 #iid, exp, hr); \
314 if(SUCCEEDED(hr)) IUnknown_Release(punk); \
315 } while(0)
317 test_qinterface(IID_IUnknown, S_OK);
318 test_qinterface(IID_IExplorerBrowser, S_OK);
319 test_qinterface(IID_IShellBrowser, S_OK);
320 todo_wine test_qinterface(IID_IOleWindow, S_OK);
321 test_qinterface(IID_ICommDlgBrowser, S_OK);
322 test_qinterface(IID_ICommDlgBrowser2, S_OK);
323 test_qinterface(IID_ICommDlgBrowser3, S_OK);
324 todo_wine test_qinterface(IID_IServiceProvider, S_OK);
325 test_qinterface(IID_IObjectWithSite, S_OK);
326 todo_wine test_qinterface(IID_IConnectionPointContainer, S_OK);
327 test_qinterface(IID_IOleObject, E_NOINTERFACE);
328 test_qinterface(IID_IViewObject, E_NOINTERFACE);
329 test_qinterface(IID_IViewObject2, E_NOINTERFACE);
330 test_qinterface(IID_IViewObjectEx, E_NOINTERFACE);
331 test_qinterface(IID_IConnectionPoint, E_NOINTERFACE);
332 test_qinterface(IID_IShellView, E_NOINTERFACE);
333 test_qinterface(IID_INameSpaceTreeControlEvents, E_NOINTERFACE);
335 #undef test_qinterface
337 lres = IExplorerBrowser_Release(peb);
338 ok(lres == 0, "Got %d\n", lres);
341 static void test_SB_misc(void)
343 IExplorerBrowser *peb;
344 IShellBrowser *psb;
345 IUnknown *punk;
346 HRESULT hr;
347 HWND retHwnd;
348 LRESULT lres;
349 LONG ref;
351 ebrowser_instantiate(&peb);
352 hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
353 ok(hr == S_OK, "Got 0x%08x\n", hr);
354 if(FAILED(hr))
356 skip("Failed to get IShellBrowser interface.\n");
357 return;
360 /* Some unimplemented methods */
361 retHwnd = (HWND)0xDEADBEEF;
362 hr = IShellBrowser_GetControlWindow(psb, FCW_TOOLBAR, &retHwnd);
363 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
364 ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
366 hr = IShellBrowser_GetControlWindow(psb, FCW_STATUS, &retHwnd);
367 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
368 ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
370 hr = IShellBrowser_GetControlWindow(psb, FCW_TREE, &retHwnd);
371 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
372 ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
374 hr = IShellBrowser_GetControlWindow(psb, FCW_PROGRESS, &retHwnd);
375 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
376 ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
378 /* ::InsertMenuSB */
379 hr = IShellBrowser_InsertMenusSB(psb, NULL, NULL);
380 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
382 /* ::RemoveMenusSB */
383 hr = IShellBrowser_RemoveMenusSB(psb, NULL);
384 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
386 /* ::SetMenuSB */
387 hr = IShellBrowser_SetMenuSB(psb, NULL, NULL, NULL);
388 ok(hr == E_NOTIMPL, "got (0x%08x)\n", hr);
390 /***** Before EB::Initialize *****/
392 /* ::GetWindow */
393 retHwnd = (HWND)0xDEADBEEF;
394 hr = IShellBrowser_GetWindow(psb, &retHwnd);
395 ok(hr == E_FAIL, "got (0x%08x)\n", hr);
396 ok(retHwnd == (HWND)0xDEADBEEF, "HWND overwritten\n");
398 todo_wine
401 /* ::SendControlMsg */
402 lres = 0xDEADBEEF;
403 hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, &lres);
404 ok(hr == S_OK, "got (0x%08x)\n", hr);
405 ok(lres == 0, "lres was %ld\n", lres);
407 lres = 0xDEADBEEF;
408 hr = IShellBrowser_SendControlMsg(psb, FCW_TOOLBAR, TB_CHECKBUTTON,
409 FCIDM_TB_SMALLICON, TRUE, &lres);
410 ok(hr == S_OK, "got (0x%08x)\n", hr);
411 ok(lres == 0, "lres was %ld\n", lres);
413 hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, NULL);
414 ok(hr == S_OK, "got (0x%08x)\n", hr);
416 hr = IShellBrowser_SendControlMsg(psb, FCW_TREE, 0, 0, 0, NULL);
417 ok(hr == S_OK, "got (0x%08x)\n", hr);
419 hr = IShellBrowser_SendControlMsg(psb, FCW_PROGRESS, 0, 0, 0, NULL);
420 ok(hr == S_OK, "got (0x%08x)\n", hr);
423 /* ::QueryActiveShellView */
424 hr = IShellBrowser_QueryActiveShellView(psb, (IShellView**)&punk);
425 ok(hr == E_FAIL, "got (0x%08x)\n", hr);
427 /* Initialize ExplorerBrowser */
428 ebrowser_initialize(peb);
430 /***** After EB::Initialize *****/
432 /* ::GetWindow */
433 hr = IShellBrowser_GetWindow(psb, &retHwnd);
434 ok(hr == S_OK, "got (0x%08x)\n", hr);
435 ok(GetParent(retHwnd) == hwnd, "The HWND returned is not our child.\n");
437 todo_wine
439 /* ::SendControlMsg */
440 hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, NULL);
441 ok(hr == S_OK, "got (0x%08x)\n", hr);
443 lres = 0xDEADBEEF;
444 hr = IShellBrowser_SendControlMsg(psb, FCW_TOOLBAR, 0, 0, 0, &lres);
445 ok(hr == S_OK, "got (0x%08x)\n", hr);
446 ok(lres == 0, "lres was %ld\n", lres);
448 lres = 0xDEADBEEF;
449 hr = IShellBrowser_SendControlMsg(psb, FCW_STATUS, 0, 0, 0, &lres);
450 ok(hr == S_OK, "got (0x%08x)\n", hr);
451 ok(lres == 0, "lres was %ld\n", lres);
453 lres = 0xDEADBEEF;
454 hr = IShellBrowser_SendControlMsg(psb, 1234, 0, 0, 0, &lres);
455 ok(hr == S_OK, "got (0x%08x)\n", hr);
456 ok(lres == 0, "lres was %ld\n", lres);
458 /* Returns S_OK */
459 hr = IShellBrowser_SetStatusTextSB(psb, NULL);
460 ok(hr == S_OK, "got (0x%08x)\n", hr);
462 hr = IShellBrowser_ContextSensitiveHelp(psb, FALSE);
463 ok(hr == S_OK, "got (0x%08x)\n", hr);
465 hr = IShellBrowser_EnableModelessSB(psb, TRUE);
466 ok(hr == S_OK, "got (0x%08x)\n", hr);
468 hr = IShellBrowser_SetToolbarItems(psb, NULL, 1, 1);
469 ok(hr == S_OK, "got (0x%08x)\n", hr);
472 hr = IShellBrowser_QueryActiveShellView(psb, (IShellView**)&punk);
473 ok(hr == E_FAIL, "got (0x%08x)\n", hr);
475 IShellBrowser_Release(psb);
476 IExplorerBrowser_Destroy(peb);
477 IExplorerBrowser_Release(peb);
479 /* Browse to the desktop. */
480 ebrowser_instantiate(&peb);
481 ebrowser_initialize(peb);
482 IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
484 process_msgs();
485 hr = ebrowser_browse_to_desktop(peb);
486 ok(hr == S_OK, "got (0x%08x)\n", hr);
487 process_msgs();
489 /****** After Browsing *****/
491 hr = IShellBrowser_QueryActiveShellView(psb, (IShellView**)&punk);
492 ok(hr == S_OK, "got (0x%08x)\n", hr);
493 if(SUCCEEDED(hr)) IUnknown_Release(punk);
495 IShellBrowser_Release(psb);
496 IExplorerBrowser_Destroy(peb);
497 ref = IExplorerBrowser_Release(peb);
498 ok(ref == 0, "Got %d\n", ref);
501 static void test_initialization(void)
503 IExplorerBrowser *peb;
504 IShellBrowser *psb;
505 HRESULT hr;
506 ULONG lres;
507 RECT rc;
509 ebrowser_instantiate(&peb);
511 if(0)
513 /* Crashes on Windows 7 */
514 hr = IExplorerBrowser_Initialize(peb, NULL, NULL, NULL);
515 hr = IExplorerBrowser_Initialize(peb, hwnd, NULL, NULL);
518 ZeroMemory(&rc, sizeof(RECT));
520 hr = IExplorerBrowser_Initialize(peb, NULL, &rc, NULL);
521 ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
523 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
524 ok(hr == S_OK, "got (0x%08x)\n", hr);
526 /* Initialize twice */
527 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
528 ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
530 hr = IExplorerBrowser_Destroy(peb);
531 ok(hr == S_OK, "got (0x%08x)\n", hr);
533 /* Initialize again */
534 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
535 ok(hr == E_UNEXPECTED, "got (0x%08x)\n", hr);
537 /* Destroy again */
538 hr = IExplorerBrowser_Destroy(peb);
539 ok(hr == S_OK, "got (0x%08x)\n", hr);
540 lres = IExplorerBrowser_Release(peb);
541 ok(lres == 0, "Got %d\n", lres);
543 /* Initialize with a few different rectangles */
544 peb = NULL;
545 ebrowser_instantiate(&peb);
546 rc.left = 50; rc.top = 20; rc.right = 100; rc.bottom = 80;
547 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
548 ok(hr == S_OK, "got (0x%08x)\n", hr);
549 hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
550 ok(hr == S_OK, "Got 0x%08x\n", hr);
551 if(SUCCEEDED(hr))
553 HWND eb_hwnd;
554 RECT eb_rc;
555 char buf[1024];
556 LONG style, expected_style;
557 static const RECT exp_rc = {0, 0, 48, 58};
559 hr = IShellBrowser_GetWindow(psb, &eb_hwnd);
560 ok(hr == S_OK, "Got 0x%08x\n", hr);
562 GetClientRect(eb_hwnd, &eb_rc);
563 ok(EqualRect(&eb_rc, &exp_rc), "Got client rect (%d, %d)-(%d, %d)\n",
564 eb_rc.left, eb_rc.top, eb_rc.right, eb_rc.bottom);
566 GetWindowRect(eb_hwnd, &eb_rc);
567 ok(eb_rc.right - eb_rc.left == 50, "Got window width %d\n", eb_rc.right - eb_rc.left);
568 ok(eb_rc.bottom - eb_rc.top == 60, "Got window height %d\n", eb_rc.bottom - eb_rc.top);
570 buf[0] = '\0';
571 GetClassNameA(eb_hwnd, buf, 1024);
572 ok(!lstrcmpA(buf, "ExplorerBrowserControl"), "Unexpected classname %s\n", buf);
574 expected_style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_BORDER;
575 style = GetWindowLongPtrW(eb_hwnd, GWL_STYLE);
576 todo_wine ok(style == expected_style, "Got style 0x%08x, expected 0x%08x\n", style, expected_style);
578 expected_style = WS_EX_CONTROLPARENT;
579 style = GetWindowLongPtrW(eb_hwnd, GWL_EXSTYLE);
580 ok(style == expected_style, "Got exstyle 0x%08x, expected 0x%08x\n", style, expected_style);
582 ok(GetParent(eb_hwnd) == hwnd, "GetParent returns %p\n", GetParent(eb_hwnd));
584 /* ::Destroy() destroys the window. */
585 ok(IsWindow(eb_hwnd), "eb_hwnd invalid.\n");
586 IExplorerBrowser_Destroy(peb);
587 ok(!IsWindow(eb_hwnd), "eb_hwnd valid.\n");
589 IShellBrowser_Release(psb);
590 lres = IExplorerBrowser_Release(peb);
591 ok(lres == 0, "Got refcount %d\n", lres);
593 else
595 skip("Skipping some tests.\n");
597 IExplorerBrowser_Destroy(peb);
598 lres = IExplorerBrowser_Release(peb);
599 ok(lres == 0, "Got refcount %d\n", lres);
602 ebrowser_instantiate(&peb);
603 rc.left = 0; rc.top = 0; rc.right = 0; rc.bottom = 0;
604 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
605 ok(hr == S_OK, "got (0x%08x)\n", hr);
606 IExplorerBrowser_Destroy(peb);
607 lres = IExplorerBrowser_Release(peb);
608 ok(lres == 0, "Got refcount %d\n", lres);
610 ebrowser_instantiate(&peb);
611 rc.left = -1; rc.top = -1; rc.right = 1; rc.bottom = 1;
612 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
613 ok(hr == S_OK, "got (0x%08x)\n", hr);
614 IExplorerBrowser_Destroy(peb);
615 lres = IExplorerBrowser_Release(peb);
616 ok(lres == 0, "Got refcount %d\n", lres);
618 ebrowser_instantiate(&peb);
619 rc.left = 10; rc.top = 10; rc.right = 5; rc.bottom = 5;
620 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
621 ok(hr == S_OK, "got (0x%08x)\n", hr);
622 IExplorerBrowser_Destroy(peb);
623 lres = IExplorerBrowser_Release(peb);
624 ok(lres == 0, "Got refcount %d\n", lres);
626 ebrowser_instantiate(&peb);
627 rc.left = 10; rc.top = 10; rc.right = 5; rc.bottom = 5;
628 hr = IExplorerBrowser_Initialize(peb, hwnd, &rc, NULL);
629 ok(hr == S_OK, "got (0x%08x)\n", hr);
630 IExplorerBrowser_Destroy(peb);
631 lres = IExplorerBrowser_Release(peb);
632 ok(lres == 0, "Got refcount %d\n", lres);
635 static void test_SetSite(void)
637 IExplorerBrowser *peb;
638 IServiceProviderImpl *spimpl = create_serviceprovider();
639 IObjectWithSite *pow;
640 HRESULT hr;
641 LONG ref;
642 UINT i;
643 struct services expected[] = {
644 /* Win 7 */
645 { &SID_STopLevelBrowser, &IID_ICommDlgBrowser2, 0, NULL },
646 { &SID_STopLevelBrowser, &IID_IShellBrowserService, 0, NULL },
647 { &SID_STopLevelBrowser, &IID_IShellBrowser, 0, NULL },
648 { &SID_STopLevelBrowser, &IID_UnknownInterface8, 0, NULL },
649 { &SID_STopLevelBrowser, &IID_IConnectionPointContainer, 0, NULL },
650 { &SID_STopLevelBrowser, &IID_IProfferService, 0, NULL },
651 { &SID_STopLevelBrowser, &IID_UnknownInterface9, 0, NULL },
652 { &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser2, 0, NULL },
653 { &SID_SExplorerBrowserFrame, &IID_ICommDlgBrowser3, 0, NULL },
654 { &SID_ExplorerPaneVisibility, &IID_IExplorerPaneVisibility, 0, NULL },
655 { &IID_IFileDialogPrivate, &IID_IFileDialogPrivate, 0, NULL },
656 { &IID_IFileDialogPrivate, &IID_IFileDialog, 0, NULL },
657 { &IID_IShellTaskScheduler, &IID_IShellTaskScheduler, 0, NULL },
658 { &IID_IShellTaskScheduler, &IID_UnknownInterface2, 0, NULL },
659 { &IID_IWebbrowserApp, &IID_IConnectionPointContainer, 0, NULL },
660 { &IID_IFolderView, &IID_IFolderView, 0, NULL },
661 { &IID_ILayoutModifier, &IID_ILayoutModifier, 0, NULL },
662 { &IID_IBrowserSettings, &IID_IBrowserSettings, 0, NULL },
663 { &CLSID_Desktop, &IID_IUnknown, 0, NULL },
664 { &IID_UnknownInterface1, &IID_UnknownInterface1, 0, NULL },
665 { &IID_UnknownInterface3, &IID_UnknownInterface3, 0, NULL },
666 { &IID_UnknownInterface4, &IID_IUnknown, 0, NULL },
667 { &IID_UnknownInterface6, &IID_UnknownInterface7, 0, NULL },
668 { &IID_IBrowserWithActivationNotification, &IID_IBrowserWithActivationNotification, 0, NULL },
670 /* Other services requested in Vista, Windows 2008 but not in Windows 7 */
671 { &IID_IBrowserSettings_Vista, &IID_IBrowserSettings_Vista, 0, NULL },
672 { &IID_IFolderTypeModifier, &IID_IFolderTypeModifier, 0, NULL },
673 { &SID_STopLevelBrowser, &IID_IShellBrowserService_Vista, 0, NULL },
674 { &IID_UnknownInterface5, &IID_UnknownInterface5, 0, NULL },
675 { &IID_ICommDlgBrowser, &IID_ICommDlgBrowser, 0, NULL },
676 { &IID_IFileDialogPrivate_Vista,&IID_IFileDialogPrivate_Vista, 0, NULL},
677 { &IID_IFileDialogPrivate_Vista,&IID_IFileDialog, 0, NULL},
678 { &IID_UnknownInterface10, &IID_IHTMLDocument2, 0, NULL},
679 { &SID_SMenuBandParent, &IID_IOleCommandTarget, 0, NULL},
680 { &SID_SMenuBandParent, &IID_IShellMenu, 0, NULL},
681 { &SID_STopLevelBrowser, &IID_IOleWindow, 0, NULL},
682 { &SID_SMenuPopup, &IID_IOleCommandTarget, 0, NULL},
683 { NULL }
686 ebrowser_instantiate(&peb);
687 IExplorerBrowser_SetOptions(peb, EBO_SHOWFRAMES);
689 hr = IExplorerBrowser_QueryInterface(peb, &IID_IObjectWithSite, (void**)&pow);
690 ok(hr == S_OK, "Got 0x%08x\n", hr);
691 if(SUCCEEDED(hr))
693 spimpl->interfaces = expected;
695 hr = IObjectWithSite_SetSite(pow, (IUnknown*)spimpl);
696 ok(hr == S_OK, "Got 0x%08x\n", hr);
698 if(FAILED(hr))
699 IObjectWithSite_Release(pow);
702 if(FAILED(hr))
704 skip("Failed to set site.\n");
706 IServiceProvider_Release((IServiceProvider*)spimpl);
707 IExplorerBrowser_Destroy(peb);
708 ref = IExplorerBrowser_Release(peb);
709 ok(ref == 0, "Got ref %d\n", ref);
711 return;
714 ShowWindow(hwnd, TRUE);
715 ebrowser_initialize(peb);
716 ebrowser_browse_to_desktop(peb);
718 for(i = 0; i < 10; i++)
720 Sleep(100);
721 process_msgs();
723 ShowWindow(hwnd, FALSE);
725 if(0)
727 for(i = 0; expected[i].service != NULL; i++)
728 if(!expected[i].count) trace("count %d was 0.\n", i);
731 /* Test when IServiceProvider is released. */
732 IServiceProvider_AddRef((IServiceProvider*)spimpl);
733 ref = IServiceProvider_Release((IServiceProvider*)spimpl);
734 ok(ref == 2, "Got ref %d\n", ref);
736 hr = IObjectWithSite_SetSite(pow, NULL);
737 ok(hr == S_OK, "Got 0x%08x\n", hr);
739 IServiceProvider_AddRef((IServiceProvider*)spimpl);
740 ref = IServiceProvider_Release((IServiceProvider*)spimpl);
741 ok(ref == 1, "Got ref %d\n", ref);
743 hr = IObjectWithSite_SetSite(pow, (IUnknown*)spimpl);
744 ok(hr == S_OK, "Got 0x%08x\n", hr);
746 IServiceProvider_AddRef((IServiceProvider*)spimpl);
747 ref = IServiceProvider_Release((IServiceProvider*)spimpl);
748 ok(ref == 2, "Got ref %d\n", ref);
750 IExplorerBrowser_Destroy(peb);
752 IServiceProvider_AddRef((IServiceProvider*)spimpl);
753 ref = IServiceProvider_Release((IServiceProvider*)spimpl);
754 ok(ref == 2, "Got ref %d\n", ref);
756 IObjectWithSite_Release(pow);
757 ref = IExplorerBrowser_Release(peb);
758 ok(ref == 0, "Got ref %d\n", ref);
760 ref = IServiceProvider_Release((IServiceProvider*)spimpl);
761 ok(ref == 0, "Got ref %d\n", ref);
764 static void test_basics(void)
766 IExplorerBrowser *peb;
767 IShellBrowser *psb;
768 FOLDERSETTINGS fs;
769 ULONG lres;
770 DWORD flags;
771 HDWP hdwp;
772 RECT rc;
773 HRESULT hr;
775 ebrowser_instantiate(&peb);
776 ebrowser_initialize(peb);
778 /* SetRect */
779 rc.left = 0; rc.top = 0; rc.right = 0; rc.bottom = 0;
780 hr = IExplorerBrowser_SetRect(peb, NULL, rc);
781 ok(hr == S_OK, "got (0x%08x)\n", hr);
783 rc.left = 100; rc.top = 100; rc.right = 10; rc.bottom = 10;
784 hr = IExplorerBrowser_SetRect(peb, NULL, rc);
785 ok(hr == S_OK, "got (0x%08x)\n", hr);
787 /* SetRect with DeferWindowPos */
788 rc.left = rc.top = 0; rc.right = rc.bottom = 10;
789 hdwp = BeginDeferWindowPos(1);
790 hr = IExplorerBrowser_SetRect(peb, &hdwp, rc);
791 ok(hr == S_OK, "got (0x%08x)\n", hr);
792 lres = EndDeferWindowPos(hdwp);
793 ok(lres, "EndDeferWindowPos failed.\n");
795 hdwp = NULL;
796 hr = IExplorerBrowser_SetRect(peb, &hdwp, rc);
797 ok(hr == S_OK, "got (0x%08x)\n", hr);
798 ok(hdwp == NULL, "got %p\n", hdwp);
799 lres = EndDeferWindowPos(hdwp);
800 ok(!lres, "EndDeferWindowPos succeeded unexpectedly.\n");
802 /* Test positioning */
803 rc.left = 10; rc.top = 20; rc.right = 50; rc.bottom = 50;
804 hr = IExplorerBrowser_SetRect(peb, NULL, rc);
805 ok(hr == S_OK, "got (0x%08x)\n", hr);
806 hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
807 ok(hr == S_OK, "Got 0x%08x\n", hr);
808 if(SUCCEEDED(hr))
810 HWND eb_hwnd;
811 RECT eb_rc;
812 static const RECT exp_rc = {11, 21, 49, 49};
814 hr = IShellBrowser_GetWindow(psb, &eb_hwnd);
815 ok(hr == S_OK, "Got 0x%08x\n", hr);
817 GetClientRect(eb_hwnd, &eb_rc);
818 MapWindowPoints(eb_hwnd, hwnd, (POINT*)&eb_rc, 2);
819 ok(EqualRect(&eb_rc, &exp_rc), "Got rect (%d, %d) - (%d, %d)\n",
820 eb_rc.left, eb_rc.top, eb_rc.right, eb_rc.bottom);
822 IShellBrowser_Release(psb);
825 IExplorerBrowser_Destroy(peb);
826 IExplorerBrowser_Release(peb);
828 /* GetOptions/SetOptions*/
829 ebrowser_instantiate(&peb);
831 if(0) {
832 /* Crashes on Windows 7 */
833 IExplorerBrowser_GetOptions(peb, NULL);
836 hr = IExplorerBrowser_GetOptions(peb, &flags);
837 ok(hr == S_OK, "got (0x%08x)\n", hr);
838 ok(flags == 0, "got (0x%08x)\n", flags);
840 /* Settings preserved through Initialize. */
841 hr = IExplorerBrowser_SetOptions(peb, 0xDEADBEEF);
842 ok(hr == S_OK, "got (0x%08x)\n", hr);
844 ebrowser_initialize(peb);
846 hr = IExplorerBrowser_GetOptions(peb, &flags);
847 ok(flags == 0xDEADBEEF, "got (0x%08x)\n", flags);
848 ok(hr == S_OK, "got (0x%08x)\n", hr);
850 IExplorerBrowser_Destroy(peb);
851 IExplorerBrowser_Release(peb);
853 ebrowser_instantiate(&peb);
854 ebrowser_initialize(peb);
856 /* SetFolderSettings */
857 hr = IExplorerBrowser_SetFolderSettings(peb, NULL);
858 ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
859 fs.ViewMode = 0; fs.fFlags = 0;
860 hr = IExplorerBrowser_SetFolderSettings(peb, &fs);
861 todo_wine ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
863 /* TODO: Test after browsing somewhere. */
865 IExplorerBrowser_Destroy(peb);
866 lres = IExplorerBrowser_Release(peb);
867 ok(lres == 0, "Got %d\n", lres);
870 static void test_Advise(void)
872 IExplorerBrowser *peb;
873 IExplorerBrowserEvents *pebe;
874 DWORD cookies[10];
875 HRESULT hr;
876 UINT i, ref;
878 /* Set up our IExplorerBrowserEvents implementation */
879 ebev.lpVtbl = &ebevents;
880 pebe = (IExplorerBrowserEvents*) &ebev;
882 ebrowser_instantiate(&peb);
884 if(0)
886 /* Crashes on Windows 7 */
887 IExplorerBrowser_Advise(peb, pebe, NULL);
888 IExplorerBrowser_Advise(peb, NULL, &cookies[0]);
891 /* Using Unadvise with a cookie that has yet to be given out
892 * results in E_INVALIDARG */
893 hr = IExplorerBrowser_Unadvise(peb, 11);
894 ok(hr == E_INVALIDARG, "got (0x%08x)\n", hr);
896 /* Add some before initialization */
897 for(i = 0; i < 5; i++)
899 hr = IExplorerBrowser_Advise(peb, pebe, &cookies[i]);
900 ok(hr == S_OK, "got (0x%08x)\n", hr);
903 ebrowser_initialize(peb);
905 /* Add some after initialization */
906 for(i = 5; i < 10; i++)
908 hr = IExplorerBrowser_Advise(peb, pebe, &cookies[i]);
909 ok(hr == S_OK, "got (0x%08x)\n", hr);
912 ok(ebev.ref == 10, "Got %d\n", ebev.ref);
914 ebev.completed = 0;
915 ebrowser_browse_to_desktop(peb);
916 process_msgs();
917 ok(ebev.completed == 10, "Got %d\n", ebev.completed);
919 /* Remove a bunch somewhere in the middle */
920 for(i = 4; i < 8; i++)
922 hr = IExplorerBrowser_Unadvise(peb, cookies[i]);
923 ok(hr == S_OK, "got (0x%08x)\n", hr);
926 ebev.completed = 0;
927 ebrowser_browse_to_desktop(peb);
928 process_msgs();
929 ok(ebev.completed == 6, "Got %d\n", ebev.completed);
931 if(0)
933 /* Using unadvise with a previously unadvised cookie results
934 * in a crash. */
935 hr = IExplorerBrowser_Unadvise(peb, cookies[5]);
938 /* Remove the rest. */
939 for(i = 0; i < 10; i++)
941 if(i<4||i>7)
943 hr = IExplorerBrowser_Unadvise(peb, cookies[i]);
944 ok(hr == S_OK, "%d: got (0x%08x)\n", i, hr);
948 ok(ebev.ref == 0, "Got %d\n", ebev.ref);
950 ebev.completed = 0;
951 ebrowser_browse_to_desktop(peb);
952 process_msgs();
953 ok(ebev.completed == 0, "Got %d\n", ebev.completed);
955 /* ::Destroy implies ::Unadvise. */
956 hr = IExplorerBrowser_Advise(peb, pebe, &cookies[0]);
957 ok(hr == S_OK, "Got 0x%08x\n", hr);
958 ok(ebev.ref == 1, "Got %d\n", ebev.ref);
960 hr = IExplorerBrowser_Destroy(peb);
961 ok(hr == S_OK, "Got 0x%08x\n", hr);
962 ok(ebev.ref == 0, "Got %d\n", ebev.ref);
964 ref = IExplorerBrowser_Release(peb);
965 ok(!ref, "Got %d", ref);
968 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
969 static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
971 size_t iLen;
973 if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH)
974 return NULL;
976 if (iLen)
978 lpszPath += iLen;
979 if (lpszPath[-1] != '\\')
981 *lpszPath++ = '\\';
982 *lpszPath = '\0';
985 return lpszPath;
988 static void test_browse_pidl_(IExplorerBrowser *peb, IExplorerBrowserEventsImpl *ebev,
989 LPITEMIDLIST pidl, UINT uFlags,
990 HRESULT hr_exp, UINT pending, UINT created, UINT failed, UINT completed,
991 const char *file, int line)
993 HRESULT hr;
994 ebev->completed = ebev->created = ebev->pending = ebev->failed = 0;
996 hr = IExplorerBrowser_BrowseToIDList(peb, pidl, uFlags);
997 ok_(file, line) (hr == hr_exp, "BrowseToIDList returned 0x%08x\n", hr);
998 process_msgs();
1000 ok_(file, line)
1001 (ebev->pending == pending && ebev->created == created &&
1002 ebev->failed == failed && ebev->completed == completed,
1003 "Events occurred: %d, %d, %d, %d\n",
1004 ebev->pending, ebev->created, ebev->failed, ebev->completed);
1006 #define test_browse_pidl(peb, ebev, pidl, uFlags, hr, p, cr, f, co) \
1007 test_browse_pidl_(peb, ebev, pidl, uFlags, hr, p, cr, f, co, __FILE__, __LINE__)
1009 static void test_browse_pidl_sb_(IExplorerBrowser *peb, IExplorerBrowserEventsImpl *ebev,
1010 LPITEMIDLIST pidl, UINT uFlags,
1011 HRESULT hr_exp, UINT pending, UINT created, UINT failed, UINT completed,
1012 const char *file, int line)
1014 IShellBrowser *psb;
1015 HRESULT hr;
1017 hr = IExplorerBrowser_QueryInterface(peb, &IID_IShellBrowser, (void**)&psb);
1018 ok_(file, line) (hr == S_OK, "QueryInterface returned 0x%08x\n", hr);
1019 if(SUCCEEDED(hr))
1021 ebev->completed = ebev->created = ebev->pending = ebev->failed = 0;
1023 hr = IShellBrowser_BrowseObject(psb, pidl, uFlags);
1024 ok_(file, line) (hr == hr_exp, "BrowseObject returned 0x%08x\n", hr);
1025 process_msgs();
1027 ok_(file, line)
1028 (ebev->pending == pending && ebev->created == created &&
1029 ebev->failed == failed && ebev->completed == completed,
1030 "Events occurred: %d, %d, %d, %d\n",
1031 ebev->pending, ebev->created, ebev->failed, ebev->completed);
1033 IShellBrowser_Release(psb);
1036 #define test_browse_pidl_sb(peb, ebev, pidl, uFlags, hr, p, cr, f, co) \
1037 test_browse_pidl_sb_(peb, ebev, pidl, uFlags, hr, p, cr, f, co, __FILE__, __LINE__)
1039 static void test_navigation(void)
1041 IExplorerBrowser *peb, *peb2;
1042 IFolderView *pfv;
1043 IShellItem *psi;
1044 IShellFolder *psf;
1045 LPITEMIDLIST pidl_current, pidl_child;
1046 DWORD cookie, cookie2;
1047 HRESULT hr;
1048 LONG lres;
1049 WCHAR current_path[MAX_PATH];
1050 WCHAR child_path[MAX_PATH];
1051 static const WCHAR testfolderW[] =
1052 {'w','i','n','e','t','e','s','t','f','o','l','d','e','r','\0'};
1054 ok(pSHParseDisplayName != NULL, "pSHParseDisplayName unexpectedly missing.\n");
1055 ok(pSHCreateShellItem != NULL, "pSHCreateShellItem unexpectedly missing.\n");
1057 GetCurrentDirectoryW(MAX_PATH, current_path);
1058 if(!lstrlenW(current_path))
1060 skip("Failed to create test-directory.\n");
1061 return;
1064 lstrcpyW(child_path, current_path);
1065 myPathAddBackslashW(child_path);
1066 lstrcatW(child_path, testfolderW);
1068 CreateDirectoryW(child_path, NULL);
1070 pSHParseDisplayName(current_path, NULL, &pidl_current, 0, NULL);
1071 pSHParseDisplayName(child_path, NULL, &pidl_child, 0, NULL);
1073 ebrowser_instantiate(&peb);
1074 ebrowser_initialize(peb);
1076 ebrowser_instantiate(&peb2);
1077 ebrowser_initialize(peb2);
1079 /* Set up our IExplorerBrowserEvents implementation */
1080 ebev.lpVtbl = &ebevents;
1082 IExplorerBrowser_Advise(peb, (IExplorerBrowserEvents*)&ebev, &cookie);
1083 IExplorerBrowser_Advise(peb2, (IExplorerBrowserEvents*)&ebev, &cookie2);
1085 /* These should all fail */
1086 test_browse_pidl(peb, &ebev, 0, SBSP_ABSOLUTE | SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1087 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_ABSOLUTE | SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1088 test_browse_pidl(peb, &ebev, 0, SBSP_ABSOLUTE, E_INVALIDARG, 0, 0, 0, 0);
1089 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_ABSOLUTE, E_INVALIDARG, 0, 0, 0, 0);
1090 test_browse_pidl(peb, &ebev, 0, SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1091 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_RELATIVE, E_FAIL, 0, 0, 0, 0);
1092 test_browse_pidl(peb, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
1093 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_PARENT, E_FAIL, 0, 0, 0, 0);
1094 test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, E_FAIL, 0, 0, 0, 0);
1095 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, E_FAIL, 0, 0, 0, 0);
1096 test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, E_FAIL, 0, 0, 0, 0);
1097 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, E_FAIL, 0, 0, 0, 0);
1099 /* "The first browse is synchronous" */
1100 test_browse_pidl(peb, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
1101 test_browse_pidl_sb(peb2, &ebev, pidl_child, SBSP_ABSOLUTE, S_OK, 1, 1, 0, 1);
1103 /* Navigate empty history */
1104 test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 0, 0, 0, 0);
1105 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 0, 0, 0, 0);
1106 test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 0, 0, 0, 0);
1107 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 0, 0, 0, 0);
1109 /* Navigate history */
1110 test_browse_pidl(peb, &ebev, 0, SBSP_PARENT, S_OK, 1, 1, 0, 1);
1111 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_PARENT, S_OK, 1, 1, 0, 1);
1112 test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 1, 1, 0, 1);
1113 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEBACK, S_OK, 1, 1, 0, 1);
1114 test_browse_pidl(peb, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 1, 1, 0, 1);
1115 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_NAVIGATEFORWARD, S_OK, 1, 1, 0, 1);
1116 test_browse_pidl(peb, &ebev, 0, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1117 test_browse_pidl_sb(peb2, &ebev, 0, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1119 /* Relative navigation */
1120 test_browse_pidl(peb, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 0, 0, 1);
1121 test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_ABSOLUTE, S_OK, 1, 0, 0, 1);
1123 hr = IExplorerBrowser_GetCurrentView(peb, &IID_IFolderView, (void**)&pfv);
1124 ok(hr == S_OK, "Got 0x%08x\n", hr);
1125 if(SUCCEEDED(hr))
1127 LPITEMIDLIST pidl_relative;
1129 hr = IFolderView_GetFolder(pfv, &IID_IShellFolder, (void**)&psf);
1130 ok(hr == S_OK, "Got 0x%08x\n", hr);
1131 hr = IShellFolder_ParseDisplayName(psf, NULL, NULL, (LPWSTR)testfolderW,
1132 NULL, &pidl_relative, NULL);
1133 ok(hr == S_OK, "Got 0x%08x\n", hr);
1135 /* Browsing to another location here before using the
1136 * pidl_relative would make ExplorerBrowser in Windows 7 show a
1137 * not-available dialog. Also, passing a relative pidl without
1138 * specifying SBSP_RELATIVE makes it look for the pidl on the
1139 * desktop
1142 test_browse_pidl(peb, &ebev, pidl_relative, SBSP_RELATIVE, S_OK, 1, 1, 0, 1);
1143 test_browse_pidl_sb(peb2, &ebev, pidl_relative, SBSP_RELATIVE, S_OK, 1, 1, 0, 1);
1145 ILFree(pidl_relative);
1146 /* IShellFolder_Release(psf); */
1147 IFolderView_Release(pfv);
1150 /* misc **/
1151 test_browse_pidl(peb, &ebev, NULL, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1152 test_browse_pidl_sb(peb2, &ebev, NULL, SBSP_ABSOLUTE, S_OK, 0, 0, 0, 0);
1153 test_browse_pidl(peb, &ebev, NULL, SBSP_DEFBROWSER, S_OK, 0, 0, 0, 0);
1154 test_browse_pidl_sb(peb2, &ebev, NULL, SBSP_DEFBROWSER, S_OK, 0, 0, 0, 0);
1155 test_browse_pidl(peb, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 1, 0, 1);
1156 test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 1, 0, 1);
1157 test_browse_pidl(peb, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 0, 0, 1);
1158 test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_SAMEBROWSER, S_OK, 1, 0, 0, 1);
1160 test_browse_pidl(peb, &ebev, pidl_current, SBSP_EXPLOREMODE, E_INVALIDARG, 0, 0, 0, 0);
1161 test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_EXPLOREMODE, E_INVALIDARG, 0, 0, 0, 0);
1162 test_browse_pidl(peb, &ebev, pidl_current, SBSP_OPENMODE, S_OK, 1, 0, 0, 1);
1163 test_browse_pidl_sb(peb2, &ebev, pidl_current, SBSP_OPENMODE, S_OK, 1, 0, 0, 1);
1165 /* SBSP_NEWBROWSER will return E_INVALIDARG, claims MSDN, but in
1166 * reality it works as one would expect (Windows 7 only?).
1168 if(0)
1170 IExplorerBrowser_BrowseToIDList(peb, NULL, SBSP_NEWBROWSER);
1173 hr = IExplorerBrowser_Unadvise(peb, cookie);
1174 ok(hr == S_OK, "Got 0x%08x\n", hr);
1175 IExplorerBrowser_Destroy(peb);
1176 process_msgs();
1177 hr = IExplorerBrowser_Unadvise(peb2, cookie2);
1178 ok(hr == S_OK, "Got 0x%08x\n", hr);
1179 IExplorerBrowser_Destroy(peb2);
1180 process_msgs();
1182 /* Attempt browsing after destroyed */
1183 test_browse_pidl(peb, &ebev, pidl_child, SBSP_ABSOLUTE, HRESULT_FROM_WIN32(ERROR_BUSY), 0, 0, 0, 0);
1184 test_browse_pidl_sb(peb2, &ebev, pidl_child, SBSP_ABSOLUTE, HRESULT_FROM_WIN32(ERROR_BUSY), 0, 0, 0, 0);
1186 lres = IExplorerBrowser_Release(peb);
1187 ok(lres == 0, "Got lres %d\n", lres);
1188 lres = IExplorerBrowser_Release(peb2);
1189 ok(lres == 0, "Got lres %d\n", lres);
1191 /******************************************/
1192 /* Test some options that affect browsing */
1194 ebrowser_instantiate(&peb);
1195 hr = IExplorerBrowser_Advise(peb, (IExplorerBrowserEvents*)&ebev, &cookie);
1196 ok(hr == S_OK, "Got 0x%08x\n", hr);
1197 hr = IExplorerBrowser_SetOptions(peb, EBO_NAVIGATEONCE);
1198 ok(hr == S_OK, "got (0x%08x)\n", hr);
1199 ebrowser_initialize(peb);
1201 test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 1, 0, 1);
1202 test_browse_pidl(peb, &ebev, pidl_current, 0, E_FAIL, 0, 0, 0, 0);
1204 hr = IExplorerBrowser_SetOptions(peb, 0);
1205 ok(hr == S_OK, "got (0x%08x)\n", hr);
1207 test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1208 test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1210 /* Difference in behavior lies where? */
1211 hr = IExplorerBrowser_SetOptions(peb, EBO_ALWAYSNAVIGATE);
1212 ok(hr == S_OK, "got (0x%08x)\n", hr);
1214 test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1215 test_browse_pidl(peb, &ebev, pidl_current, 0, S_OK, 1, 0, 0, 1);
1217 hr = IExplorerBrowser_Unadvise(peb, cookie);
1218 ok(hr == S_OK, "Got 0x%08x\n", hr);
1220 IExplorerBrowser_Destroy(peb);
1221 lres = IExplorerBrowser_Release(peb);
1222 ok(lres == 0, "Got lres %d\n", lres);
1224 /* BrowseToObject tests */
1225 ebrowser_instantiate(&peb);
1226 ebrowser_initialize(peb);
1228 /* Browse to the desktop by passing an IShellFolder */
1229 hr = SHGetDesktopFolder(&psf);
1230 ok(hr == S_OK, "Got 0x%08x\n", hr);
1231 if(SUCCEEDED(hr))
1233 hr = IExplorerBrowser_BrowseToObject(peb, (IUnknown*)psf, SBSP_DEFBROWSER);
1234 ok(hr == S_OK, "got (0x%08x)\n", hr);
1235 if(hr == S_OK) process_msgs();
1237 IShellFolder_Release(psf);
1240 /* Browse to the current directory by passing a ShellItem */
1241 hr = pSHCreateShellItem(NULL, NULL, pidl_current, &psi);
1242 ok(hr == S_OK, "Got 0x%08x\n", hr);
1243 if(SUCCEEDED(hr))
1245 hr = IExplorerBrowser_BrowseToObject(peb, (IUnknown*)psi, SBSP_DEFBROWSER);
1246 ok(hr == S_OK, "got (0x%08x)\n", hr);
1247 process_msgs();
1249 IShellItem_Release(psi);
1252 IExplorerBrowser_Destroy(peb);
1253 lres = IExplorerBrowser_Release(peb);
1254 ok(lres == 0, "Got lres %d\n", lres);
1256 /* Cleanup */
1257 RemoveDirectoryW(child_path);
1258 ILFree(pidl_current);
1259 ILFree(pidl_child);
1262 static void test_GetCurrentView(void)
1264 IExplorerBrowser *peb;
1265 IUnknown *punk;
1266 HRESULT hr;
1268 /* GetCurrentView */
1269 ebrowser_instantiate(&peb);
1271 if(0)
1273 /* Crashes under Windows 7 */
1274 hr = IExplorerBrowser_GetCurrentView(peb, NULL, NULL);
1276 hr = IExplorerBrowser_GetCurrentView(peb, NULL, (void**)&punk);
1277 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1279 #define test_gcv(iid, exp) \
1280 do { \
1281 hr = IExplorerBrowser_GetCurrentView(peb, &iid, (void**)&punk); \
1282 ok(hr == exp, "(%s:)Expected (0x%08x), got: (0x%08x)\n", \
1283 #iid ,exp, hr); \
1284 if(SUCCEEDED(hr)) IUnknown_Release(punk); \
1285 } while(0)
1287 test_gcv(IID_IUnknown, E_FAIL);
1288 test_gcv(IID_IUnknown, E_FAIL);
1289 test_gcv(IID_IShellView, E_FAIL);
1290 test_gcv(IID_IShellView2, E_FAIL);
1291 test_gcv(IID_IFolderView, E_FAIL);
1292 test_gcv(IID_IPersistFolder, E_FAIL);
1293 test_gcv(IID_IPersistFolder2, E_FAIL);
1294 test_gcv(IID_ICommDlgBrowser, E_FAIL);
1295 test_gcv(IID_ICommDlgBrowser2, E_FAIL);
1296 test_gcv(IID_ICommDlgBrowser3, E_FAIL);
1298 ebrowser_initialize(peb);
1299 ebrowser_browse_to_desktop(peb);
1301 test_gcv(IID_IUnknown, S_OK);
1302 test_gcv(IID_IUnknown, S_OK);
1303 test_gcv(IID_IShellView, S_OK);
1304 test_gcv(IID_IShellView2, S_OK);
1305 test_gcv(IID_IFolderView, S_OK);
1306 todo_wine test_gcv(IID_IPersistFolder, S_OK);
1307 test_gcv(IID_IPersistFolder2, E_NOINTERFACE);
1308 test_gcv(IID_ICommDlgBrowser, E_NOINTERFACE);
1309 test_gcv(IID_ICommDlgBrowser2, E_NOINTERFACE);
1310 test_gcv(IID_ICommDlgBrowser3, E_NOINTERFACE);
1312 #undef test_gcv
1314 IExplorerBrowser_Destroy(peb);
1315 IExplorerBrowser_Release(peb);
1318 static BOOL test_instantiate_control(void)
1320 IExplorerBrowser *peb;
1321 HRESULT hr;
1323 hr = ebrowser_instantiate(&peb);
1324 ok(hr == S_OK || hr == REGDB_E_CLASSNOTREG, "Got (0x%08x)\n", hr);
1325 if(FAILED(hr))
1326 return FALSE;
1328 IExplorerBrowser_Release(peb);
1329 return TRUE;
1332 static void setup_window(void)
1334 WNDCLASSW wc;
1335 static const WCHAR ebtestW[] = {'e','b','t','e','s','t',0};
1337 ZeroMemory(&wc, sizeof(WNDCLASSW));
1338 wc.lpfnWndProc = DefWindowProcW;
1339 wc.lpszClassName = ebtestW;
1340 RegisterClassW(&wc);
1341 hwnd = CreateWindowExW(0, ebtestW, NULL, 0,
1342 0, 0, 500, 500,
1343 NULL, 0, 0, NULL);
1344 ok(hwnd != NULL, "Failed to create window for tests.\n");
1347 START_TEST(ebrowser)
1349 OleInitialize(NULL);
1351 if(!test_instantiate_control())
1353 win_skip("No ExplorerBrowser control..\n");
1354 OleUninitialize();
1355 return;
1358 setup_window();
1359 init_function_pointers();
1361 test_QueryInterface();
1362 test_SB_misc();
1363 test_initialization();
1364 test_basics();
1365 test_Advise();
1366 test_navigation();
1367 test_GetCurrentView();
1368 test_SetSite();
1370 DestroyWindow(hwnd);
1371 OleUninitialize();