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