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