4 * Copyright 2004 Kevin Koltzau
5 * Copyright 2004 Jacek Caban
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/test.h"
32 #define DEFINE_EXPECT(func) \
33 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
35 #define SET_EXPECT(func) \
36 expect_ ## func = TRUE
38 #define CHECK_EXPECT(func) \
39 ok(expect_ ##func, "unexpected call\n"); \
40 expect_ ## func = FALSE; \
41 called_ ## func = TRUE
43 #define CHECK_EXPECT2(func) \
44 ok(expect_ ##func, "unexpected call\n"); \
45 called_ ## func = TRUE
47 #define CHECK_CALLED(func) \
48 ok(called_ ## func, "expected " #func "\n"); \
49 expect_ ## func = called_ ## func = FALSE
51 DEFINE_EXPECT(GetBindInfo
);
52 DEFINE_EXPECT(OnStartBinding
);
53 DEFINE_EXPECT(OnProgress_FINDINGRESOURCE
);
54 DEFINE_EXPECT(OnProgress_CONNECTING
);
55 DEFINE_EXPECT(OnProgress_SENDINGREQUEST
);
56 DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE
);
57 DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA
);
58 DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA
);
59 DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA
);
60 DEFINE_EXPECT(OnStopBinding
);
61 DEFINE_EXPECT(OnDataAvailable
);
63 static const WCHAR TEST_URL_1
[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','\0'};
64 static const WCHAR TEST_PART_URL_1
[] = {'/','t','e','s','t','/','\0'};
66 static const WCHAR WINE_ABOUT_URL
[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
67 'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
68 static BOOL stopped_binding
= FALSE
;
70 static void test_CreateURLMoniker(LPCWSTR url1
, LPCWSTR url2
)
73 IMoniker
*mon1
= NULL
;
74 IMoniker
*mon2
= NULL
;
76 hr
= CreateURLMoniker(NULL
, url1
, &mon1
);
77 ok(SUCCEEDED(hr
), "failed to create moniker: 0x%08lx\n", hr
);
79 hr
= CreateURLMoniker(mon1
, url2
, &mon2
);
80 ok(SUCCEEDED(hr
), "failed to create moniker: 0x%08lx\n", hr
);
82 if(mon1
) IMoniker_Release(mon1
);
83 if(mon2
) IMoniker_Release(mon2
);
86 static void test_create(void)
88 test_CreateURLMoniker(TEST_URL_1
, TEST_PART_URL_1
);
92 const IBindStatusCallbackVtbl
*lpVtbl
;
98 static HRESULT WINAPI
statusclb_QueryInterface(IBindStatusCallback
*iface
, REFIID riid
, void **ppvObject
)
100 return E_NOINTERFACE
;
103 static ULONG WINAPI
statusclb_AddRef(IBindStatusCallback
*iface
)
105 return InterlockedIncrement(&((statusclb
*)iface
)->ref
);
108 static ULONG WINAPI
statusclb_Release(IBindStatusCallback
*iface
)
110 statusclb
*This
= (statusclb
*)iface
;
112 ref
= InterlockedDecrement(&This
->ref
);
114 HeapFree(GetProcessHeap(), 0, This
);
118 static HRESULT WINAPI
statusclb_OnStartBinding(IBindStatusCallback
*iface
, DWORD dwReserved
,
121 statusclb
*This
= (statusclb
*)iface
;
125 CHECK_EXPECT(OnStartBinding
);
128 ok(pib
!= NULL
, "pib should not be NULL\n");
130 IBinding_AddRef(pib
);
132 hres
= IBinding_QueryInterface(pib
, &IID_IMoniker
, (void**)&mon
);
133 ok(hres
== E_NOINTERFACE
, "IBinding should not have IMoniker interface\n");
135 IMoniker_Release(mon
);
140 static HRESULT WINAPI
statusclb_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
142 ok(0, "unexpected call\n");
146 static HRESULT WINAPI
statusclb_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
148 ok(0, "unexpected call\n");
152 static HRESULT WINAPI
statusclb_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
153 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
155 switch(ulStatusCode
) {
156 case BINDSTATUS_FINDINGRESOURCE
:
157 CHECK_EXPECT(OnProgress_FINDINGRESOURCE
);
159 case BINDSTATUS_CONNECTING
:
160 CHECK_EXPECT(OnProgress_CONNECTING
);
162 case BINDSTATUS_SENDINGREQUEST
:
163 CHECK_EXPECT(OnProgress_SENDINGREQUEST
);
165 case BINDSTATUS_MIMETYPEAVAILABLE
:
166 CHECK_EXPECT(OnProgress_MIMETYPEAVAILABLE
);
168 case BINDSTATUS_BEGINDOWNLOADDATA
:
169 CHECK_EXPECT(OnProgress_BEGINDOWNLOADDATA
);
171 case BINDSTATUS_DOWNLOADINGDATA
:
172 CHECK_EXPECT2(OnProgress_DOWNLOADINGDATA
);
174 case BINDSTATUS_ENDDOWNLOADDATA
:
175 CHECK_EXPECT(OnProgress_ENDDOWNLOADDATA
);
178 todo_wine
{ ok(0, "unexpexted code %ld\n", ulStatusCode
); }
183 static HRESULT WINAPI
statusclb_OnStopBinding(IBindStatusCallback
*iface
, HRESULT hresult
, LPCWSTR szError
)
185 statusclb
*This
= (statusclb
*)iface
;
187 CHECK_EXPECT(OnStopBinding
);
189 ok(SUCCEEDED(hresult
), "Download failed: %08lx\n", hresult
);
190 ok(szError
== NULL
, "szError should be NULL\n");
191 stopped_binding
= TRUE
;
192 IBinding_Release(This
->pbind
);
193 ok(This
->pstr
!= NULL
, "pstr should not be NULL here\n");
195 IStream_Release(This
->pstr
);
200 static HRESULT WINAPI
statusclb_GetBindInfo(IBindStatusCallback
*iface
, DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
204 CHECK_EXPECT(GetBindInfo
);
206 *grfBINDF
= BINDF_ASYNCHRONOUS
| BINDF_ASYNCSTORAGE
| BINDF_PULLDATA
;
207 cbSize
= pbindinfo
->cbSize
;
208 memset(pbindinfo
, 0, cbSize
);
209 pbindinfo
->cbSize
= cbSize
;
214 static HRESULT WINAPI
statusclb_OnDataAvailable(IBindStatusCallback
*iface
, DWORD grfBSCF
, DWORD dwSize
,
215 FORMATETC
* pformatetc
, STGMEDIUM
* pstgmed
)
217 statusclb
*This
= (statusclb
*)iface
;
222 CHECK_EXPECT2(OnDataAvailable
);
225 ok(grfBSCF
& BSCF_FIRSTDATANOTIFICATION
, "pstr should be set when BSCF_FIRSTDATANOTIFICATION\n");
226 This
->pstr
= U(*pstgmed
).pstm
;
227 IStream_AddRef(This
->pstr
);
228 ok(This
->pstr
!= NULL
, "pstr should not be NULL here\n");
231 do hres
= IStream_Read(This
->pstr
, buf
, 512, &readed
);
233 ok(hres
== S_FALSE
|| hres
== E_PENDING
, "IStream_Read returned %08lx\n", hres
);
238 static HRESULT WINAPI
statusclb_OnObjectAvailable(IBindStatusCallback
*iface
, REFIID riid
, IUnknown
*punk
)
240 ok(0, "unexpected call\n");
244 static const IBindStatusCallbackVtbl statusclbVtbl
= {
245 statusclb_QueryInterface
,
248 statusclb_OnStartBinding
,
249 statusclb_GetPriority
,
250 statusclb_OnLowResource
,
251 statusclb_OnProgress
,
252 statusclb_OnStopBinding
,
253 statusclb_GetBindInfo
,
254 statusclb_OnDataAvailable
,
255 statusclb_OnObjectAvailable
258 static IBindStatusCallback
* statusclb_create(void)
260 statusclb
*ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(statusclb
));
261 ret
->lpVtbl
= &statusclbVtbl
;
265 return (IBindStatusCallback
*)ret
;
268 static void test_CreateAsyncBindCtx(void)
270 IBindCtx
*bctx
= (IBindCtx
*)0x0ff00ff0;
274 IBindStatusCallback
*bsc
= statusclb_create();
276 hres
= CreateAsyncBindCtx(0, NULL
, NULL
, &bctx
);
277 ok(hres
== E_INVALIDARG
, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08lx\n", hres
);
278 ok(bctx
== (IBindCtx
*)0x0ff00ff0, "bctx should not be changed\n");
280 hres
= CreateAsyncBindCtx(0, NULL
, NULL
, NULL
);
281 ok(hres
== E_INVALIDARG
, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08lx\n", hres
);
283 hres
= CreateAsyncBindCtx(0, bsc
, NULL
, &bctx
);
284 ok(SUCCEEDED(hres
), "CreateAsyncBindCtx failed: %08lx\n", hres
);
286 IBindStatusCallback_Release(bsc
);
290 bindopts
.cbStruct
= sizeof(bindopts
);
291 hres
= IBindCtx_GetBindOptions(bctx
, &bindopts
);
292 ok(SUCCEEDED(hres
), "IBindCtx_GetBindOptions failed: %08lx\n", hres
);
293 ok(bindopts
.grfFlags
== BIND_MAYBOTHERUSER
,
294 "bindopts.grfFlags = %08lx, expected: BIND_MAYBOTHERUSER\n", bindopts
.grfFlags
);
295 ok(bindopts
.grfMode
== (STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
),
296 "bindopts.grfMode = %08lx, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
298 ok(bindopts
.dwTickCountDeadline
== 0,
299 "bindopts.dwTickCountDeadline = %08lx, expected: 0\n", bindopts
.dwTickCountDeadline
);
301 ref
= IBindCtx_Release(bctx
);
302 ok(ref
== 0, "bctx should be destroyed here\n");
303 ref
= IBindStatusCallback_Release(bsc
);
304 ok(ref
== 0, "bsc should be destroyed here\n");
307 static void test_CreateAsyncBindCtxEx(void)
309 IBindCtx
*bctx
= NULL
, *bctx_arg
= NULL
;
310 IBindStatusCallback
*bsc
= statusclb_create();
314 hres
= CreateAsyncBindCtxEx(NULL
, 0, NULL
, NULL
, NULL
, 0);
315 ok(hres
== E_INVALIDARG
, "CreateAsyncBindCtx failed: %08lx, expected E_INVALIDARG\n", hres
);
317 hres
= CreateAsyncBindCtxEx(NULL
, 0, NULL
, NULL
, &bctx
, 0);
318 ok(hres
== S_OK
, "CreateAsyncBindCtxEx failed: %08lx\n", hres
);
320 if(SUCCEEDED(hres
)) {
321 bindopts
.cbStruct
= sizeof(bindopts
);
322 hres
= IBindCtx_GetBindOptions(bctx
, &bindopts
);
323 ok(SUCCEEDED(hres
), "IBindCtx_GetBindOptions failed: %08lx\n", hres
);
324 ok(bindopts
.grfFlags
== BIND_MAYBOTHERUSER
,
325 "bindopts.grfFlags = %08lx, expected: BIND_MAYBOTHERUSER\n", bindopts
.grfFlags
);
326 ok(bindopts
.grfMode
== (STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
),
327 "bindopts.grfMode = %08lx, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
329 ok(bindopts
.dwTickCountDeadline
== 0,
330 "bindopts.dwTickCountDeadline = %08lx, expected: 0\n", bindopts
.dwTickCountDeadline
);
332 IBindCtx_Release(bctx
);
335 CreateBindCtx(0, &bctx_arg
);
336 hres
= CreateAsyncBindCtxEx(NULL
, 0, NULL
, NULL
, &bctx
, 0);
337 ok(hres
== S_OK
, "CreateAsyncBindCtxEx failed: %08lx\n", hres
);
339 if(SUCCEEDED(hres
)) {
340 bindopts
.cbStruct
= sizeof(bindopts
);
341 hres
= IBindCtx_GetBindOptions(bctx
, &bindopts
);
342 ok(SUCCEEDED(hres
), "IBindCtx_GetBindOptions failed: %08lx\n", hres
);
343 ok(bindopts
.grfFlags
== BIND_MAYBOTHERUSER
,
344 "bindopts.grfFlags = %08lx, expected: BIND_MAYBOTHERUSER\n", bindopts
.grfFlags
);
345 ok(bindopts
.grfMode
== (STGM_READWRITE
| STGM_SHARE_EXCLUSIVE
),
346 "bindopts.grfMode = %08lx, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
348 ok(bindopts
.dwTickCountDeadline
== 0,
349 "bindopts.dwTickCountDeadline = %08lx, expected: 0\n", bindopts
.dwTickCountDeadline
);
351 IBindCtx_Release(bctx
);
354 IBindCtx_Release(bctx_arg
);
356 hres
= CreateAsyncBindCtxEx(NULL
, 0, bsc
, NULL
, &bctx
, 0);
357 ok(hres
== S_OK
, "CreateAsyncBindCtxEx failed: %08lx\n", hres
);
360 IBindCtx_Release(bctx
);
362 IBindStatusCallback_Release(bsc
);
365 static void test_BindToStorage(void)
369 LPOLESTR display_name
;
372 IBindStatusCallback
*previousclb
, *sclb
= statusclb_create();
373 IUnknown
*unk
= (IUnknown
*)0x00ff00ff;
376 hres
= CreateAsyncBindCtx(0, sclb
, NULL
, &bctx
);
377 ok(SUCCEEDED(hres
), "CreateAsyncBindCtx failed: %08lx\n\n", hres
);
379 IBindStatusCallback_Release(sclb
);
383 hres
= RegisterBindStatusCallback(bctx
, sclb
, &previousclb
, 0);
384 ok(SUCCEEDED(hres
), "RegisterBindStatusCallback failed: %08lx\n", hres
);
385 ok(previousclb
== sclb
, "previousclb(%p) != sclb(%p)\n", previousclb
, sclb
);
387 IBindStatusCallback_Release(previousclb
);
389 hres
= CreateURLMoniker(NULL
, WINE_ABOUT_URL
, &mon
);
390 ok(SUCCEEDED(hres
), "failed to create moniker: %08lx\n", hres
);
392 IBindStatusCallback_Release(sclb
);
393 IBindCtx_Release(bctx
);
397 hres
= IMoniker_QueryInterface(mon
, &IID_IBinding
, (void**)&bind
);
398 ok(hres
== E_NOINTERFACE
, "IMoniker should not have IBinding interface\n");
400 IBinding_Release(bind
);
402 hres
= IMoniker_GetDisplayName(mon
, bctx
, NULL
, &display_name
);
403 ok(SUCCEEDED(hres
), "GetDisplayName failed %08lx\n", hres
);
404 ok(!lstrcmpW(display_name
, WINE_ABOUT_URL
), "GetDisplayName got wrong name\n");
406 SET_EXPECT(GetBindInfo
);
407 SET_EXPECT(OnStartBinding
);
408 SET_EXPECT(OnProgress_FINDINGRESOURCE
);
409 SET_EXPECT(OnProgress_CONNECTING
);
410 SET_EXPECT(OnProgress_SENDINGREQUEST
);
411 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE
);
412 SET_EXPECT(OnProgress_BEGINDOWNLOADDATA
);
413 SET_EXPECT(OnDataAvailable
);
414 SET_EXPECT(OnProgress_DOWNLOADINGDATA
);
415 SET_EXPECT(OnProgress_ENDDOWNLOADDATA
);
416 SET_EXPECT(OnStopBinding
);
418 hres
= IMoniker_BindToStorage(mon
, bctx
, NULL
, &IID_IStream
, (void**)&unk
);
419 ok(SUCCEEDED(hres
), "IMoniker_BindToStorage failed: %08lx\n", hres
);
421 ok(unk
== NULL
, "istr should be NULL\n");
424 IBindStatusCallback_Release(sclb
);
425 IMoniker_Release(mon
);
429 IUnknown_Release(unk
);
431 while(!stopped_binding
&& GetMessage(&msg
,NULL
,0,0)) {
432 TranslateMessage(&msg
);
433 DispatchMessage(&msg
);
436 CHECK_CALLED(GetBindInfo
);
437 CHECK_CALLED(OnStartBinding
);
438 CHECK_CALLED(OnProgress_FINDINGRESOURCE
);
439 CHECK_CALLED(OnProgress_CONNECTING
);
440 CHECK_CALLED(OnProgress_SENDINGREQUEST
);
441 todo_wine
{ CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE
); }
442 CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA
);
443 CHECK_CALLED(OnDataAvailable
);
444 CHECK_CALLED(OnProgress_DOWNLOADINGDATA
);
445 CHECK_CALLED(OnProgress_ENDDOWNLOADDATA
);
446 CHECK_CALLED(OnStopBinding
);
448 ok(IMoniker_Release(mon
) == 0, "mon should be destroyed here\n");
449 ok(IBindCtx_Release(bctx
) == 0, "bctx should be destroyed here\n");
450 ok(IBindStatusCallback_Release(sclb
) == 0, "scbl should be destroyed here\n");
456 test_CreateAsyncBindCtx();
457 test_CreateAsyncBindCtxEx();
458 test_BindToStorage();