push 4764fdcba48f6a6df3263056e605233f2bb574ff
[wine/hacks.git] / dlls / urlmon / tests / url.c
blob1b2758e361c0ffa26831b95a2f78d4417d3708df
1 /*
2 * UrlMon URL tests
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
24 #define COBJMACROS
25 #define CONST_VTABLE
27 #include "windef.h"
28 #include "winbase.h"
29 #include "urlmon.h"
30 #include "wininet.h"
32 #include "wine/test.h"
34 #define DEFINE_EXPECT(func) \
35 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
37 #define SET_EXPECT(func) \
38 expect_ ## func = TRUE
40 #define CHECK_EXPECT(func) \
41 do { \
42 ok(expect_ ##func, "unexpected call " #func "\n"); \
43 expect_ ## func = FALSE; \
44 called_ ## func = TRUE; \
45 }while(0)
47 #define CHECK_EXPECT2(func) \
48 do { \
49 ok(expect_ ##func, "unexpected call " #func "\n"); \
50 called_ ## func = TRUE; \
51 }while(0)
53 #define CHECK_CALLED(func) \
54 do { \
55 ok(called_ ## func, "expected " #func "\n"); \
56 expect_ ## func = called_ ## func = FALSE; \
57 }while(0)
59 #define CHECK_NOT_CALLED(func) \
60 do { \
61 ok(!called_ ## func, "unexpected " #func "\n"); \
62 expect_ ## func = called_ ## func = FALSE; \
63 }while(0)
65 #define CLEAR_CALLED(func) \
66 expect_ ## func = called_ ## func = FALSE
68 DEFINE_EXPECT(QueryInterface_IServiceProvider);
69 DEFINE_EXPECT(QueryInterface_IHttpNegotiate);
70 DEFINE_EXPECT(BeginningTransaction);
71 DEFINE_EXPECT(OnResponse);
72 DEFINE_EXPECT(QueryInterface_IHttpNegotiate2);
73 DEFINE_EXPECT(GetRootSecurityId);
74 DEFINE_EXPECT(GetBindInfo);
75 DEFINE_EXPECT(OnStartBinding);
76 DEFINE_EXPECT(OnProgress_FINDINGRESOURCE);
77 DEFINE_EXPECT(OnProgress_CONNECTING);
78 DEFINE_EXPECT(OnProgress_SENDINGREQUEST);
79 DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE);
80 DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA);
81 DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA);
82 DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA);
83 DEFINE_EXPECT(OnStopBinding);
84 DEFINE_EXPECT(OnDataAvailable);
85 DEFINE_EXPECT(Start);
86 DEFINE_EXPECT(Read);
87 DEFINE_EXPECT(LockRequest);
88 DEFINE_EXPECT(Terminate);
89 DEFINE_EXPECT(UnlockRequest);
91 static const WCHAR TEST_URL_1[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','\0'};
92 static const WCHAR TEST_PART_URL_1[] = {'/','t','e','s','t','/','\0'};
94 static const WCHAR WINE_ABOUT_URL[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
95 'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
96 static const WCHAR ABOUT_BLANK[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
97 static WCHAR INDEX_HTML[MAX_PATH];
98 static const WCHAR ITS_URL[] =
99 {'i','t','s',':','t','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0};
100 static const WCHAR MK_URL[] = {'m','k',':','@','M','S','I','T','S','t','o','r','e',':',
101 't','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0};
105 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
107 static BOOL stopped_binding = FALSE, emulate_protocol = FALSE;
108 static DWORD read = 0;
110 static const LPCWSTR urls[] = {
111 WINE_ABOUT_URL,
112 ABOUT_BLANK,
113 INDEX_HTML,
114 ITS_URL,
115 MK_URL
118 static enum {
119 HTTP_TEST,
120 ABOUT_TEST,
121 FILE_TEST,
122 ITS_TEST,
123 MK_TEST
124 } test_protocol;
126 static void test_CreateURLMoniker(LPCWSTR url1, LPCWSTR url2)
128 HRESULT hr;
129 IMoniker *mon1 = NULL;
130 IMoniker *mon2 = NULL;
132 hr = CreateURLMoniker(NULL, url1, &mon1);
133 ok(SUCCEEDED(hr), "failed to create moniker: 0x%08x\n", hr);
134 if(SUCCEEDED(hr)) {
135 hr = CreateURLMoniker(mon1, url2, &mon2);
136 ok(SUCCEEDED(hr), "failed to create moniker: 0x%08x\n", hr);
138 if(mon1) IMoniker_Release(mon1);
139 if(mon2) IMoniker_Release(mon2);
142 static void test_create(void)
144 test_CreateURLMoniker(TEST_URL_1, TEST_PART_URL_1);
147 static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
149 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
150 *ppv = iface;
151 return S_OK;
154 *ppv = NULL;
155 return E_NOINTERFACE;
158 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
160 return 2;
163 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
165 return 1;
168 static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
169 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
170 DWORD grfPI, DWORD dwReserved)
172 BINDINFO bindinfo, bi = {sizeof(bi), 0};
173 DWORD bindf, bscf = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
174 WCHAR null_char = 0;
175 HRESULT hres;
177 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
179 CHECK_EXPECT(Start);
181 read = 0;
183 ok(szUrl && !lstrcmpW(szUrl, urls[test_protocol]), "wrong url\n");
184 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
185 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
186 ok(grfPI == 0, "grfPI=%d, expected 0\n", grfPI);
187 ok(dwReserved == 0, "dwReserved=%d, expected 0\n", dwReserved);
189 memset(&bindinfo, 0, sizeof(bindinfo));
190 bindinfo.cbSize = sizeof(bindinfo);
191 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
192 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
194 if(test_protocol == FILE_TEST || test_protocol == MK_TEST) {
195 ok(bindf == (BINDF_ASYNCHRONOUS|BINDF_ASYNCSTORAGE|BINDF_PULLDATA
196 |BINDF_FROMURLMON),
197 "bindf=%08x\n", bindf);
198 }else {
199 ok(bindf == (BINDF_ASYNCHRONOUS|BINDF_ASYNCSTORAGE|BINDF_PULLDATA|
200 BINDF_FROMURLMON|BINDF_NEEDFILE),
201 "bindf=%08x\n", bindf);
204 ok(!memcmp(&bindinfo, &bi, sizeof(bindinfo)), "wrong bindinfo\n");
206 switch(test_protocol) {
207 case MK_TEST:
208 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
209 BINDSTATUS_DIRECTBIND, NULL);
210 ok(hres == S_OK,
211 "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
213 case FILE_TEST:
214 case ITS_TEST:
215 SET_EXPECT(OnProgress_SENDINGREQUEST);
216 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
217 BINDSTATUS_SENDINGREQUEST, &null_char);
218 ok(hres == S_OK,
219 "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
220 CHECK_CALLED(OnProgress_SENDINGREQUEST);
221 default:
222 break;
225 if(test_protocol == FILE_TEST) {
226 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
227 BINDSTATUS_CACHEFILENAMEAVAILABLE, &null_char);
228 ok(hres == S_OK,
229 "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
231 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
232 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
233 BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, wszTextHtml);
234 ok(hres == S_OK,
235 "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
236 CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
237 }else {
238 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
239 BINDSTATUS_MIMETYPEAVAILABLE, wszTextHtml);
240 ok(hres == S_OK,
241 "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
244 if(test_protocol == ABOUT_TEST)
245 bscf |= BSCF_DATAFULLYAVAILABLE;
246 if(test_protocol == ITS_TEST)
247 bscf = BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
249 SET_EXPECT(Read);
250 if(test_protocol != FILE_TEST && test_protocol != MK_TEST)
251 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
252 SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
253 SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
254 SET_EXPECT(LockRequest);
255 SET_EXPECT(OnDataAvailable);
256 SET_EXPECT(OnStopBinding);
258 hres = IInternetProtocolSink_ReportData(pOIProtSink, bscf, 13, 13);
259 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
261 CHECK_CALLED(Read);
262 if(test_protocol != FILE_TEST && test_protocol != MK_TEST)
263 CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
264 CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
265 CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
266 CHECK_CALLED(LockRequest);
267 CHECK_CALLED(OnDataAvailable);
268 CHECK_CALLED(OnStopBinding);
270 if(test_protocol == ITS_TEST) {
271 SET_EXPECT(Read);
272 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
273 ok(hres == S_OK, "ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres);
274 CHECK_CALLED(Read);
277 SET_EXPECT(Terminate);
278 hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
279 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
280 CHECK_CALLED(Terminate);
282 return S_OK;
285 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
286 PROTOCOLDATA *pProtocolData)
288 ok(0, "unexpected call\n");
289 return E_NOTIMPL;
292 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
293 DWORD dwOptions)
295 ok(0, "unexpected call\n");
296 return E_NOTIMPL;
299 static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
301 CHECK_EXPECT(Terminate);
302 ok(dwOptions == 0, "dwOptions=%d, expected 0\n", dwOptions);
303 return S_OK;
306 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
308 ok(0, "unexpected call\n");
309 return E_NOTIMPL;
312 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
314 ok(0, "unexpected call\n");
315 return E_NOTIMPL;
318 static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv,
319 ULONG cb, ULONG *pcbRead)
321 static const char data[] = "<HTML></HTML>";
323 CHECK_EXPECT2(Read);
325 if(read) {
326 *pcbRead = 0;
327 return S_FALSE;
330 ok(pv != NULL, "pv == NULL\n");
331 ok(cb != 0, "cb == 0\n");
332 ok(pcbRead != NULL, "pcbRead == NULL\n");
333 if(pcbRead) {
334 ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
335 read += *pcbRead = sizeof(data)-1;
337 if(pv)
338 memcpy(pv, data, sizeof(data));
340 return S_OK;
343 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
344 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
346 ok(0, "unexpected call\n");
347 return E_NOTIMPL;
350 static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
352 CHECK_EXPECT(LockRequest);
353 return S_OK;
356 static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface)
358 CHECK_EXPECT(UnlockRequest);
359 return S_OK;
362 static const IInternetProtocolVtbl ProtocolVtbl = {
363 Protocol_QueryInterface,
364 Protocol_AddRef,
365 Protocol_Release,
366 Protocol_Start,
367 Protocol_Continue,
368 Protocol_Abort,
369 Protocol_Terminate,
370 Protocol_Suspend,
371 Protocol_Resume,
372 Protocol_Read,
373 Protocol_Seek,
374 Protocol_LockRequest,
375 Protocol_UnlockRequest
378 static IInternetProtocol Protocol = { &ProtocolVtbl };
380 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
382 if(IsEqualGUID(&IID_IUnknown, riid)
383 || IsEqualGUID(&IID_IHttpNegotiate, riid)
384 || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
385 *ppv = iface;
386 return S_OK;
389 ok(0, "unexpected call\n");
390 return E_NOINTERFACE;
393 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
395 return 2;
398 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
400 return 1;
403 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
404 LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
406 CHECK_EXPECT(BeginningTransaction);
408 ok(!lstrcmpW(szURL, urls[test_protocol]), "szURL != urls[test_protocol]\n");
409 ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
410 ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
411 if(pszAdditionalHeaders)
412 ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
414 return S_OK;
417 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
418 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
420 CHECK_EXPECT(OnResponse);
422 ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
423 ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
424 ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
425 /* Note: in protocol.c tests, OnResponse pszAdditionalRequestHeaders _is_ NULL */
426 ok(pszAdditionalRequestHeaders != NULL, "pszAdditionalHeaders == NULL\n");
427 if(pszAdditionalRequestHeaders)
428 ok(*pszAdditionalRequestHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
430 return S_OK;
433 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
434 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
436 static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
438 CHECK_EXPECT(GetRootSecurityId);
440 ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
441 ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
442 ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
444 if(pcbSecurityId) {
445 ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
446 *pcbSecurityId = sizeof(sec_id);
449 if(pbSecurityId)
450 memcpy(pbSecurityId, sec_id, sizeof(sec_id));
452 return E_FAIL;
455 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
456 HttpNegotiate_QueryInterface,
457 HttpNegotiate_AddRef,
458 HttpNegotiate_Release,
459 HttpNegotiate_BeginningTransaction,
460 HttpNegotiate_OnResponse,
461 HttpNegotiate_GetRootSecurityId
464 static IHttpNegotiate2 HttpNegotiate = { &HttpNegotiateVtbl };
466 static HRESULT WINAPI statusclb_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
468 if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
469 if(emulate_protocol) {
470 *ppv = &Protocol;
471 return S_OK;
472 }else {
473 return E_NOINTERFACE;
476 else if (IsEqualGUID(&IID_IServiceProvider, riid))
478 CHECK_EXPECT(QueryInterface_IServiceProvider);
480 else if (IsEqualGUID(&IID_IHttpNegotiate, riid))
482 CHECK_EXPECT(QueryInterface_IHttpNegotiate);
483 *ppv = &HttpNegotiate;
484 return S_OK;
486 else if (IsEqualGUID(&IID_IHttpNegotiate2, riid))
488 CHECK_EXPECT(QueryInterface_IHttpNegotiate2);
489 *ppv = &HttpNegotiate;
490 return S_OK;
493 return E_NOINTERFACE;
496 static ULONG WINAPI statusclb_AddRef(IBindStatusCallback *iface)
498 return 2;
501 static ULONG WINAPI statusclb_Release(IBindStatusCallback *iface)
503 return 1;
506 static HRESULT WINAPI statusclb_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
507 IBinding *pib)
509 HRESULT hres;
510 IMoniker *mon;
512 CHECK_EXPECT(OnStartBinding);
514 ok(pib != NULL, "pib should not be NULL\n");
516 hres = IBinding_QueryInterface(pib, &IID_IMoniker, (void**)&mon);
517 ok(hres == E_NOINTERFACE, "IBinding should not have IMoniker interface\n");
518 if(SUCCEEDED(hres))
519 IMoniker_Release(mon);
521 return S_OK;
524 static HRESULT WINAPI statusclb_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
526 ok(0, "unexpected call\n");
527 return E_NOTIMPL;
530 static HRESULT WINAPI statusclb_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
532 ok(0, "unexpected call\n");
533 return E_NOTIMPL;
536 static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
537 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
539 switch(ulStatusCode) {
540 case BINDSTATUS_FINDINGRESOURCE:
541 CHECK_EXPECT(OnProgress_FINDINGRESOURCE);
542 break;
543 case BINDSTATUS_CONNECTING:
544 CHECK_EXPECT(OnProgress_CONNECTING);
545 break;
546 case BINDSTATUS_SENDINGREQUEST:
547 CHECK_EXPECT(OnProgress_SENDINGREQUEST);
548 break;
549 case BINDSTATUS_MIMETYPEAVAILABLE:
550 CHECK_EXPECT(OnProgress_MIMETYPEAVAILABLE);
551 break;
552 case BINDSTATUS_BEGINDOWNLOADDATA:
553 CHECK_EXPECT(OnProgress_BEGINDOWNLOADDATA);
554 ok(szStatusText != NULL, "szStatusText == NULL\n");
555 if(szStatusText)
556 ok(!lstrcmpW(szStatusText, urls[test_protocol]), "wrong szStatusText\n");
557 break;
558 case BINDSTATUS_DOWNLOADINGDATA:
559 CHECK_EXPECT2(OnProgress_DOWNLOADINGDATA);
560 break;
561 case BINDSTATUS_ENDDOWNLOADDATA:
562 CHECK_EXPECT(OnProgress_ENDDOWNLOADDATA);
563 ok(szStatusText != NULL, "szStatusText == NULL\n");
564 if(szStatusText)
565 ok(!lstrcmpW(szStatusText, urls[test_protocol]), "wrong szStatusText\n");
566 break;
567 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
568 ok(szStatusText != NULL, "szStatusText == NULL\n");
569 if(szStatusText && test_protocol == FILE_TEST)
570 ok(!lstrcmpW(INDEX_HTML+7, szStatusText), "wrong szStatusText\n");
571 break;
572 default:
573 todo_wine { ok(0, "unexpexted code %d\n", ulStatusCode); }
575 return S_OK;
578 static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
580 CHECK_EXPECT(OnStopBinding);
582 /* ignore DNS failure */
583 if (hresult != HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED))
585 ok(SUCCEEDED(hresult), "Download failed: %08x\n", hresult);
586 ok(szError == NULL, "szError should be NULL\n");
588 stopped_binding = TRUE;
590 return S_OK;
593 static HRESULT WINAPI statusclb_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
595 DWORD cbSize;
597 CHECK_EXPECT(GetBindInfo);
599 *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
600 cbSize = pbindinfo->cbSize;
601 memset(pbindinfo, 0, cbSize);
602 pbindinfo->cbSize = cbSize;
604 return S_OK;
607 static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
608 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
610 HRESULT hres;
611 DWORD readed;
612 BYTE buf[512];
614 CHECK_EXPECT2(OnDataAvailable);
616 if (0)
618 /* FIXME: Uncomment after removing BindToStorage hack. */
619 ok(pformatetc != NULL, "pformatetx == NULL\n");
620 if(pformatetc) {
621 ok(pformatetc->cfFormat == 0xc02d, "clipformat=%x\n", pformatetc->cfFormat);
622 ok(pformatetc->ptd == NULL, "ptd = %p\n", pformatetc->ptd);
623 ok(pformatetc->dwAspect == 1, "dwAspect=%u\n", pformatetc->dwAspect);
624 ok(pformatetc->lindex == -1, "lindex=%d\n", pformatetc->lindex);
625 ok(pformatetc->tymed == TYMED_ISTREAM, "tymed=%u\n", pformatetc->tymed);
628 ok(pstgmed != NULL, "stgmeg == NULL\n");
629 if(pstgmed) {
630 ok(pstgmed->tymed == TYMED_ISTREAM, "tymed=%u\n", pstgmed->tymed);
631 ok(U(*pstgmed).pstm != NULL, "pstm == NULL\n");
632 ok(pstgmed->pUnkForRelease != NULL, "pUnkForRelease == NULL\n");
636 if(U(*pstgmed).pstm) {
637 do hres = IStream_Read(U(*pstgmed).pstm, buf, 512, &readed);
638 while(hres == S_OK);
639 ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08x\n", hres);
642 return S_OK;
645 static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
647 ok(0, "unexpected call\n");
648 return E_NOTIMPL;
651 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
652 statusclb_QueryInterface,
653 statusclb_AddRef,
654 statusclb_Release,
655 statusclb_OnStartBinding,
656 statusclb_GetPriority,
657 statusclb_OnLowResource,
658 statusclb_OnProgress,
659 statusclb_OnStopBinding,
660 statusclb_GetBindInfo,
661 statusclb_OnDataAvailable,
662 statusclb_OnObjectAvailable
665 static IBindStatusCallback bsc = { &BindStatusCallbackVtbl };
667 static void test_CreateAsyncBindCtx(void)
669 IBindCtx *bctx = (IBindCtx*)0x0ff00ff0;
670 HRESULT hres;
671 ULONG ref;
672 BIND_OPTS bindopts;
674 hres = CreateAsyncBindCtx(0, NULL, NULL, &bctx);
675 ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08x\n", hres);
676 ok(bctx == (IBindCtx*)0x0ff00ff0, "bctx should not be changed\n");
678 hres = CreateAsyncBindCtx(0, NULL, NULL, NULL);
679 ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08x\n", hres);
681 SET_EXPECT(QueryInterface_IServiceProvider);
682 hres = CreateAsyncBindCtx(0, &bsc, NULL, &bctx);
683 ok(SUCCEEDED(hres), "CreateAsyncBindCtx failed: %08x\n", hres);
684 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
686 bindopts.cbStruct = sizeof(bindopts);
687 hres = IBindCtx_GetBindOptions(bctx, &bindopts);
688 ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08x\n", hres);
689 ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
690 "bindopts.grfFlags = %08x, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
691 ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
692 "bindopts.grfMode = %08x, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
693 bindopts.grfMode);
694 ok(bindopts.dwTickCountDeadline == 0,
695 "bindopts.dwTickCountDeadline = %08x, expected: 0\n", bindopts.dwTickCountDeadline);
697 ref = IBindCtx_Release(bctx);
698 ok(ref == 0, "bctx should be destroyed here\n");
701 static void test_CreateAsyncBindCtxEx(void)
703 IBindCtx *bctx = NULL, *bctx_arg = NULL;
704 BIND_OPTS bindopts;
705 HRESULT hres;
707 hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, NULL, 0);
708 ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed: %08x, expected E_INVALIDARG\n", hres);
710 hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
711 ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
713 if(SUCCEEDED(hres)) {
714 bindopts.cbStruct = sizeof(bindopts);
715 hres = IBindCtx_GetBindOptions(bctx, &bindopts);
716 ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08x\n", hres);
717 ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
718 "bindopts.grfFlags = %08x, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
719 ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
720 "bindopts.grfMode = %08x, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
721 bindopts.grfMode);
722 ok(bindopts.dwTickCountDeadline == 0,
723 "bindopts.dwTickCountDeadline = %08x, expected: 0\n", bindopts.dwTickCountDeadline);
725 IBindCtx_Release(bctx);
728 CreateBindCtx(0, &bctx_arg);
729 hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
730 ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
732 if(SUCCEEDED(hres)) {
733 bindopts.cbStruct = sizeof(bindopts);
734 hres = IBindCtx_GetBindOptions(bctx, &bindopts);
735 ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08x\n", hres);
736 ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
737 "bindopts.grfFlags = %08x, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
738 ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
739 "bindopts.grfMode = %08x, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
740 bindopts.grfMode);
741 ok(bindopts.dwTickCountDeadline == 0,
742 "bindopts.dwTickCountDeadline = %08x, expected: 0\n", bindopts.dwTickCountDeadline);
744 IBindCtx_Release(bctx);
747 IBindCtx_Release(bctx_arg);
749 SET_EXPECT(QueryInterface_IServiceProvider);
750 hres = CreateAsyncBindCtxEx(NULL, 0, &bsc, NULL, &bctx, 0);
751 ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
752 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
754 if(SUCCEEDED(hres))
755 IBindCtx_Release(bctx);
758 static void test_BindToStorage(int protocol, BOOL emul)
760 IMoniker *mon;
761 HRESULT hres;
762 LPOLESTR display_name;
763 IBindCtx *bctx;
764 MSG msg;
765 IBindStatusCallback *previousclb;
766 IUnknown *unk = (IUnknown*)0x00ff00ff;
767 IBinding *bind;
769 test_protocol = protocol;
770 emulate_protocol = emul;
772 SET_EXPECT(QueryInterface_IServiceProvider);
773 hres = CreateAsyncBindCtx(0, &bsc, NULL, &bctx);
774 ok(SUCCEEDED(hres), "CreateAsyncBindCtx failed: %08x\n\n", hres);
775 if(FAILED(hres))
776 return;
777 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
779 SET_EXPECT(QueryInterface_IServiceProvider);
780 hres = RegisterBindStatusCallback(bctx, &bsc, &previousclb, 0);
781 ok(SUCCEEDED(hres), "RegisterBindStatusCallback failed: %08x\n", hres);
782 ok(previousclb == &bsc, "previousclb(%p) != sclb(%p)\n", previousclb, &bsc);
783 todo_wine CHECK_CALLED(QueryInterface_IServiceProvider);
784 if(previousclb)
785 IBindStatusCallback_Release(previousclb);
787 hres = CreateURLMoniker(NULL, urls[test_protocol], &mon);
788 ok(SUCCEEDED(hres), "failed to create moniker: %08x\n", hres);
789 if(FAILED(hres)) {
790 IBindCtx_Release(bctx);
791 return;
794 if(test_protocol == FILE_TEST && INDEX_HTML[7] == '/')
795 memmove(INDEX_HTML+7, INDEX_HTML+8, lstrlenW(INDEX_HTML+7)*sizeof(WCHAR));
797 hres = IMoniker_QueryInterface(mon, &IID_IBinding, (void**)&bind);
798 ok(hres == E_NOINTERFACE, "IMoniker should not have IBinding interface\n");
799 if(SUCCEEDED(hres))
800 IBinding_Release(bind);
802 hres = IMoniker_GetDisplayName(mon, bctx, NULL, &display_name);
803 ok(hres == S_OK, "GetDisplayName failed %08x\n", hres);
804 ok(!lstrcmpW(display_name, urls[test_protocol]), "GetDisplayName got wrong name\n");
806 SET_EXPECT(QueryInterface_IServiceProvider);
807 SET_EXPECT(GetBindInfo);
808 SET_EXPECT(OnStartBinding);
809 if(emulate_protocol) {
810 SET_EXPECT(Start);
811 SET_EXPECT(UnlockRequest);
812 }else {
813 if(test_protocol == HTTP_TEST) {
814 SET_EXPECT(QueryInterface_IHttpNegotiate);
815 SET_EXPECT(BeginningTransaction);
816 SET_EXPECT(QueryInterface_IHttpNegotiate2);
817 SET_EXPECT(GetRootSecurityId);
818 SET_EXPECT(OnProgress_FINDINGRESOURCE);
819 SET_EXPECT(OnProgress_CONNECTING);
821 if(test_protocol == HTTP_TEST || test_protocol == FILE_TEST)
822 SET_EXPECT(OnProgress_SENDINGREQUEST);
823 if(test_protocol == HTTP_TEST)
824 SET_EXPECT(OnResponse);
825 SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
826 SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
827 if(test_protocol == HTTP_TEST)
828 SET_EXPECT(OnProgress_DOWNLOADINGDATA);
829 SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
830 SET_EXPECT(OnDataAvailable);
831 SET_EXPECT(OnStopBinding);
834 hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk);
835 if (test_protocol == HTTP_TEST && hres == HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED))
837 trace( "Network unreachable, skipping tests\n" );
838 return;
840 ok(SUCCEEDED(hres), "IMoniker_BindToStorage failed: %08x\n", hres);
841 if (!SUCCEEDED(hres)) return;
843 if(test_protocol == HTTP_TEST) {
844 todo_wine {
845 ok(unk == NULL, "istr should be NULL\n");
847 }else {
848 ok(unk != NULL, "unk == NULL\n");
850 if(unk)
851 IUnknown_Release(unk);
853 while(!stopped_binding && GetMessage(&msg,NULL,0,0)) {
854 TranslateMessage(&msg);
855 DispatchMessage(&msg);
858 CHECK_CALLED(GetBindInfo);
859 CHECK_CALLED(OnStartBinding);
860 if(emulate_protocol) {
861 todo_wine CHECK_NOT_CALLED(QueryInterface_IServiceProvider);
862 CHECK_CALLED(Start);
863 CHECK_CALLED(UnlockRequest);
864 }else {
865 if(test_protocol == HTTP_TEST) {
866 CHECK_NOT_CALLED(QueryInterface_IServiceProvider);
867 todo_wine CHECK_CALLED(QueryInterface_IHttpNegotiate);
868 todo_wine CHECK_CALLED(BeginningTransaction);
869 /* QueryInterface_IHttpNegotiate2 and GetRootSecurityId
870 * called on WinXP but not on Win98 */
871 CLEAR_CALLED(QueryInterface_IHttpNegotiate2);
872 CLEAR_CALLED(GetRootSecurityId);
873 CHECK_CALLED(OnProgress_FINDINGRESOURCE);
874 CHECK_CALLED(OnProgress_CONNECTING);
875 CHECK_CALLED(OnProgress_SENDINGREQUEST);
876 todo_wine CHECK_CALLED(OnResponse);
877 todo_wine { CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE); }
878 }else {
879 todo_wine CHECK_NOT_CALLED(QueryInterface_IServiceProvider);
880 CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
882 CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
883 if(test_protocol == HTTP_TEST)
884 CHECK_CALLED(OnProgress_DOWNLOADINGDATA);
885 CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
886 CHECK_CALLED(OnDataAvailable);
887 CHECK_CALLED(OnStopBinding);
890 ok(IMoniker_Release(mon) == 0, "mon should be destroyed here\n");
891 ok(IBindCtx_Release(bctx) == 0, "bctx should be destroyed here\n");
894 static void set_file_url(void)
896 int len;
898 static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
900 memcpy(INDEX_HTML, wszFile, sizeof(wszFile));
901 len = sizeof(wszFile)/sizeof(WCHAR);
902 INDEX_HTML[len++] = '/';
903 len += GetCurrentDirectoryW(sizeof(INDEX_HTML)/sizeof(WCHAR)-len, INDEX_HTML+len);
904 INDEX_HTML[len++] = '\\';
905 memcpy(INDEX_HTML+len, wszIndexHtml, sizeof(wszIndexHtml));
908 static void create_file(void)
910 HANDLE file;
911 DWORD size;
913 static const char html_doc[] = "<HTML></HTML>";
915 file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
916 FILE_ATTRIBUTE_NORMAL, NULL);
917 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
918 if(file == INVALID_HANDLE_VALUE)
919 return;
921 WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
922 CloseHandle(file);
924 set_file_url();
927 static void test_BindToStorage_fail(void)
929 IMoniker *mon = NULL;
930 IBindCtx *bctx = NULL;
931 IUnknown *unk;
932 HRESULT hres;
934 hres = CreateURLMoniker(NULL, ABOUT_BLANK, &mon);
935 ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
936 if(FAILED(hres))
937 return;
939 hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
940 ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
942 hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk);
943 ok(hres == MK_E_SYNTAX, "hres=%08x, expected INET_E_SYNTAX\n", hres);
945 IBindCtx_Release(bctx);
947 IMoniker_Release(mon);
950 START_TEST(url)
952 test_create();
953 test_CreateAsyncBindCtx();
954 test_CreateAsyncBindCtxEx();
956 trace("http test...\n");
957 test_BindToStorage(HTTP_TEST, FALSE);
959 trace("about test...\n");
960 CoInitialize(NULL);
961 test_BindToStorage(ABOUT_TEST, FALSE);
962 CoUninitialize();
964 trace("emulated about test...\n");
965 test_BindToStorage(ABOUT_TEST, TRUE);
967 trace("file test...\n");
968 create_file();
969 test_BindToStorage(FILE_TEST, FALSE);
970 DeleteFileW(wszIndexHtml);
972 trace("emulated file test...\n");
973 set_file_url();
974 test_BindToStorage(FILE_TEST, TRUE);
976 trace("emulated its test...\n");
977 test_BindToStorage(ITS_TEST, TRUE);
979 trace("emulated mk test...\n");
980 test_BindToStorage(MK_TEST, TRUE);
982 test_BindToStorage_fail();