wintrust: Add a helper function to initialize chain creation parameters.
[wine] / dlls / urlmon / tests / url.c
1 /*
2  * UrlMon URL tests
3  *
4  * Copyright 2004 Kevin Koltzau
5  * Copyright 2004 Jacek Caban
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "urlmon.h"
31 #include "wininet.h"
32
33 #include "wine/test.h"
34
35 #define DEFINE_EXPECT(func) \
36     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
37
38 #define SET_EXPECT(func) \
39     expect_ ## func = TRUE
40
41 #define CHECK_EXPECT(func) \
42     do { \
43         ok(expect_ ##func, "unexpected call " #func "\n"); \
44         expect_ ## func = FALSE; \
45         called_ ## func = TRUE; \
46     }while(0)
47
48 #define CHECK_EXPECT2(func) \
49     do { \
50         ok(expect_ ##func, "unexpected call " #func "\n"); \
51         called_ ## func = TRUE; \
52     }while(0)
53
54 #define CHECK_CALLED(func) \
55     do { \
56         ok(called_ ## func, "expected " #func "\n"); \
57         expect_ ## func = called_ ## func = FALSE; \
58     }while(0)
59
60 #define CHECK_NOT_CALLED(func) \
61     do { \
62         ok(!called_ ## func, "unexpected " #func "\n"); \
63         expect_ ## func = called_ ## func = FALSE; \
64     }while(0)
65
66 #define CLEAR_CALLED(func) \
67     expect_ ## func = called_ ## func = FALSE
68
69 DEFINE_EXPECT(QueryInterface_IServiceProvider);
70 DEFINE_EXPECT(QueryInterface_IHttpNegotiate);
71 DEFINE_EXPECT(QueryInterface_IBindStatusCallback);
72 DEFINE_EXPECT(QueryInterface_IBindStatusCallbackHolder);
73 DEFINE_EXPECT(QueryInterface_IInternetBindInfo);
74 DEFINE_EXPECT(QueryInterface_IAuthenticate);
75 DEFINE_EXPECT(QueryInterface_IInternetProtocol);
76 DEFINE_EXPECT(QueryService_IAuthenticate);
77 DEFINE_EXPECT(QueryService_IInternetProtocol);
78 DEFINE_EXPECT(BeginningTransaction);
79 DEFINE_EXPECT(OnResponse);
80 DEFINE_EXPECT(QueryInterface_IHttpNegotiate2);
81 DEFINE_EXPECT(GetRootSecurityId);
82 DEFINE_EXPECT(GetBindInfo);
83 DEFINE_EXPECT(OnStartBinding);
84 DEFINE_EXPECT(OnProgress_FINDINGRESOURCE);
85 DEFINE_EXPECT(OnProgress_CONNECTING);
86 DEFINE_EXPECT(OnProgress_SENDINGREQUEST);
87 DEFINE_EXPECT(OnProgress_MIMETYPEAVAILABLE);
88 DEFINE_EXPECT(OnProgress_BEGINDOWNLOADDATA);
89 DEFINE_EXPECT(OnProgress_DOWNLOADINGDATA);
90 DEFINE_EXPECT(OnProgress_ENDDOWNLOADDATA);
91 DEFINE_EXPECT(OnStopBinding);
92 DEFINE_EXPECT(OnDataAvailable);
93 DEFINE_EXPECT(Start);
94 DEFINE_EXPECT(Read);
95 DEFINE_EXPECT(LockRequest);
96 DEFINE_EXPECT(Terminate);
97 DEFINE_EXPECT(UnlockRequest);
98
99 static const WCHAR TEST_URL_1[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g','/','\0'};
100 static const WCHAR TEST_PART_URL_1[] = {'/','t','e','s','t','/','\0'};
101
102 static const WCHAR WINE_ABOUT_URL[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
103                                        'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
104 static const WCHAR SHORT_RESPONSE_URL[] =
105         {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.',
106          'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/',
107          'p','o','s','t','t','e','s','t','.','p','h','p',0};
108 static const WCHAR ABOUT_BLANK[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
109 static WCHAR INDEX_HTML[MAX_PATH];
110 static const WCHAR ITS_URL[] =
111     {'i','t','s',':','t','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0};
112 static const WCHAR MK_URL[] = {'m','k',':','@','M','S','I','T','S','t','o','r','e',':',
113     't','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0};
114
115 static WCHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
116
117 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
118
119 static BOOL stopped_binding = FALSE, emulate_protocol = FALSE,
120     data_available = FALSE, http_is_first = TRUE;
121 static DWORD read = 0, bindf = 0;
122 static CHAR mime_type[512];
123
124 extern IID IID_IBindStatusCallbackHolder;
125
126 static LPCWSTR urls[] = {
127     WINE_ABOUT_URL,
128     ABOUT_BLANK,
129     INDEX_HTML,
130     ITS_URL,
131     MK_URL
132 };
133
134 static enum {
135     HTTP_TEST,
136     ABOUT_TEST,
137     FILE_TEST,
138     ITS_TEST,
139     MK_TEST
140 } test_protocol;
141
142 static enum {
143     BEFORE_DOWNLOAD,
144     DOWNLOADING,
145     END_DOWNLOAD
146 } download_state;
147
148 static const char *debugstr_guid(REFIID riid)
149 {
150     static char buf[50];
151
152     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
153             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
154             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
155             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
156
157     return buf;
158 }
159
160 static void test_CreateURLMoniker(LPCWSTR url1, LPCWSTR url2)
161 {
162     HRESULT hr;
163     IMoniker *mon1 = NULL;
164     IMoniker *mon2 = NULL;
165
166     hr = CreateURLMoniker(NULL, url1, &mon1);
167     ok(SUCCEEDED(hr), "failed to create moniker: 0x%08x\n", hr);
168     if(SUCCEEDED(hr)) {
169         hr = CreateURLMoniker(mon1, url2, &mon2);
170         ok(SUCCEEDED(hr), "failed to create moniker: 0x%08x\n", hr);
171     }
172     if(mon1) IMoniker_Release(mon1);
173     if(mon2) IMoniker_Release(mon2);
174 }
175
176 static void test_create(void)
177 {
178     test_CreateURLMoniker(TEST_URL_1, TEST_PART_URL_1);
179 }
180
181 static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
182 {
183     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
184         *ppv = iface;
185         return S_OK;
186     }
187
188     *ppv = NULL;
189     return E_NOINTERFACE;
190 }
191
192 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
193 {
194     return 2;
195 }
196
197 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
198 {
199     return 1;
200 }
201
202 static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
203         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
204         DWORD grfPI, DWORD dwReserved)
205 {
206     BINDINFO bindinfo, bi = {sizeof(bi), 0};
207     DWORD bindf, bscf = BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION;
208     WCHAR null_char = 0;
209     HRESULT hres;
210
211     static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
212
213     CHECK_EXPECT(Start);
214
215     read = 0;
216
217     ok(szUrl && !lstrcmpW(szUrl, urls[test_protocol]), "wrong url\n");
218     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
219     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
220     ok(grfPI == 0, "grfPI=%d, expected 0\n", grfPI);
221     ok(dwReserved == 0, "dwReserved=%d, expected 0\n", dwReserved);
222
223     memset(&bindinfo, 0, sizeof(bindinfo));
224     bindinfo.cbSize = sizeof(bindinfo);
225     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
226     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
227
228     if(test_protocol == FILE_TEST || test_protocol == MK_TEST) {
229         ok(bindf == (BINDF_ASYNCHRONOUS|BINDF_ASYNCSTORAGE|BINDF_PULLDATA
230                      |BINDF_FROMURLMON),
231            "bindf=%08x\n", bindf);
232     }else {
233         ok(bindf == (BINDF_ASYNCHRONOUS|BINDF_ASYNCSTORAGE|BINDF_PULLDATA|
234                      BINDF_FROMURLMON|BINDF_NEEDFILE),
235            "bindf=%08x\n", bindf);
236     }
237
238     ok(!memcmp(&bindinfo, &bi, sizeof(bindinfo)), "wrong bindinfo\n");
239
240     switch(test_protocol) {
241     case MK_TEST:
242         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
243                 BINDSTATUS_DIRECTBIND, NULL);
244         ok(hres == S_OK,
245            "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
246
247     case FILE_TEST:
248     case ITS_TEST:
249         SET_EXPECT(OnProgress_SENDINGREQUEST);
250         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
251                 BINDSTATUS_SENDINGREQUEST, &null_char);
252         ok(hres == S_OK,
253            "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
254         CHECK_CALLED(OnProgress_SENDINGREQUEST);
255     default:
256         break;
257     }
258
259     if(test_protocol == FILE_TEST) {
260         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
261                 BINDSTATUS_CACHEFILENAMEAVAILABLE, &null_char);
262         ok(hres == S_OK,
263            "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
264
265         SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
266         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
267                 BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, wszTextHtml);
268         ok(hres == S_OK,
269            "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
270         CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
271     }else {
272         hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
273                 BINDSTATUS_MIMETYPEAVAILABLE, wszTextHtml);
274         ok(hres == S_OK,
275            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
276     }
277
278     if(test_protocol == ABOUT_TEST)
279         bscf |= BSCF_DATAFULLYAVAILABLE;
280     if(test_protocol == ITS_TEST)
281         bscf = BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE;
282
283     SET_EXPECT(Read);
284     if(test_protocol != FILE_TEST && test_protocol != MK_TEST)
285         SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
286     SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
287     SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
288     SET_EXPECT(LockRequest);
289     SET_EXPECT(OnDataAvailable);
290     SET_EXPECT(OnStopBinding);
291
292     hres = IInternetProtocolSink_ReportData(pOIProtSink, bscf, 13, 13);
293     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
294
295     CHECK_CALLED(Read);
296     if(test_protocol != FILE_TEST && test_protocol != MK_TEST)
297         CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
298     CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
299     CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
300     CHECK_CALLED(LockRequest);
301     CHECK_CALLED(OnDataAvailable);
302     CHECK_CALLED(OnStopBinding);
303
304     if(test_protocol == ITS_TEST) {
305         SET_EXPECT(Read);
306         hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
307         ok(hres == S_OK, "ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres);
308         CHECK_CALLED(Read);
309     }
310
311     SET_EXPECT(Terminate);
312     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
313     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
314     CHECK_CALLED(Terminate);
315
316     return S_OK;
317 }
318
319 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
320         PROTOCOLDATA *pProtocolData)
321 {
322     ok(0, "unexpected call\n");
323     return E_NOTIMPL;
324 }
325
326 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
327         DWORD dwOptions)
328 {
329     ok(0, "unexpected call\n");
330     return E_NOTIMPL;
331 }
332
333 static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
334 {
335     CHECK_EXPECT(Terminate);
336     ok(dwOptions == 0, "dwOptions=%d, expected 0\n", dwOptions);
337     return S_OK;
338 }
339
340 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
341 {
342     ok(0, "unexpected call\n");
343     return E_NOTIMPL;
344 }
345
346 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
347 {
348     ok(0, "unexpected call\n");
349     return E_NOTIMPL;
350 }
351
352 static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv,
353         ULONG cb, ULONG *pcbRead)
354 {
355     static const char data[] = "<HTML></HTML>";
356
357     CHECK_EXPECT2(Read);
358
359     if(read) {
360         *pcbRead = 0;
361         return S_FALSE;
362     }
363
364     ok(pv != NULL, "pv == NULL\n");
365     ok(cb != 0, "cb == 0\n");
366     ok(pcbRead != NULL, "pcbRead == NULL\n");
367     if(pcbRead) {
368         ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
369         read += *pcbRead = sizeof(data)-1;
370     }
371     if(pv)
372         memcpy(pv, data, sizeof(data));
373
374     return S_OK;
375 }
376
377 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
378         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
379 {
380     ok(0, "unexpected call\n");
381     return E_NOTIMPL;
382 }
383
384 static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
385 {
386     CHECK_EXPECT(LockRequest);
387     return S_OK;
388 }
389
390 static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface)
391 {
392     CHECK_EXPECT(UnlockRequest);
393     return S_OK;
394 }
395
396 static const IInternetProtocolVtbl ProtocolVtbl = {
397     Protocol_QueryInterface,
398     Protocol_AddRef,
399     Protocol_Release,
400     Protocol_Start,
401     Protocol_Continue,
402     Protocol_Abort,
403     Protocol_Terminate,
404     Protocol_Suspend,
405     Protocol_Resume,
406     Protocol_Read,
407     Protocol_Seek,
408     Protocol_LockRequest,
409     Protocol_UnlockRequest
410 };
411
412 static IInternetProtocol Protocol = { &ProtocolVtbl };
413
414 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
415 {
416     if(IsEqualGUID(&IID_IUnknown, riid)
417             || IsEqualGUID(&IID_IHttpNegotiate, riid)
418             || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
419         *ppv = iface;
420         return S_OK;
421     }
422
423     ok(0, "unexpected call\n");
424     return E_NOINTERFACE;
425 }
426
427 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
428 {
429     return 2;
430 }
431
432 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
433 {
434     return 1;
435 }
436
437 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
438         LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
439 {
440     CHECK_EXPECT(BeginningTransaction);
441
442     ok(!lstrcmpW(szURL, urls[test_protocol]), "szURL != urls[test_protocol]\n");
443     ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
444     ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
445     if(pszAdditionalHeaders)
446         ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
447
448     return S_OK;
449 }
450
451 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
452         LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
453 {
454     CHECK_EXPECT(OnResponse);
455
456     ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
457     ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
458     ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
459     /* Note: in protocol.c tests, OnResponse pszAdditionalRequestHeaders _is_ NULL */
460     ok(pszAdditionalRequestHeaders != NULL, "pszAdditionalHeaders == NULL\n");
461     if(pszAdditionalRequestHeaders)
462         ok(*pszAdditionalRequestHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
463
464     return S_OK;
465 }
466
467 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
468         BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
469 {
470     static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
471
472     CHECK_EXPECT(GetRootSecurityId);
473
474     ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
475     ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
476     ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
477
478     if(pbSecurityId == (void*)0xdeadbeef)
479         return E_NOTIMPL;
480
481     if(pcbSecurityId) {
482         ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
483         *pcbSecurityId = sizeof(sec_id);
484     }
485
486     if(pbSecurityId)
487         memcpy(pbSecurityId, sec_id, sizeof(sec_id));
488
489     return E_FAIL;
490 }
491
492 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
493     HttpNegotiate_QueryInterface,
494     HttpNegotiate_AddRef,
495     HttpNegotiate_Release,
496     HttpNegotiate_BeginningTransaction,
497     HttpNegotiate_OnResponse,
498     HttpNegotiate_GetRootSecurityId
499 };
500
501 static IHttpNegotiate2 HttpNegotiate = { &HttpNegotiateVtbl };
502
503 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
504 {
505     ok(0, "unexpected call\n");
506     return E_NOINTERFACE;
507 }
508
509 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
510 {
511     return 2;
512 }
513
514 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
515 {
516     return 1;
517 }
518
519 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
520         REFGUID guidService, REFIID riid, void **ppv)
521 {
522     if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
523         CHECK_EXPECT(QueryService_IAuthenticate);
524         return E_NOTIMPL;
525     }
526
527     if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
528         CHECK_EXPECT2(QueryService_IInternetProtocol);
529         return E_NOTIMPL;
530     }
531
532     ok(0, "unexpected service %s\n", debugstr_guid(guidService));
533     return E_NOINTERFACE;
534 }
535
536 static IServiceProviderVtbl ServiceProviderVtbl = {
537     ServiceProvider_QueryInterface,
538     ServiceProvider_AddRef,
539     ServiceProvider_Release,
540     ServiceProvider_QueryService
541 };
542
543 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
544
545 static HRESULT WINAPI statusclb_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
546 {
547     if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
548         CHECK_EXPECT2(QueryInterface_IInternetProtocol);
549         if(emulate_protocol) {
550             *ppv = &Protocol;
551             return S_OK;
552         }else {
553             return E_NOINTERFACE;
554         }
555     }
556     else if (IsEqualGUID(&IID_IServiceProvider, riid))
557     {
558         CHECK_EXPECT2(QueryInterface_IServiceProvider);
559         *ppv = &ServiceProvider;
560         return S_OK;
561     }
562     else if (IsEqualGUID(&IID_IHttpNegotiate, riid))
563     {
564         CHECK_EXPECT(QueryInterface_IHttpNegotiate);
565         *ppv = &HttpNegotiate;
566         return S_OK;
567     }
568     else if (IsEqualGUID(&IID_IHttpNegotiate2, riid))
569     {
570         CHECK_EXPECT(QueryInterface_IHttpNegotiate2);
571         *ppv = &HttpNegotiate;
572         return S_OK;
573     }
574     else if (IsEqualGUID(&IID_IAuthenticate, riid))
575     {
576         CHECK_EXPECT(QueryInterface_IAuthenticate);
577         return E_NOINTERFACE;
578     }
579     else if(IsEqualGUID(&IID_IBindStatusCallback, riid))
580     {
581         CHECK_EXPECT2(QueryInterface_IBindStatusCallback);
582         *ppv = iface;
583         return S_OK;
584     }
585     else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid))
586     {
587         CHECK_EXPECT2(QueryInterface_IBindStatusCallbackHolder);
588         return E_NOINTERFACE;
589     }
590     else if(IsEqualGUID(&IID_IInternetBindInfo, riid))
591     {
592         /* TODO */
593         CHECK_EXPECT(QueryInterface_IInternetBindInfo);
594     }
595     else
596     {
597         ok(0, "unexpected interface %s\n", debugstr_guid(riid));
598     }
599
600     return E_NOINTERFACE;
601 }
602
603 static ULONG WINAPI statusclb_AddRef(IBindStatusCallback *iface)
604 {
605     return 2;
606 }
607
608 static ULONG WINAPI statusclb_Release(IBindStatusCallback *iface)
609 {
610     return 1;
611 }
612
613 static HRESULT WINAPI statusclb_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
614         IBinding *pib)
615 {
616     HRESULT hres;
617     IMoniker *mon;
618
619     CHECK_EXPECT(OnStartBinding);
620
621     ok(pib != NULL, "pib should not be NULL\n");
622     ok(dwReserved == 0xff, "dwReserved=%x\n", dwReserved);
623
624     if(pib == (void*)0xdeadbeef)
625         return S_OK;
626
627     hres = IBinding_QueryInterface(pib, &IID_IMoniker, (void**)&mon);
628     ok(hres == E_NOINTERFACE, "IBinding should not have IMoniker interface\n");
629     if(SUCCEEDED(hres))
630         IMoniker_Release(mon);
631
632     return S_OK;
633 }
634
635 static HRESULT WINAPI statusclb_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
636 {
637     ok(0, "unexpected call\n");
638     return E_NOTIMPL;
639 }
640
641 static HRESULT WINAPI statusclb_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
642 {
643     ok(0, "unexpected call\n");
644     return E_NOTIMPL;
645 }
646
647 static HRESULT WINAPI statusclb_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
648         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
649 {
650     switch(ulStatusCode) {
651     case BINDSTATUS_FINDINGRESOURCE:
652         CHECK_EXPECT(OnProgress_FINDINGRESOURCE);
653         break;
654     case BINDSTATUS_CONNECTING:
655         CHECK_EXPECT(OnProgress_CONNECTING);
656         break;
657     case BINDSTATUS_SENDINGREQUEST:
658         CHECK_EXPECT(OnProgress_SENDINGREQUEST);
659         break;
660     case BINDSTATUS_MIMETYPEAVAILABLE:
661         CHECK_EXPECT(OnProgress_MIMETYPEAVAILABLE);
662         ok(download_state == BEFORE_DOWNLOAD, "Download state was %d, expected BEFORE_DOWNLOAD\n",
663            download_state);
664         WideCharToMultiByte(CP_ACP, 0, szStatusText, -1, mime_type, sizeof(mime_type)-1, NULL, NULL);
665         break;
666     case BINDSTATUS_BEGINDOWNLOADDATA:
667         CHECK_EXPECT(OnProgress_BEGINDOWNLOADDATA);
668         ok(szStatusText != NULL, "szStatusText == NULL\n");
669         if(szStatusText)
670             ok(!lstrcmpW(szStatusText, urls[test_protocol]), "wrong szStatusText\n");
671         ok(download_state == BEFORE_DOWNLOAD, "Download state was %d, expected BEFORE_DOWNLOAD\n",
672            download_state);
673         download_state = DOWNLOADING;
674         break;
675     case BINDSTATUS_DOWNLOADINGDATA:
676         CHECK_EXPECT2(OnProgress_DOWNLOADINGDATA);
677         ok(download_state == DOWNLOADING, "Download state was %d, expected DOWNLOADING\n",
678            download_state);
679         break;
680     case BINDSTATUS_ENDDOWNLOADDATA:
681         CHECK_EXPECT(OnProgress_ENDDOWNLOADDATA);
682         ok(szStatusText != NULL, "szStatusText == NULL\n");
683         if(szStatusText)
684             ok(!lstrcmpW(szStatusText, urls[test_protocol]), "wrong szStatusText\n");
685         ok(download_state == DOWNLOADING, "Download state was %d, expected DOWNLOADING\n",
686            download_state);
687         download_state = END_DOWNLOAD;
688         break;
689     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
690         ok(szStatusText != NULL, "szStatusText == NULL\n");
691         if(szStatusText && test_protocol == FILE_TEST)
692             ok(!lstrcmpW(INDEX_HTML+7, szStatusText), "wrong szStatusText\n");
693         break;
694     default:
695         todo_wine { ok(0, "unexpexted code %d\n", ulStatusCode); }
696     };
697     return S_OK;
698 }
699
700 static HRESULT WINAPI statusclb_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
701 {
702     CHECK_EXPECT(OnStopBinding);
703
704     /* ignore DNS failure */
705     if (hresult != HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED))
706     {
707         ok(SUCCEEDED(hresult), "Download failed: %08x\n", hresult);
708         ok(szError == NULL, "szError should be NULL\n");
709     }
710     stopped_binding = TRUE;
711
712     return S_OK;
713 }
714
715 static HRESULT WINAPI statusclb_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
716 {
717     DWORD cbSize;
718
719     CHECK_EXPECT(GetBindInfo);
720
721     *grfBINDF = bindf;
722     cbSize = pbindinfo->cbSize;
723     memset(pbindinfo, 0, cbSize);
724     pbindinfo->cbSize = cbSize;
725
726     return S_OK;
727 }
728
729 static HRESULT WINAPI statusclb_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
730         DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
731 {
732     HRESULT hres;
733     DWORD readed;
734     BYTE buf[512];
735     CHAR clipfmt[512];
736
737     CHECK_EXPECT2(OnDataAvailable);
738     ok(download_state == DOWNLOADING || download_state == END_DOWNLOAD,
739        "Download state was %d, expected DOWNLOADING or END_DOWNLOAD\n",
740        download_state);
741     data_available = TRUE;
742
743     ok(pformatetc != NULL, "pformatetx == NULL\n");
744     if(pformatetc) {
745         if (mime_type[0]) todo_wine {
746             clipfmt[0] = 0;
747             ok(GetClipboardFormatName(pformatetc->cfFormat, clipfmt, sizeof(clipfmt)-1),
748                "GetClipboardFormatName failed, error %d\n", GetLastError());
749             ok(!lstrcmp(clipfmt, mime_type), "clipformat != mime_type, \"%s\" != \"%s\"\n",
750                clipfmt, mime_type);
751         } else {
752             ok(pformatetc->cfFormat == 0, "clipformat=%x\n", pformatetc->cfFormat);
753         }
754         ok(pformatetc->ptd == NULL, "ptd = %p\n", pformatetc->ptd);
755         ok(pformatetc->dwAspect == 1, "dwAspect=%u\n", pformatetc->dwAspect);
756         ok(pformatetc->lindex == -1, "lindex=%d\n", pformatetc->lindex);
757         ok(pformatetc->tymed == TYMED_ISTREAM, "tymed=%u\n", pformatetc->tymed);
758     }
759
760     ok(pstgmed != NULL, "stgmeg == NULL\n");
761     if(pstgmed) {
762         ok(pstgmed->tymed == TYMED_ISTREAM, "tymed=%u\n", pstgmed->tymed);
763         ok(U(*pstgmed).pstm != NULL, "pstm == NULL\n");
764         ok(pstgmed->pUnkForRelease != NULL, "pUnkForRelease == NULL\n");
765     }
766
767     if(U(*pstgmed).pstm) {
768         do hres = IStream_Read(U(*pstgmed).pstm, buf, 512, &readed);
769         while(hres == S_OK);
770         ok(hres == S_FALSE || hres == E_PENDING, "IStream_Read returned %08x\n", hres);
771     }
772
773     return S_OK;
774 }
775
776 static HRESULT WINAPI statusclb_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
777 {
778     ok(0, "unexpected call\n");
779     return E_NOTIMPL;
780 }
781
782 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
783     statusclb_QueryInterface,
784     statusclb_AddRef,
785     statusclb_Release,
786     statusclb_OnStartBinding,
787     statusclb_GetPriority,
788     statusclb_OnLowResource,
789     statusclb_OnProgress,
790     statusclb_OnStopBinding,
791     statusclb_GetBindInfo,
792     statusclb_OnDataAvailable,
793     statusclb_OnObjectAvailable
794 };
795
796 static IBindStatusCallback bsc = { &BindStatusCallbackVtbl };
797
798 static void test_CreateAsyncBindCtx(void)
799 {
800     IBindCtx *bctx = (IBindCtx*)0x0ff00ff0;
801     IUnknown *unk;
802     HRESULT hres;
803     ULONG ref;
804     BIND_OPTS bindopts;
805
806     hres = CreateAsyncBindCtx(0, NULL, NULL, &bctx);
807     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08x\n", hres);
808     ok(bctx == (IBindCtx*)0x0ff00ff0, "bctx should not be changed\n");
809
810     hres = CreateAsyncBindCtx(0, NULL, NULL, NULL);
811     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed. expected: E_INVALIDARG, got: %08x\n", hres);
812
813     SET_EXPECT(QueryInterface_IServiceProvider);
814     hres = CreateAsyncBindCtx(0, &bsc, NULL, &bctx);
815     ok(hres == S_OK, "CreateAsyncBindCtx failed: %08x\n", hres);
816     CHECK_CALLED(QueryInterface_IServiceProvider);
817
818     bindopts.cbStruct = sizeof(bindopts);
819     hres = IBindCtx_GetBindOptions(bctx, &bindopts);
820     ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08x\n", hres);
821     ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
822                 "bindopts.grfFlags = %08x, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
823     ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
824                 "bindopts.grfMode = %08x, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
825                 bindopts.grfMode);
826     ok(bindopts.dwTickCountDeadline == 0,
827                 "bindopts.dwTickCountDeadline = %08x, expected: 0\n", bindopts.dwTickCountDeadline);
828
829     hres = IBindCtx_QueryInterface(bctx, &IID_IAsyncBindCtx, (void**)&unk);
830     ok(hres == E_NOINTERFACE, "QueryInterface(IID_IAsyncBindCtx) failed: %08x, expected E_NOINTERFACE\n", hres);
831     if(SUCCEEDED(hres))
832         IUnknown_Release(unk);
833
834     ref = IBindCtx_Release(bctx);
835     ok(ref == 0, "bctx should be destroyed here\n");
836 }
837
838 static void test_CreateAsyncBindCtxEx(void)
839 {
840     IBindCtx *bctx = NULL, *bctx_arg = NULL;
841     IUnknown *unk;
842     BIND_OPTS bindopts;
843     HRESULT hres;
844
845     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, NULL, 0);
846     ok(hres == E_INVALIDARG, "CreateAsyncBindCtx failed: %08x, expected E_INVALIDARG\n", hres);
847
848     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
849     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
850
851     if(SUCCEEDED(hres)) {
852         bindopts.cbStruct = sizeof(bindopts);
853         hres = IBindCtx_GetBindOptions(bctx, &bindopts);
854         ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08x\n", hres);
855         ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
856                 "bindopts.grfFlags = %08x, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
857         ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
858                 "bindopts.grfMode = %08x, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
859                 bindopts.grfMode);
860         ok(bindopts.dwTickCountDeadline == 0,
861                 "bindopts.dwTickCountDeadline = %08x, expected: 0\n", bindopts.dwTickCountDeadline);
862
863         IBindCtx_Release(bctx);
864     }
865
866     CreateBindCtx(0, &bctx_arg);
867     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
868     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
869
870     if(SUCCEEDED(hres)) {
871         bindopts.cbStruct = sizeof(bindopts);
872         hres = IBindCtx_GetBindOptions(bctx, &bindopts);
873         ok(SUCCEEDED(hres), "IBindCtx_GetBindOptions failed: %08x\n", hres);
874         ok(bindopts.grfFlags == BIND_MAYBOTHERUSER,
875                 "bindopts.grfFlags = %08x, expected: BIND_MAYBOTHERUSER\n", bindopts.grfFlags);
876         ok(bindopts.grfMode == (STGM_READWRITE | STGM_SHARE_EXCLUSIVE),
877                 "bindopts.grfMode = %08x, expected: STGM_READWRITE | STGM_SHARE_EXCLUSIVE\n",
878                 bindopts.grfMode);
879         ok(bindopts.dwTickCountDeadline == 0,
880                 "bindopts.dwTickCountDeadline = %08x, expected: 0\n", bindopts.dwTickCountDeadline);
881
882         IBindCtx_Release(bctx);
883     }
884
885     IBindCtx_Release(bctx_arg);
886
887     SET_EXPECT(QueryInterface_IServiceProvider);
888     hres = CreateAsyncBindCtxEx(NULL, 0, &bsc, NULL, &bctx, 0);
889     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
890     CHECK_CALLED(QueryInterface_IServiceProvider);
891
892     hres = IBindCtx_QueryInterface(bctx, &IID_IAsyncBindCtx, (void**)&unk);
893     ok(hres == S_OK, "QueryInterface(IID_IAsyncBindCtx) failed: %08x\n", hres);
894     if(SUCCEEDED(hres))
895         IUnknown_Release(unk);
896
897     if(SUCCEEDED(hres))
898         IBindCtx_Release(bctx);
899 }
900
901 static void test_bscholder(IBindStatusCallback *holder)
902 {
903     IServiceProvider *serv_prov;
904     IHttpNegotiate *http_negotiate, *http_negotiate_serv;
905     IHttpNegotiate2 *http_negotiate2, *http_negotiate2_serv;
906     IAuthenticate *authenticate, *authenticate_serv;
907     IInternetProtocol *protocol;
908     BINDINFO bindinfo = {sizeof(bindinfo)};
909     LPWSTR wstr;
910     DWORD dw;
911     HRESULT hres;
912
913     static const WCHAR emptyW[] = {0};
914
915     hres = IBindStatusCallback_QueryInterface(holder, &IID_IServiceProvider, (void**)&serv_prov);
916     ok(hres == S_OK, "Could not get IServiceProvider interface: %08x\n", hres);
917
918     dw = 0xdeadbeef;
919     SET_EXPECT(GetBindInfo);
920     hres = IBindStatusCallback_GetBindInfo(holder, &dw, &bindinfo);
921     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
922     CHECK_CALLED(GetBindInfo);
923
924     SET_EXPECT(OnStartBinding);
925     hres = IBindStatusCallback_OnStartBinding(holder, 0, (void*)0xdeadbeef);
926     ok(hres == S_OK, "OnStartBinding failed: %08x\n", hres);
927     CHECK_CALLED(OnStartBinding);
928
929     hres = IBindStatusCallback_QueryInterface(holder, &IID_IHttpNegotiate, (void**)&http_negotiate);
930     ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
931
932     wstr = (void*)0xdeadbeef;
933     hres = IHttpNegotiate_BeginningTransaction(http_negotiate, urls[test_protocol], (void*)0xdeadbeef, 0xff, &wstr);
934     ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
935     ok(wstr == NULL, "wstr = %p\n", wstr);
936
937     SET_EXPECT(QueryInterface_IHttpNegotiate);
938     hres = IServiceProvider_QueryService(serv_prov, &IID_IHttpNegotiate, &IID_IHttpNegotiate,
939                                          (void**)&http_negotiate_serv);
940     ok(hres == S_OK, "Could not get IHttpNegotiate service: %08x\n", hres);
941     CHECK_CALLED(QueryInterface_IHttpNegotiate);
942
943     ok(http_negotiate == http_negotiate_serv, "http_negotiate != http_negotiate_serv\n");
944
945     wstr = (void*)0xdeadbeef;
946     SET_EXPECT(BeginningTransaction);
947     hres = IHttpNegotiate_BeginningTransaction(http_negotiate_serv, urls[test_protocol], emptyW, 0, &wstr);
948     CHECK_CALLED(BeginningTransaction);
949     ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
950     ok(wstr == NULL, "wstr = %p\n", wstr);
951
952     IHttpNegotiate_Release(http_negotiate_serv);
953
954     hres = IServiceProvider_QueryService(serv_prov, &IID_IHttpNegotiate, &IID_IHttpNegotiate,
955                                          (void**)&http_negotiate_serv);
956     ok(hres == S_OK, "Could not get IHttpNegotiate service: %08x\n", hres);
957     ok(http_negotiate == http_negotiate_serv, "http_negotiate != http_negotiate_serv\n");
958     IHttpNegotiate_Release(http_negotiate_serv);
959
960     hres = IBindStatusCallback_QueryInterface(holder, &IID_IHttpNegotiate2, (void**)&http_negotiate2);
961     ok(hres == S_OK, "Could not get IHttpNegotiate2 interface: %08x\n", hres);
962
963     hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, (void*)0xdeadbeef, (void*)0xdeadbeef, 0);
964     ok(hres == E_FAIL, "GetRootSecurityId failed: %08x\n", hres);
965
966     IHttpNegotiate_Release(http_negotiate2);
967
968     SET_EXPECT(QueryInterface_IHttpNegotiate2);
969     hres = IServiceProvider_QueryService(serv_prov, &IID_IHttpNegotiate2, &IID_IHttpNegotiate2,
970                                          (void**)&http_negotiate2_serv);
971     ok(hres == S_OK, "Could not get IHttpNegotiate2 service: %08x\n", hres);
972     CHECK_CALLED(QueryInterface_IHttpNegotiate2);
973     ok(http_negotiate2 == http_negotiate2_serv, "http_negotiate != http_negotiate_serv\n");
974
975     SET_EXPECT(GetRootSecurityId);
976     hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, (void*)0xdeadbeef, (void*)0xdeadbeef, 0);
977     ok(hres == E_NOTIMPL, "GetRootSecurityId failed: %08x\n", hres);
978     CHECK_CALLED(GetRootSecurityId);
979
980     IHttpNegotiate_Release(http_negotiate2_serv);
981
982     SET_EXPECT(OnProgress_FINDINGRESOURCE);
983     hres = IBindStatusCallback_OnProgress(holder, 0, 0, BINDSTATUS_FINDINGRESOURCE, NULL);
984     ok(hres == S_OK, "OnProgress failed: %08x\n", hres);
985     CHECK_CALLED(OnProgress_FINDINGRESOURCE);
986
987     SET_EXPECT(OnResponse);
988     wstr = (void*)0xdeadbeef;
989     hres = IHttpNegotiate_OnResponse(http_negotiate, 200, emptyW, NULL, NULL);
990     ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
991     CHECK_CALLED(OnResponse);
992
993     IHttpNegotiate_Release(http_negotiate);
994
995     hres = IBindStatusCallback_QueryInterface(holder, &IID_IAuthenticate, (void**)&authenticate);
996     ok(hres == S_OK, "Could not get IAuthenticate interface: %08x\n", hres);
997
998     SET_EXPECT(QueryInterface_IAuthenticate);
999     SET_EXPECT(QueryService_IAuthenticate);
1000     hres = IServiceProvider_QueryService(serv_prov, &IID_IAuthenticate, &IID_IAuthenticate,
1001                                          (void**)&authenticate_serv);
1002     ok(hres == S_OK, "Could not get IAuthenticate service: %08x\n", hres);
1003     CHECK_CALLED(QueryInterface_IAuthenticate);
1004     CHECK_CALLED(QueryService_IAuthenticate);
1005     ok(authenticate == authenticate_serv, "authenticate != authenticate_serv\n");
1006     IAuthenticate_Release(authenticate_serv);
1007
1008     hres = IServiceProvider_QueryService(serv_prov, &IID_IAuthenticate, &IID_IAuthenticate,
1009                                          (void**)&authenticate_serv);
1010     ok(hres == S_OK, "Could not get IAuthenticate service: %08x\n", hres);
1011     ok(authenticate == authenticate_serv, "authenticate != authenticate_serv\n");
1012
1013     IAuthenticate_Release(authenticate);
1014     IAuthenticate_Release(authenticate_serv);
1015
1016     SET_EXPECT(OnStopBinding);
1017     hres = IBindStatusCallback_OnStopBinding(holder, S_OK, NULL);
1018     ok(hres == S_OK, "OnStopBinding failed: %08x\n", hres);
1019     CHECK_CALLED(OnStopBinding);
1020
1021     SET_EXPECT(QueryInterface_IInternetProtocol);
1022     SET_EXPECT(QueryService_IInternetProtocol);
1023     hres = IServiceProvider_QueryService(serv_prov, &IID_IInternetProtocol, &IID_IInternetProtocol,
1024                                          (void**)&protocol);
1025     ok(hres == E_NOINTERFACE, "QueryService(IInternetProtocol) failed: %08x\n", hres);
1026     CHECK_CALLED(QueryInterface_IInternetProtocol);
1027     CHECK_CALLED(QueryService_IInternetProtocol);
1028
1029     IServiceProvider_Release(serv_prov);
1030 }
1031
1032 static void test_RegisterBindStatusCallback(void)
1033 {
1034     IBindStatusCallback *prevbsc, *clb;
1035     IBindCtx *bindctx;
1036     IUnknown *unk;
1037     HRESULT hres;
1038
1039     hres = CreateBindCtx(0, &bindctx);
1040     ok(hres == S_OK, "BindCtx failed: %08x\n", hres);
1041
1042     SET_EXPECT(QueryInterface_IServiceProvider);
1043
1044     hres = IBindCtx_RegisterObjectParam(bindctx, BSCBHolder, (IUnknown*)&bsc);
1045     ok(hres == S_OK, "RegisterObjectParam failed: %08x\n", hres);
1046
1047     SET_EXPECT(QueryInterface_IBindStatusCallback);
1048     SET_EXPECT(QueryInterface_IBindStatusCallbackHolder);
1049     prevbsc = (void*)0xdeadbeef;
1050     hres = RegisterBindStatusCallback(bindctx, &bsc, &prevbsc, 0);
1051     ok(hres == S_OK, "RegisterBindStatusCallback failed: %08x\n", hres);
1052     ok(prevbsc == &bsc, "prevbsc=%p\n", prevbsc);
1053     CHECK_CALLED(QueryInterface_IBindStatusCallback);
1054     CHECK_CALLED(QueryInterface_IBindStatusCallbackHolder);
1055
1056     CHECK_CALLED(QueryInterface_IServiceProvider);
1057
1058     hres = IBindCtx_GetObjectParam(bindctx, BSCBHolder, &unk);
1059     ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
1060
1061     hres = IUnknown_QueryInterface(unk, &IID_IBindStatusCallback, (void**)&clb);
1062     IUnknown_Release(unk);
1063     ok(hres == S_OK, "QueryInterface(IID_IBindStatusCallback) failed: %08x\n", hres);
1064     ok(clb != &bsc, "bsc == clb\n");
1065
1066     test_bscholder(clb);
1067
1068     IBindStatusCallback_Release(clb);
1069
1070     hres = RevokeBindStatusCallback(bindctx, &bsc);
1071     ok(hres == S_OK, "RevokeBindStatusCallback failed: %08x\n", hres);
1072
1073     unk = (void*)0xdeadbeef;
1074     hres = IBindCtx_GetObjectParam(bindctx, BSCBHolder, &unk);
1075     ok(hres == E_FAIL, "GetObjectParam failed: %08x\n", hres);
1076     ok(unk == NULL, "unk != NULL\n");
1077
1078     if(unk)
1079         IUnknown_Release(unk);
1080
1081     hres = RevokeBindStatusCallback(bindctx, (void*)0xdeadbeef);
1082     ok(hres == S_OK, "RevokeBindStatusCallback failed: %08x\n", hres);
1083
1084     hres = RevokeBindStatusCallback(NULL, (void*)0xdeadbeef);
1085     ok(hres == E_INVALIDARG, "RevokeBindStatusCallback failed: %08x\n", hres);
1086
1087     hres = RevokeBindStatusCallback(bindctx, NULL);
1088     ok(hres == E_INVALIDARG, "RevokeBindStatusCallback failed: %08x\n", hres);
1089
1090     IBindCtx_Release(bindctx);
1091 }
1092
1093 static void test_BindToStorage(int protocol, BOOL emul)
1094 {
1095     IMoniker *mon;
1096     HRESULT hres;
1097     LPOLESTR display_name;
1098     IBindCtx *bctx;
1099     MSG msg;
1100     IBindStatusCallback *previousclb;
1101     IUnknown *unk = (IUnknown*)0x00ff00ff;
1102     IBinding *bind;
1103
1104     test_protocol = protocol;
1105     emulate_protocol = emul;
1106     download_state = BEFORE_DOWNLOAD;
1107     stopped_binding = FALSE;
1108     data_available = FALSE;
1109     mime_type[0] = 0;
1110
1111     SET_EXPECT(QueryInterface_IServiceProvider);
1112     hres = CreateAsyncBindCtx(0, &bsc, NULL, &bctx);
1113     ok(hres == S_OK, "CreateAsyncBindCtx failed: %08x\n\n", hres);
1114     CHECK_CALLED(QueryInterface_IServiceProvider);
1115     if(FAILED(hres))
1116         return;
1117
1118     SET_EXPECT(QueryInterface_IServiceProvider);
1119     hres = RegisterBindStatusCallback(bctx, &bsc, &previousclb, 0);
1120     ok(hres == S_OK, "RegisterBindStatusCallback failed: %08x\n", hres);
1121     ok(previousclb == &bsc, "previousclb(%p) != sclb(%p)\n", previousclb, &bsc);
1122     CHECK_CALLED(QueryInterface_IServiceProvider);
1123     if(previousclb)
1124         IBindStatusCallback_Release(previousclb);
1125
1126     hres = CreateURLMoniker(NULL, urls[test_protocol], &mon);
1127     ok(SUCCEEDED(hres), "failed to create moniker: %08x\n", hres);
1128     if(FAILED(hres)) {
1129         IBindCtx_Release(bctx);
1130         return;
1131     }
1132
1133     if(test_protocol == FILE_TEST && INDEX_HTML[7] == '/')
1134         memmove(INDEX_HTML+7, INDEX_HTML+8, lstrlenW(INDEX_HTML+7)*sizeof(WCHAR));
1135
1136     hres = IMoniker_QueryInterface(mon, &IID_IBinding, (void**)&bind);
1137     ok(hres == E_NOINTERFACE, "IMoniker should not have IBinding interface\n");
1138     if(SUCCEEDED(hres))
1139         IBinding_Release(bind);
1140
1141     hres = IMoniker_GetDisplayName(mon, bctx, NULL, &display_name);
1142     ok(hres == S_OK, "GetDisplayName failed %08x\n", hres);
1143     ok(!lstrcmpW(display_name, urls[test_protocol]), "GetDisplayName got wrong name\n");
1144
1145     SET_EXPECT(GetBindInfo);
1146     SET_EXPECT(QueryInterface_IInternetProtocol);
1147     if(!emulate_protocol)
1148         SET_EXPECT(QueryService_IInternetProtocol);
1149     SET_EXPECT(OnStartBinding);
1150     if(emulate_protocol) {
1151         SET_EXPECT(Start);
1152         SET_EXPECT(UnlockRequest);
1153     }else {
1154         if(test_protocol == HTTP_TEST) {
1155             SET_EXPECT(QueryInterface_IHttpNegotiate);
1156             SET_EXPECT(BeginningTransaction);
1157             SET_EXPECT(QueryInterface_IHttpNegotiate2);
1158             SET_EXPECT(GetRootSecurityId);
1159             SET_EXPECT(OnProgress_FINDINGRESOURCE);
1160             SET_EXPECT(OnProgress_CONNECTING);
1161         }
1162         if(test_protocol == HTTP_TEST || test_protocol == FILE_TEST)
1163             SET_EXPECT(OnProgress_SENDINGREQUEST);
1164         if(test_protocol == HTTP_TEST)
1165             SET_EXPECT(OnResponse);
1166         SET_EXPECT(OnProgress_MIMETYPEAVAILABLE);
1167         SET_EXPECT(OnProgress_BEGINDOWNLOADDATA);
1168         if(test_protocol == HTTP_TEST)
1169             SET_EXPECT(OnProgress_DOWNLOADINGDATA);
1170         SET_EXPECT(OnProgress_ENDDOWNLOADDATA);
1171         SET_EXPECT(OnDataAvailable);
1172         SET_EXPECT(OnStopBinding);
1173     }
1174
1175     hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk);
1176     if (test_protocol == HTTP_TEST && hres == HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED))
1177     {
1178         trace( "Network unreachable, skipping tests\n" );
1179         return;
1180     }
1181     if (!SUCCEEDED(hres)) return;
1182
1183     if((bindf & BINDF_ASYNCHRONOUS) && !data_available) {
1184         ok(hres == MK_S_ASYNCHRONOUS, "IMoniker_BindToStorage failed: %08x\n", hres);
1185         ok(unk == NULL, "istr should be NULL\n");
1186     }else {
1187         ok(hres == S_OK, "IMoniker_BindToStorage failed: %08x\n", hres);
1188         ok(unk != NULL, "unk == NULL\n");
1189     }
1190     if(unk)
1191         IUnknown_Release(unk);
1192
1193     while((bindf & BINDF_ASYNCHRONOUS) &&
1194           !stopped_binding && GetMessage(&msg,NULL,0,0)) {
1195         TranslateMessage(&msg);
1196         DispatchMessage(&msg);
1197     }
1198
1199     CHECK_CALLED(GetBindInfo);
1200     CHECK_CALLED(QueryInterface_IInternetProtocol);
1201     if(!emulate_protocol)
1202         CHECK_CALLED(QueryService_IInternetProtocol);
1203     CHECK_CALLED(OnStartBinding);
1204     if(emulate_protocol) {
1205         CHECK_CALLED(Start);
1206         CHECK_CALLED(UnlockRequest);
1207     }else {
1208         if(test_protocol == HTTP_TEST) {
1209             CHECK_CALLED(QueryInterface_IHttpNegotiate);
1210             CHECK_CALLED(BeginningTransaction);
1211             /* QueryInterface_IHttpNegotiate2 and GetRootSecurityId
1212              * called on WinXP but not on Win98 */
1213             CLEAR_CALLED(QueryInterface_IHttpNegotiate2);
1214             CLEAR_CALLED(GetRootSecurityId);
1215             if(http_is_first) {
1216                 CHECK_CALLED(OnProgress_FINDINGRESOURCE);
1217                 CHECK_CALLED(OnProgress_CONNECTING);
1218             }else todo_wine {
1219                 CHECK_NOT_CALLED(OnProgress_FINDINGRESOURCE);
1220                 CHECK_NOT_CALLED(OnProgress_CONNECTING);
1221             }
1222         }
1223         if(test_protocol == HTTP_TEST || test_protocol == FILE_TEST)
1224             CHECK_CALLED(OnProgress_SENDINGREQUEST);
1225         if(test_protocol == HTTP_TEST)
1226             CHECK_CALLED(OnResponse);
1227         CHECK_CALLED(OnProgress_MIMETYPEAVAILABLE);
1228         CHECK_CALLED(OnProgress_BEGINDOWNLOADDATA);
1229         if(test_protocol == HTTP_TEST)
1230             CLEAR_CALLED(OnProgress_DOWNLOADINGDATA);
1231         CHECK_CALLED(OnProgress_ENDDOWNLOADDATA);
1232         CHECK_CALLED(OnDataAvailable);
1233         CHECK_CALLED(OnStopBinding);
1234     }
1235
1236     ok(IMoniker_Release(mon) == 0, "mon should be destroyed here\n");
1237     ok(IBindCtx_Release(bctx) == 0, "bctx should be destroyed here\n");
1238
1239     if(test_protocol == HTTP_TEST)
1240         http_is_first = FALSE;
1241 }
1242
1243 static void set_file_url(void)
1244 {
1245     int len;
1246
1247     static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
1248
1249     memcpy(INDEX_HTML, wszFile, sizeof(wszFile));
1250     len = sizeof(wszFile)/sizeof(WCHAR);
1251     INDEX_HTML[len++] = '/';
1252     len += GetCurrentDirectoryW(sizeof(INDEX_HTML)/sizeof(WCHAR)-len, INDEX_HTML+len);
1253     INDEX_HTML[len++] = '\\';
1254     memcpy(INDEX_HTML+len, wszIndexHtml, sizeof(wszIndexHtml));
1255 }
1256
1257 static void create_file(void)
1258 {
1259     HANDLE file;
1260     DWORD size;
1261
1262     static const char html_doc[] = "<HTML></HTML>";
1263
1264     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1265             FILE_ATTRIBUTE_NORMAL, NULL);
1266     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1267     if(file == INVALID_HANDLE_VALUE)
1268         return;
1269
1270     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
1271     CloseHandle(file);
1272
1273     set_file_url();
1274 }
1275
1276 static void test_BindToStorage_fail(void)
1277 {
1278     IMoniker *mon = NULL;
1279     IBindCtx *bctx = NULL;
1280     IUnknown *unk;
1281     HRESULT hres;
1282
1283     hres = CreateURLMoniker(NULL, ABOUT_BLANK, &mon);
1284     ok(hres == S_OK, "CreateURLMoniker failed: %08x\n", hres);
1285     if(FAILED(hres))
1286         return;
1287
1288     hres = CreateAsyncBindCtxEx(NULL, 0, NULL, NULL, &bctx, 0);
1289     ok(hres == S_OK, "CreateAsyncBindCtxEx failed: %08x\n", hres);
1290
1291     hres = IMoniker_BindToStorage(mon, bctx, NULL, &IID_IStream, (void**)&unk);
1292     ok(hres == MK_E_SYNTAX, "hres=%08x, expected INET_E_SYNTAX\n", hres);
1293
1294     IBindCtx_Release(bctx);
1295
1296     IMoniker_Release(mon);
1297 }
1298
1299 START_TEST(url)
1300 {
1301     test_create();
1302     test_CreateAsyncBindCtx();
1303     test_CreateAsyncBindCtxEx();
1304     test_RegisterBindStatusCallback();
1305
1306     trace("synchronous http test...\n");
1307     test_BindToStorage(HTTP_TEST, FALSE);
1308
1309     trace("synchronous file test...\n");
1310     create_file();
1311     test_BindToStorage(FILE_TEST, FALSE);
1312     DeleteFileW(wszIndexHtml);
1313
1314     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
1315
1316     trace("http test...\n");
1317     test_BindToStorage(HTTP_TEST, FALSE);
1318
1319     trace("http test (short response)...\n");
1320     http_is_first = TRUE;
1321     urls[HTTP_TEST] = SHORT_RESPONSE_URL;
1322     test_BindToStorage(HTTP_TEST, FALSE);
1323
1324     trace("about test...\n");
1325     CoInitialize(NULL);
1326     test_BindToStorage(ABOUT_TEST, FALSE);
1327     CoUninitialize();
1328
1329     trace("emulated about test...\n");
1330     test_BindToStorage(ABOUT_TEST, TRUE);
1331
1332     trace("file test...\n");
1333     create_file();
1334     test_BindToStorage(FILE_TEST, FALSE);
1335     DeleteFileW(wszIndexHtml);
1336
1337     trace("emulated file test...\n");
1338     set_file_url();
1339     test_BindToStorage(FILE_TEST, TRUE);
1340
1341     trace("emulated its test...\n");
1342     test_BindToStorage(ITS_TEST, TRUE);
1343
1344     trace("emulated mk test...\n");
1345     test_BindToStorage(MK_TEST, TRUE);
1346
1347     test_BindToStorage_fail();
1348 }