hlink/tests: Sign compare fix.
[wine] / dlls / urlmon / tests / protocol.c
1 /*
2  * Copyright 2005-2007 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define COBJMACROS
20 #define CONST_VTABLE
21
22 #include <wine/test.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "ole2.h"
29 #include "urlmon.h"
30 #include "wininet.h"
31
32 #define DEFINE_EXPECT(func) \
33     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34
35 #define SET_EXPECT(func) \
36     expect_ ## func = TRUE
37
38 #define CHECK_EXPECT2(func) \
39     do { \
40         ok(expect_ ##func, "unexpected call " #func  "\n"); \
41         called_ ## func = TRUE; \
42     }while(0)
43
44 #define CHECK_EXPECT(func) \
45     do { \
46         CHECK_EXPECT2(func);     \
47         expect_ ## func = FALSE; \
48     }while(0)
49
50 #define CHECK_CALLED(func) \
51     do { \
52         ok(called_ ## func, "expected " #func "\n"); \
53         expect_ ## func = called_ ## func = FALSE; \
54     }while(0)
55
56 #define CHECK_NOT_CALLED(func) \
57     do { \
58         ok(!called_ ## func, "unexpected " #func "\n"); \
59         expect_ ## func = called_ ## func = FALSE; \
60     }while(0)
61
62 #define CLEAR_CALLED(func) \
63     expect_ ## func = called_ ## func = FALSE
64
65 DEFINE_EXPECT(GetBindInfo);
66 DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
67 DEFINE_EXPECT(ReportProgress_DIRECTBIND);
68 DEFINE_EXPECT(ReportProgress_RAWMIMETYPE);
69 DEFINE_EXPECT(ReportProgress_FINDINGRESOURCE);
70 DEFINE_EXPECT(ReportProgress_CONNECTING);
71 DEFINE_EXPECT(ReportProgress_SENDINGREQUEST);
72 DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
73 DEFINE_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
74 DEFINE_EXPECT(ReportProgress_PROTOCOLCLASSID);
75 DEFINE_EXPECT(ReportProgress_COOKIE_SENT);
76 DEFINE_EXPECT(ReportProgress_REDIRECTING);
77 DEFINE_EXPECT(ReportProgress_ENCODING);
78 DEFINE_EXPECT(ReportProgress_ACCEPTRANGES);
79 DEFINE_EXPECT(ReportProgress_PROXYDETECTING);
80 DEFINE_EXPECT(ReportData);
81 DEFINE_EXPECT(ReportResult);
82 DEFINE_EXPECT(GetBindString_ACCEPT_MIMES);
83 DEFINE_EXPECT(GetBindString_USER_AGENT);
84 DEFINE_EXPECT(GetBindString_POST_COOKIE);
85 DEFINE_EXPECT(QueryService_HttpNegotiate);
86 DEFINE_EXPECT(QueryService_InternetProtocol);
87 DEFINE_EXPECT(QueryService_HttpSecurity);
88 DEFINE_EXPECT(BeginningTransaction);
89 DEFINE_EXPECT(GetRootSecurityId);
90 DEFINE_EXPECT(OnResponse);
91 DEFINE_EXPECT(Switch);
92 DEFINE_EXPECT(Continue);
93 DEFINE_EXPECT(CreateInstance);
94 DEFINE_EXPECT(Start);
95 DEFINE_EXPECT(Terminate);
96 DEFINE_EXPECT(Read);
97 DEFINE_EXPECT(SetPriority);
98 DEFINE_EXPECT(LockRequest);
99 DEFINE_EXPECT(UnlockRequest);
100
101 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
102 static const WCHAR index_url[] =
103     {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
104
105 static const WCHAR acc_mimeW[] = {'*','/','*',0};
106 static const WCHAR user_agentW[] = {'W','i','n','e',0};
107 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
108 static const WCHAR hostW[] = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
109 static const WCHAR winehq_ipW[] = {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
110 static const WCHAR emptyW[] = {0};
111
112 static HRESULT expect_hrResult;
113 static LPCWSTR file_name, http_url, expect_wsz;
114 static IInternetProtocol *async_protocol = NULL;
115 static BOOL first_data_notif = FALSE, http_is_first = FALSE,
116     http_post_test = FALSE;
117 static int state = 0, prot_state;
118 static DWORD bindf = 0, ex_priority = 0;
119 static IInternetProtocol *binding_protocol;
120 static IInternetBindInfo *prot_bind_info;
121 static IInternetProtocolSink *binding_sink;
122 static void *expect_pv;
123 static HANDLE event_complete, event_complete2;
124 static BOOL binding_test;
125 static PROTOCOLDATA protocoldata, *pdata;
126 static DWORD prot_read;
127 static BOOL security_problem = FALSE;
128
129 static enum {
130     FILE_TEST,
131     HTTP_TEST,
132     HTTPS_TEST,
133     FTP_TEST,
134     MK_TEST,
135     BIND_TEST
136 } tested_protocol;
137
138 static const WCHAR protocol_names[][10] = {
139     {'f','i','l','e',0},
140     {'h','t','t','p',0},
141     {'h','t','t','p','s',0},
142     {'f','t','p',0},
143     {'m','k',0},
144     {'t','e','s','t',0}
145 };
146
147 static const WCHAR binding_urls[][130] = {
148     {'f','i','l','e',':','t','e','s','t','.','h','t','m','l',0},
149     {'h','t','t','p',':','/','/','t','e','s','t','/','t','e','s','t','.','h','t','m','l',0},
150     {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
151      '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0},
152     {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
153      '/','p','u','b','/','o','t','h','e','r',
154      '/','w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0},
155     {'m','k',':','t','e','s','t',0},
156     {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0}
157 };
158
159 static const char *debugstr_w(LPCWSTR str)
160 {
161     static char buf[512];
162     if(!str)
163         return "(null)";
164     WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
165     return buf;
166 }
167
168 static const char *debugstr_guid(REFIID riid)
169 {
170     static char buf[50];
171
172     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
173             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
174             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
175             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
176
177     return buf;
178 }
179
180 static int strcmp_wa(LPCWSTR strw, const char *stra)
181 {
182     WCHAR buf[512];
183     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
184     return lstrcmpW(strw, buf);
185 }
186
187 static HRESULT WINAPI HttpSecurity_QueryInterface(IHttpSecurity *iface, REFIID riid, void **ppv)
188 {
189     if(IsEqualGUID(&IID_IUnknown, riid)
190             || IsEqualGUID(&IID_IHttpSecurity, riid)) {
191         *ppv = iface;
192         return S_OK;
193     }
194
195     ok(0, "unexpected call\n");
196     return E_NOINTERFACE;
197 }
198
199 static ULONG WINAPI HttpSecurity_AddRef(IHttpSecurity *iface)
200 {
201     return 2;
202 }
203
204 static ULONG WINAPI HttpSecurity_Release(IHttpSecurity *iface)
205 {
206     return 1;
207 }
208
209 static  HRESULT WINAPI HttpSecurity_GetWindow(IHttpSecurity* iface, REFGUID rguidReason, HWND *phwnd)
210 {
211     trace("HttpSecurity_GetWindow\n");
212
213     return S_FALSE;
214 }
215
216 static HRESULT WINAPI HttpSecurity_OnSecurityProblem(IHttpSecurity *iface, DWORD dwProblem)
217 {
218     trace("Security problem: %u\n", dwProblem);
219     ok(dwProblem == ERROR_INTERNET_SEC_CERT_REV_FAILED, "Expected ERROR_INTERNET_SEC_CERT_REV_FAILED got %u\n", dwProblem);
220
221     /* Only retry once */
222     if (security_problem)
223         return E_ABORT;
224
225     security_problem = TRUE;
226     SET_EXPECT(BeginningTransaction);
227
228     return RPC_E_RETRY;
229 }
230
231 static IHttpSecurityVtbl HttpSecurityVtbl = {
232     HttpSecurity_QueryInterface,
233     HttpSecurity_AddRef,
234     HttpSecurity_Release,
235     HttpSecurity_GetWindow,
236     HttpSecurity_OnSecurityProblem
237 };
238
239 static IHttpSecurity http_security = { &HttpSecurityVtbl };
240
241 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
242 {
243     if(IsEqualGUID(&IID_IUnknown, riid)
244             || IsEqualGUID(&IID_IHttpNegotiate, riid)
245             || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
246         *ppv = iface;
247         return S_OK;
248     }
249
250     ok(0, "unexpected call\n");
251     return E_NOINTERFACE;
252 }
253
254 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
255 {
256     return 2;
257 }
258
259 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
260 {
261     return 1;
262 }
263
264 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
265         LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
266 {
267     LPWSTR addl_headers;
268
269     static const WCHAR wszHeaders[] =
270         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
271          'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
272          'd','e','d','\r','\n',0};
273
274     CHECK_EXPECT(BeginningTransaction);
275
276     if(binding_test)
277         ok(!lstrcmpW(szURL, binding_urls[tested_protocol]), "szURL != http_url\n");
278     else
279         ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
280     ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
281     ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
282     if(pszAdditionalHeaders)
283     {
284         ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
285         if (http_post_test)
286         {
287             addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
288             if (!addl_headers)
289             {
290                 http_post_test = FALSE;
291                 skip("Out of memory\n");
292                 return E_OUTOFMEMORY;
293             }
294             lstrcpyW(addl_headers, wszHeaders);
295             *pszAdditionalHeaders = addl_headers;
296         }
297     }
298
299     return S_OK;
300 }
301
302 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
303         LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
304 {
305     CHECK_EXPECT(OnResponse);
306
307     ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
308     ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
309     ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
310     ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
311
312     return S_OK;
313 }
314
315 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
316         BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
317 {
318     static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
319     
320     CHECK_EXPECT(GetRootSecurityId);
321
322     ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
323     ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
324     ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
325
326     if(pcbSecurityId) {
327         ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
328         *pcbSecurityId = sizeof(sec_id);
329     }
330
331     if(pbSecurityId)
332         memcpy(pbSecurityId, sec_id, sizeof(sec_id));
333
334     return E_FAIL;
335 }
336
337 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
338     HttpNegotiate_QueryInterface,
339     HttpNegotiate_AddRef,
340     HttpNegotiate_Release,
341     HttpNegotiate_BeginningTransaction,
342     HttpNegotiate_OnResponse,
343     HttpNegotiate_GetRootSecurityId
344 };
345
346 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
347
348 static HRESULT QueryInterface(REFIID,void**);
349
350 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
351 {
352     return QueryInterface(riid, ppv);
353 }
354
355 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
356 {
357     return 2;
358 }
359
360 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
361 {
362     return 1;
363 }
364
365 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
366         REFIID riid, void **ppv)
367 {
368     if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
369         CHECK_EXPECT2(QueryService_HttpNegotiate);
370         return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
371     }
372
373     if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
374         ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
375         CHECK_EXPECT(QueryService_InternetProtocol);
376         return E_NOINTERFACE;
377     }
378
379     if(IsEqualGUID(&IID_IHttpSecurity, guidService)) {
380         ok(IsEqualGUID(&IID_IHttpSecurity, riid), "unexpected riid\n");
381         CHECK_EXPECT(QueryService_HttpSecurity);
382         return IHttpSecurity_QueryInterface(&http_security, riid, ppv);
383     }
384
385     ok(0, "unexpected service %s\n", debugstr_guid(guidService));
386     return E_FAIL;
387 }
388
389 static const IServiceProviderVtbl ServiceProviderVtbl = {
390     ServiceProvider_QueryInterface,
391     ServiceProvider_AddRef,
392     ServiceProvider_Release,
393     ServiceProvider_QueryService
394 };
395
396 static IServiceProvider service_provider = { &ServiceProviderVtbl };
397
398 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
399 {
400     return QueryInterface(riid, ppv);
401 }
402
403 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
404 {
405     return 2;
406 }
407
408 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
409 {
410     return 1;
411 }
412
413 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
414 {
415     HRESULT hres;
416
417     if(tested_protocol == FTP_TEST)
418       CHECK_EXPECT2(Switch);
419     else
420       CHECK_EXPECT(Switch);
421     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
422
423     pdata = pProtocolData;
424
425     if(binding_test) {
426         SetEvent(event_complete);
427         WaitForSingleObject(event_complete2, INFINITE);
428         return S_OK;
429     }
430
431     if (!state) {
432         if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST) {
433             if (http_is_first) {
434                 CLEAR_CALLED(ReportProgress_FINDINGRESOURCE);
435                 CLEAR_CALLED(ReportProgress_CONNECTING);
436                 CLEAR_CALLED(ReportProgress_PROXYDETECTING);
437             } else todo_wine {
438                     CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
439                     /* IE7 does call this */
440                     CLEAR_CALLED(ReportProgress_CONNECTING);
441                 }
442         }
443         if(tested_protocol == FTP_TEST)
444             todo_wine CHECK_CALLED(ReportProgress_SENDINGREQUEST);
445         else if (tested_protocol != HTTPS_TEST)
446             CHECK_CALLED(ReportProgress_SENDINGREQUEST);
447         if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
448             SET_EXPECT(OnResponse);
449             if(tested_protocol == HTTPS_TEST)
450                 SET_EXPECT(ReportProgress_ACCEPTRANGES);
451             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
452             if(bindf & BINDF_NEEDFILE)
453                 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
454         }
455     }
456
457     SET_EXPECT(ReportData);
458     hres = IInternetProtocol_Continue(async_protocol, pProtocolData);
459     ok(hres == S_OK, "Continue failed: %08x\n", hres);
460     if(tested_protocol == FTP_TEST)
461         CLEAR_CALLED(ReportData);
462     else if (! security_problem)
463         CHECK_CALLED(ReportData);
464
465     if (!state) {
466         if (! security_problem)
467         {
468             state = 1;
469             if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
470                 CHECK_CALLED(OnResponse);
471                 if(tested_protocol == HTTPS_TEST)
472                     CHECK_CALLED(ReportProgress_ACCEPTRANGES);
473                 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
474                 if(bindf & BINDF_NEEDFILE)
475                     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
476             }
477         }
478         else
479         {
480             security_problem = FALSE;
481             SET_EXPECT(ReportProgress_CONNECTING);
482         }
483     }
484
485     SetEvent(event_complete);
486
487     return S_OK;
488 }
489
490 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
491         LPCWSTR szStatusText)
492 {
493     static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
494         '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
495     static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
496
497     switch(ulStatusCode) {
498     case BINDSTATUS_MIMETYPEAVAILABLE:
499         CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
500         ok(szStatusText != NULL, "szStatusText == NULL\n");
501         if(szStatusText) {
502             if(tested_protocol == BIND_TEST)
503                 ok(szStatusText == expect_wsz, "unexpected szStatusText\n");
504             else if (http_post_test)
505                 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
506                    !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
507                    "szStatusText != text/plain\n");
508             else
509                 ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) &&
510                    !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
511                    "szStatusText != text/html\n");
512         }
513         break;
514     case BINDSTATUS_DIRECTBIND:
515         CHECK_EXPECT2(ReportProgress_DIRECTBIND);
516         ok(szStatusText == NULL, "szStatusText != NULL\n");
517         break;
518     case BINDSTATUS_RAWMIMETYPE:
519         CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
520         ok(szStatusText != NULL, "szStatusText == NULL\n");
521         if(szStatusText)
522             ok(lstrlenW(szStatusText) < lstrlenW(text_htmlW) ||
523                !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
524                "szStatusText != text/html\n");
525         break;
526     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
527         CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
528         ok(szStatusText != NULL, "szStatusText == NULL\n");
529         if(szStatusText) {
530             if(binding_test)
531                 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText\n");
532             else if(tested_protocol == FILE_TEST)
533                 ok(!lstrcmpW(szStatusText, file_name), "szStatusText = \"%s\"\n", debugstr_w(szStatusText));
534             else
535                 ok(szStatusText != NULL, "szStatusText == NULL\n");
536         }
537         break;
538     case BINDSTATUS_FINDINGRESOURCE:
539         CHECK_EXPECT2(ReportProgress_FINDINGRESOURCE);
540         ok(szStatusText != NULL, "szStatusText == NULL\n");
541         break;
542     case BINDSTATUS_CONNECTING:
543         CHECK_EXPECT2(ReportProgress_CONNECTING);
544         ok(szStatusText != NULL, "szStatusText == NULL\n");
545         break;
546     case BINDSTATUS_SENDINGREQUEST:
547         CHECK_EXPECT2(ReportProgress_SENDINGREQUEST);
548         if(tested_protocol == FILE_TEST) {
549             ok(szStatusText != NULL, "szStatusText == NULL\n");
550             if(szStatusText)
551                 ok(!*szStatusText, "wrong szStatusText\n");
552         }
553         break;
554     case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
555         CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
556         ok(szStatusText != NULL, "szStatusText == NULL\n");
557         if(szStatusText)
558             ok(!lstrcmpW(szStatusText, text_htmlW), "szStatusText != text/html\n");
559         break;
560     case BINDSTATUS_PROTOCOLCLASSID:
561         CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
562         ok(szStatusText != NULL, "szStatusText == NULL\n");
563         ok(!lstrcmpW(szStatusText, null_guid), "unexpected szStatusText\n");
564         break;
565     case BINDSTATUS_COOKIE_SENT:
566         CHECK_EXPECT(ReportProgress_COOKIE_SENT);
567         ok(szStatusText == NULL, "szStatusText != NULL\n");
568         break;
569     case BINDSTATUS_REDIRECTING:
570         CHECK_EXPECT(ReportProgress_REDIRECTING);
571         ok(szStatusText == NULL, "szStatusText = %s\n", debugstr_w(szStatusText));
572         break;
573     case BINDSTATUS_ENCODING:
574         CHECK_EXPECT(ReportProgress_ENCODING);
575         ok(!strcmp_wa(szStatusText, "gzip"), "szStatusText = %s\n", debugstr_w(szStatusText));
576         break;
577     case BINDSTATUS_ACCEPTRANGES:
578         CHECK_EXPECT(ReportProgress_ACCEPTRANGES);
579         ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText));
580         break;
581     case BINDSTATUS_PROXYDETECTING:
582         CHECK_EXPECT(ReportProgress_PROXYDETECTING);
583         SET_EXPECT(ReportProgress_CONNECTING);
584         ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText));
585         break;
586     default:
587         ok(0, "Unexpected status %d\n", ulStatusCode);
588     };
589
590     return S_OK;
591 }
592
593 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
594         ULONG ulProgress, ULONG ulProgressMax)
595 {
596     if(tested_protocol == FILE_TEST) {
597         CHECK_EXPECT2(ReportData);
598
599         ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
600            ulProgress, ulProgressMax);
601         ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
602         /* BSCF_SKIPDRAINDATAFORFILEURLS added in IE8 */
603         ok((grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION)) ||
604            (grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_SKIPDRAINDATAFORFILEURLS)),
605                 "grcfBSCF = %08x\n", grfBSCF);
606     }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST)) {
607         if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
608             CHECK_EXPECT(ReportData);
609         else if (http_post_test)
610             ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
611
612         ok(ulProgress, "ulProgress == 0\n");
613
614         if(first_data_notif) {
615             ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
616                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
617                "grcfBSCF = %08x\n", grfBSCF);
618             first_data_notif = FALSE;
619         } else {
620             ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
621                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
622                || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
623                "grcfBSCF = %08x\n", grfBSCF);
624         }
625
626         if(!(bindf & BINDF_FROMURLMON) &&
627            !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
628             if(!state) {
629                 state = 1;
630                 if(http_is_first) {
631                     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
632                     CHECK_CALLED(ReportProgress_CONNECTING);
633                 } else todo_wine {
634                     CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
635                     CHECK_NOT_CALLED(ReportProgress_CONNECTING);
636                 }
637                 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
638                 CHECK_CALLED(OnResponse);
639                 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
640             }
641             SetEvent(event_complete);
642         }
643     }else {
644         BYTE buf[1000];
645         ULONG read;
646         HRESULT hres;
647
648         CHECK_EXPECT(ReportData);
649
650         if(tested_protocol == BIND_TEST)
651             return S_OK;
652
653         do {
654             SET_EXPECT(Read);
655             hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
656             CHECK_CALLED(Read);
657         }while(hres == S_OK);
658     }
659
660     return S_OK;
661 }
662
663 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
664         DWORD dwError, LPCWSTR szResult)
665 {
666     CHECK_EXPECT(ReportResult);
667
668     if(tested_protocol == FTP_TEST)
669         ok(hrResult == E_PENDING || hrResult == S_OK, "hrResult = %08x, expected E_PENDING or S_OK\n", hrResult);
670     else
671         ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
672            hrResult, expect_hrResult);
673     if(SUCCEEDED(hrResult) || tested_protocol == FTP_TEST)
674         ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
675     else
676         ok(dwError != ERROR_SUCCESS ||
677            broken(tested_protocol == MK_TEST), /* Win9x, WinME and NT4 */
678            "dwError == ERROR_SUCCESS\n");
679     ok(!szResult, "szResult != NULL\n");
680
681     return S_OK;
682 }
683
684 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
685     ProtocolSink_QueryInterface,
686     ProtocolSink_AddRef,
687     ProtocolSink_Release,
688     ProtocolSink_Switch,
689     ProtocolSink_ReportProgress,
690     ProtocolSink_ReportData,
691     ProtocolSink_ReportResult
692 };
693
694 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
695
696 static HRESULT QueryInterface(REFIID riid, void **ppv)
697 {
698     *ppv = NULL;
699
700     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
701         *ppv = &protocol_sink;
702     if(IsEqualGUID(&IID_IServiceProvider, riid))
703         *ppv = &service_provider;
704
705     if(*ppv)
706         return S_OK;
707
708     return E_NOINTERFACE;
709 }
710
711 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
712 {
713     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
714         *ppv = iface;
715         return S_OK;
716     }
717     return E_NOINTERFACE;
718 }
719
720 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
721 {
722     return 2;
723 }
724
725 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
726 {
727     return 1;
728 }
729
730 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
731 {
732     DWORD cbSize;
733
734     static const CHAR szPostData[] = "mode=Test";
735
736     CHECK_EXPECT(GetBindInfo);
737
738     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
739     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
740     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
741
742     *grfBINDF = bindf;
743     if(binding_test)
744         *grfBINDF |= BINDF_FROMURLMON;
745     cbSize = pbindinfo->cbSize;
746     memset(pbindinfo, 0, cbSize);
747     pbindinfo->cbSize = cbSize;
748
749     if (http_post_test)
750     {
751         /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly
752          * with urlmon on native (Win98 and WinXP) */
753         U(pbindinfo->stgmedData).hGlobal = GlobalAlloc(GPTR, sizeof(szPostData));
754         if (!U(pbindinfo->stgmedData).hGlobal)
755         {
756             http_post_test = FALSE;
757             skip("Out of memory\n");
758             return E_OUTOFMEMORY;
759         }
760         lstrcpy((LPSTR)U(pbindinfo->stgmedData).hGlobal, szPostData);
761         pbindinfo->cbstgmedData = sizeof(szPostData)-1;
762         pbindinfo->dwBindVerb = BINDVERB_POST;
763         pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
764     }
765
766     return S_OK;
767 }
768
769 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
770         LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
771 {
772     ok(ppwzStr != NULL, "ppwzStr == NULL\n");
773     ok(pcElFetched != NULL, "pcElFetched == NULL\n");
774
775     switch(ulStringType) {
776     case BINDSTRING_ACCEPT_MIMES:
777         CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
778         ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
779         if(pcElFetched) {
780             ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
781             *pcElFetched = 1;
782         }
783         if(ppwzStr) {
784             *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
785             memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
786         }
787         return S_OK;
788     case BINDSTRING_USER_AGENT:
789         CHECK_EXPECT(GetBindString_USER_AGENT);
790         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
791         if(pcElFetched) {
792             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
793             *pcElFetched = 1;
794         }
795         if(ppwzStr) {
796             *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
797             memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
798         }
799         return S_OK;
800     case BINDSTRING_POST_COOKIE:
801         CHECK_EXPECT(GetBindString_POST_COOKIE);
802         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
803         if(pcElFetched)
804             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
805         return S_OK;
806     default:
807         ok(0, "unexpected call\n");
808     }
809
810     return E_NOTIMPL;
811 }
812
813 static IInternetBindInfoVtbl bind_info_vtbl = {
814     BindInfo_QueryInterface,
815     BindInfo_AddRef,
816     BindInfo_Release,
817     BindInfo_GetBindInfo,
818     BindInfo_GetBindString
819 };
820
821 static IInternetBindInfo bind_info = { &bind_info_vtbl };
822
823 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
824                                                   REFIID riid, void **ppv)
825 {
826     ok(0, "unexpected call\n");
827     return E_NOINTERFACE;
828 }
829
830 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
831 {
832     return 2;
833 }
834
835 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
836 {
837     return 1;
838 }
839
840 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
841 {
842     CHECK_EXPECT(SetPriority);
843     ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
844     return S_OK;
845 }
846
847 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
848 {
849     ok(0, "unexpected call\n");
850     return E_NOTIMPL;
851 }
852
853
854 static const IInternetPriorityVtbl InternetPriorityVtbl = {
855     InternetPriority_QueryInterface,
856     InternetPriority_AddRef,
857     InternetPriority_Release,
858     InternetPriority_SetPriority,
859     InternetPriority_GetPriority
860 };
861
862 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
863
864 static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
865 {
866     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
867         *ppv = iface;
868         return S_OK;
869     }
870
871     if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
872         trace("IID_IInternetProtocolEx not supported\n");
873         *ppv = NULL;
874         return E_NOINTERFACE;
875     }
876
877     if(IsEqualGUID(&IID_IInternetPriority, riid)) {
878         *ppv = &InternetPriority;
879         return S_OK;
880     }
881
882     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
883     *ppv = NULL;
884     return E_NOINTERFACE;
885 }
886
887 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
888 {
889     return 2;
890 }
891
892 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
893 {
894     return 1;
895 }
896
897 static DWORD WINAPI thread_proc(PVOID arg)
898 {
899     HRESULT hres;
900
901     memset(&protocoldata, -1, sizeof(protocoldata));
902
903     prot_state = 0;
904
905     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
906     hres = IInternetProtocolSink_ReportProgress(binding_sink,
907             BINDSTATUS_FINDINGRESOURCE, hostW);
908     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
909     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
910
911     SET_EXPECT(ReportProgress_CONNECTING);
912     hres = IInternetProtocolSink_ReportProgress(binding_sink,
913             BINDSTATUS_CONNECTING, winehq_ipW);
914     CHECK_CALLED(ReportProgress_CONNECTING);
915     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
916
917     SET_EXPECT(ReportProgress_SENDINGREQUEST);
918     hres = IInternetProtocolSink_ReportProgress(binding_sink,
919             BINDSTATUS_SENDINGREQUEST, NULL);
920     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
921     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
922
923     prot_state = 1;
924     SET_EXPECT(Switch);
925     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
926     CHECK_CALLED(Switch);
927     ok(hres == S_OK, "Switch failed: %08x\n", hres);
928
929     prot_state = 2;
930     SET_EXPECT(Switch);
931     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
932     CHECK_CALLED(Switch);
933     ok(hres == S_OK, "Switch failed: %08x\n", hres);
934
935     prot_state = 2;
936     SET_EXPECT(Switch);
937     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
938     CHECK_CALLED(Switch);
939     ok(hres == S_OK, "Switch failed: %08x\n", hres);
940
941     prot_state = 3;
942     SET_EXPECT(Switch);
943     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
944     CHECK_CALLED(Switch);
945     ok(hres == S_OK, "Switch failed: %08x\n", hres);
946
947     SetEvent(event_complete);
948
949     return 0;
950 }
951
952 static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
953         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
954         DWORD grfPI, HANDLE_PTR dwReserved)
955 {
956     BINDINFO bindinfo, exp_bindinfo;
957     DWORD cbindf = 0;
958     HRESULT hres;
959
960     CHECK_EXPECT(Start);
961
962     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
963     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
964     ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
965     ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
966     ok(!grfPI, "grfPI = %x\n", grfPI);
967     ok(!dwReserved, "dwReserved = %lx\n", dwReserved);
968
969     memset(&bindinfo, 0, sizeof(bindinfo));
970     bindinfo.cbSize = sizeof(bindinfo);
971     memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
972     SET_EXPECT(GetBindInfo);
973     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
974     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
975     CHECK_CALLED(GetBindInfo);
976     ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
977        cbindf, (bindf|BINDF_FROMURLMON));
978     ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
979     ReleaseBindInfo(&bindinfo);
980
981     SET_EXPECT(ReportProgress_SENDINGREQUEST);
982     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
983     ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
984     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
985
986     if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
987         IServiceProvider *service_provider;
988         IHttpNegotiate *http_negotiate;
989         IHttpNegotiate2 *http_negotiate2;
990         LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
991         LPWSTR additional_headers = NULL;
992         BYTE sec_id[100];
993         DWORD fetched = 0, size = 100;
994         DWORD tid;
995
996         SET_EXPECT(GetBindString_USER_AGENT);
997         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
998                                                &ua, 1, &fetched);
999         CHECK_CALLED(GetBindString_USER_AGENT);
1000         ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
1001         ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
1002         ok(ua != NULL, "ua =  %p\n", ua);
1003         ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", debugstr_w(ua));
1004         CoTaskMemFree(ua);
1005
1006         fetched = 256;
1007         SET_EXPECT(GetBindString_ACCEPT_MIMES);
1008         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
1009                                                accept_mimes, 256, &fetched);
1010         CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1011
1012         ok(hres == S_OK,
1013            "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
1014         ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
1015         ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", debugstr_w(accept_mimes[0]));
1016
1017         hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
1018                                                 (void**)&service_provider);
1019         ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
1020
1021         SET_EXPECT(QueryService_HttpNegotiate);
1022         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1023                 &IID_IHttpNegotiate, (void**)&http_negotiate);
1024         CHECK_CALLED(QueryService_HttpNegotiate);
1025         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1026
1027         SET_EXPECT(BeginningTransaction);
1028         hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
1029                                                    NULL, 0, &additional_headers);
1030         CHECK_CALLED(BeginningTransaction);
1031         IHttpNegotiate_Release(http_negotiate);
1032         ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
1033         ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
1034
1035         SET_EXPECT(QueryService_HttpNegotiate);
1036         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
1037                 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
1038         CHECK_CALLED(QueryService_HttpNegotiate);
1039         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1040
1041         size = 512;
1042         SET_EXPECT(GetRootSecurityId);
1043         hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
1044         CHECK_CALLED(GetRootSecurityId);
1045         IHttpNegotiate2_Release(http_negotiate2);
1046         ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
1047         ok(size == 13, "size=%d\n", size);
1048
1049         IServiceProvider_Release(service_provider);
1050
1051         CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
1052
1053         return S_OK;
1054     }
1055
1056     SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1057     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
1058             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1059     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1060     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1061
1062     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1063     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
1064                                                 expect_wsz = text_htmlW);
1065     ok(hres == S_OK,
1066        "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
1067     CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1068
1069     SET_EXPECT(ReportData);
1070     hres = IInternetProtocolSink_ReportData(pOIProtSink,
1071             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, 13, 13);
1072     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1073     CHECK_CALLED(ReportData);
1074
1075     if(tested_protocol == BIND_TEST) {
1076         hres = IInternetProtocol_Terminate(binding_protocol, 0);
1077         ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
1078     }
1079
1080     SET_EXPECT(ReportResult);
1081     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
1082     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1083     CHECK_CALLED(ReportResult);
1084
1085     return S_OK;
1086 }
1087
1088 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
1089         PROTOCOLDATA *pProtocolData)
1090 {
1091     DWORD bscf = 0;
1092     HRESULT hres;
1093
1094     CHECK_EXPECT(Continue);
1095
1096     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
1097     if(!pProtocolData || tested_protocol == BIND_TEST)
1098         return S_OK;
1099
1100     switch(prot_state) {
1101     case 1: {
1102         IServiceProvider *service_provider;
1103         IHttpNegotiate *http_negotiate;
1104         static WCHAR header[] = {'?',0};
1105
1106         hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
1107                                                     (void**)&service_provider);
1108         ok(hres == S_OK, "Could not get IServiceProvicder\n");
1109
1110         SET_EXPECT(QueryService_HttpNegotiate);
1111         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1112                                              &IID_IHttpNegotiate, (void**)&http_negotiate);
1113         IServiceProvider_Release(service_provider);
1114         CHECK_CALLED(QueryService_HttpNegotiate);
1115         ok(hres == S_OK, "Could not get IHttpNegotiate\n");
1116
1117         SET_EXPECT(OnResponse);
1118         hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
1119         IHttpNegotiate_Release(http_negotiate);
1120         CHECK_CALLED(OnResponse);
1121         IHttpNegotiate_Release(http_negotiate);
1122         ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
1123
1124         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1125         hres = IInternetProtocolSink_ReportProgress(binding_sink,
1126                 BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW);
1127         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1128         ok(hres == S_OK,
1129            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
1130
1131         bscf |= BSCF_FIRSTDATANOTIFICATION;
1132         break;
1133     }
1134     case 2:
1135     case 3:
1136         bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
1137         break;
1138     }
1139
1140     SET_EXPECT(ReportData);
1141     hres = IInternetProtocolSink_ReportData(binding_sink, bscf, 100, 400);
1142     CHECK_CALLED(ReportData);
1143     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1144
1145     if(prot_state == 3)
1146         prot_state = 4;
1147
1148     return S_OK;
1149 }
1150
1151 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
1152         DWORD dwOptions)
1153 {
1154     ok(0, "unexpected call\n");
1155     return E_NOTIMPL;
1156 }
1157
1158 static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
1159 {
1160     CHECK_EXPECT(Terminate);
1161     ok(!dwOptions, "dwOptions=%d\n", dwOptions);
1162     return S_OK;
1163 }
1164
1165 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
1166 {
1167     ok(0, "unexpected call\n");
1168     return E_NOTIMPL;
1169 }
1170
1171 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
1172 {
1173     ok(0, "unexpected call\n");
1174     return E_NOTIMPL;
1175 }
1176
1177 static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv,
1178         ULONG cb, ULONG *pcbRead)
1179 {
1180     static BOOL b = TRUE;
1181
1182     CHECK_EXPECT(Read);
1183
1184     ok(pv == expect_pv, "pv != expect_pv\n");
1185     ok(cb == 1000, "cb=%d\n", cb);
1186     ok(pcbRead != NULL, "pcbRead == NULL\n");
1187     ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
1188
1189     if(prot_state == 3) {
1190         HRESULT hres;
1191
1192         SET_EXPECT(ReportResult);
1193         hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1194         CHECK_CALLED(ReportResult);
1195
1196         return S_FALSE;
1197     }
1198
1199     if((b = !b))
1200         return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
1201
1202     memset(pv, 'x', 100);
1203     prot_read += *pcbRead = 100;
1204     return S_OK;
1205 }
1206
1207 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
1208         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1209 {
1210     ok(0, "unexpected call\n");
1211     return E_NOTIMPL;
1212 }
1213
1214 static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
1215 {
1216     CHECK_EXPECT(LockRequest);
1217     ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
1218     return S_OK;
1219 }
1220
1221 static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface)
1222 {
1223     CHECK_EXPECT(UnlockRequest);
1224     return S_OK;
1225 }
1226
1227 static const IInternetProtocolVtbl ProtocolVtbl = {
1228     Protocol_QueryInterface,
1229     Protocol_AddRef,
1230     Protocol_Release,
1231     Protocol_Start,
1232     Protocol_Continue,
1233     Protocol_Abort,
1234     Protocol_Terminate,
1235     Protocol_Suspend,
1236     Protocol_Resume,
1237     Protocol_Read,
1238     Protocol_Seek,
1239     Protocol_LockRequest,
1240     Protocol_UnlockRequest
1241 };
1242
1243 static IInternetProtocol Protocol = { &ProtocolVtbl };
1244
1245 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
1246 {
1247     ok(0, "unexpected call\n");
1248     return E_NOINTERFACE;
1249 }
1250
1251 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
1252 {
1253     return 2;
1254 }
1255
1256 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
1257 {
1258     return 1;
1259 }
1260
1261 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1262                                         REFIID riid, void **ppv)
1263 {
1264     CHECK_EXPECT(CreateInstance);
1265
1266     ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
1267     ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
1268     ok(ppv != NULL, "ppv == NULL\n");
1269
1270     *ppv = &Protocol;
1271     return S_OK;
1272 }
1273
1274 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
1275 {
1276     ok(0, "unexpected call\n");
1277     return S_OK;
1278 }
1279
1280 static const IClassFactoryVtbl ClassFactoryVtbl = {
1281     ClassFactory_QueryInterface,
1282     ClassFactory_AddRef,
1283     ClassFactory_Release,
1284     ClassFactory_CreateInstance,
1285     ClassFactory_LockServer
1286 };
1287
1288 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
1289
1290 static void test_priority(IInternetProtocol *protocol)
1291 {
1292     IInternetPriority *priority;
1293     LONG pr;
1294     HRESULT hres;
1295
1296     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
1297                                             (void**)&priority);
1298     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
1299     if(FAILED(hres))
1300         return;
1301
1302     hres = IInternetPriority_GetPriority(priority, &pr);
1303     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1304     ok(pr == 0, "pr=%d, expected 0\n", pr);
1305
1306     hres = IInternetPriority_SetPriority(priority, 1);
1307     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1308
1309     hres = IInternetPriority_GetPriority(priority, &pr);
1310     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1311     ok(pr == 1, "pr=%d, expected 1\n", pr);
1312
1313     IInternetPriority_Release(priority);
1314 }
1315
1316 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url, BOOL is_first)
1317 {
1318     HRESULT hres;
1319
1320     SET_EXPECT(GetBindInfo);
1321     if(!(bindf & BINDF_FROMURLMON))
1322        SET_EXPECT(ReportProgress_DIRECTBIND);
1323     if(is_first) {
1324         SET_EXPECT(ReportProgress_SENDINGREQUEST);
1325         SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1326         if(bindf & BINDF_FROMURLMON)
1327             SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
1328         else
1329             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1330     }
1331     SET_EXPECT(ReportData);
1332     if(is_first)
1333         SET_EXPECT(ReportResult);
1334
1335     expect_hrResult = S_OK;
1336
1337     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
1338     if(hres == INET_E_RESOURCE_NOT_FOUND) {
1339         win_skip("Start failed\n");
1340         return FALSE;
1341     }
1342     ok(hres == S_OK, "Start failed: %08x\n", hres);
1343
1344     CHECK_CALLED(GetBindInfo);
1345     if(!(bindf & BINDF_FROMURLMON))
1346        CHECK_CALLED(ReportProgress_DIRECTBIND);
1347     if(is_first) {
1348         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1349         CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1350         if(bindf & BINDF_FROMURLMON)
1351             CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
1352         else
1353             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1354     }
1355     CHECK_CALLED(ReportData);
1356     if(is_first)
1357         CHECK_CALLED(ReportResult);
1358
1359     return TRUE;
1360 }
1361
1362 static void test_file_protocol_url(LPCWSTR url)
1363 {
1364     IInternetProtocolInfo *protocol_info;
1365     IUnknown *unk;
1366     IClassFactory *factory;
1367     HRESULT hres;
1368
1369     hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
1370             &IID_IUnknown, (void**)&unk);
1371     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1372     if(FAILED(hres))
1373         return;
1374
1375     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1376     ok(hres == E_NOINTERFACE,
1377             "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
1378
1379     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1380     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1381     if(SUCCEEDED(hres)) {
1382         IInternetProtocol *protocol;
1383         BYTE buf[512];
1384         ULONG cb;
1385         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1386         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1387
1388         if(SUCCEEDED(hres)) {
1389             if(file_protocol_start(protocol, url, TRUE)) {
1390                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1391                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1392                 ok(cb == 2, "cb=%u expected 2\n", cb);
1393                 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
1394                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1395                 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
1396                 ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
1397                 ok(cb == 0, "cb=%u expected 0\n", cb);
1398                 hres = IInternetProtocol_UnlockRequest(protocol);
1399                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1400             }
1401
1402             if(file_protocol_start(protocol, url, FALSE)) {
1403                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1404                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1405                 hres = IInternetProtocol_LockRequest(protocol, 0);
1406                 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1407                 hres = IInternetProtocol_UnlockRequest(protocol);
1408                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1409             }
1410
1411             IInternetProtocol_Release(protocol);
1412         }
1413
1414         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1415         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1416
1417         if(SUCCEEDED(hres)) {
1418             if(file_protocol_start(protocol, url, TRUE)) {
1419                 hres = IInternetProtocol_LockRequest(protocol, 0);
1420                 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1421                 hres = IInternetProtocol_Terminate(protocol, 0);
1422                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1423                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1424                 ok(hres == S_OK, "Read failed: %08x\n\n", hres);
1425                 hres = IInternetProtocol_UnlockRequest(protocol);
1426                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1427                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1428                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1429                 hres = IInternetProtocol_Terminate(protocol, 0);
1430                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1431             }
1432
1433             IInternetProtocol_Release(protocol);
1434         }
1435
1436         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1437         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1438
1439         if(SUCCEEDED(hres)) {
1440             if(file_protocol_start(protocol, url, TRUE)) {
1441                 hres = IInternetProtocol_Terminate(protocol, 0);
1442                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1443                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1444                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1445                 ok(cb == 2, "cb=%u expected 2\n", cb);
1446             }
1447
1448             IInternetProtocol_Release(protocol);
1449         }
1450
1451         IClassFactory_Release(factory);
1452     }
1453
1454     IUnknown_Release(unk);
1455 }
1456
1457 static void test_file_protocol_fail(void)
1458 {
1459     IInternetProtocol *protocol;
1460     HRESULT hres;
1461
1462     static const WCHAR index_url2[] =
1463         {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
1464
1465     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1466             &IID_IInternetProtocol, (void**)&protocol);
1467     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1468     if(FAILED(hres))
1469         return;
1470
1471     SET_EXPECT(GetBindInfo);
1472     expect_hrResult = MK_E_SYNTAX;
1473     hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
1474     ok(hres == MK_E_SYNTAX ||
1475        hres == E_INVALIDARG,
1476        "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres);
1477     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
1478
1479     SET_EXPECT(GetBindInfo);
1480     if(!(bindf & BINDF_FROMURLMON))
1481         SET_EXPECT(ReportProgress_DIRECTBIND);
1482     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1483     SET_EXPECT(ReportResult);
1484     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1485     hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
1486     ok(hres == INET_E_RESOURCE_NOT_FOUND,
1487             "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1488     CHECK_CALLED(GetBindInfo);
1489     if(!(bindf & BINDF_FROMURLMON))
1490         CHECK_CALLED(ReportProgress_DIRECTBIND);
1491     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1492     CHECK_CALLED(ReportResult);
1493
1494     IInternetProtocol_Release(protocol);
1495
1496     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1497             &IID_IInternetProtocol, (void**)&protocol);
1498     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1499     if(FAILED(hres))
1500         return;
1501
1502     SET_EXPECT(GetBindInfo);
1503     if(!(bindf & BINDF_FROMURLMON))
1504         SET_EXPECT(ReportProgress_DIRECTBIND);
1505     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1506     SET_EXPECT(ReportResult);
1507     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1508
1509     hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
1510     ok(hres == INET_E_RESOURCE_NOT_FOUND,
1511             "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1512     CHECK_CALLED(GetBindInfo);
1513     if(!(bindf & BINDF_FROMURLMON))
1514         CHECK_CALLED(ReportProgress_DIRECTBIND);
1515     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1516     CHECK_CALLED(ReportResult);
1517
1518     SET_EXPECT(GetBindInfo);
1519     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
1520     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1521     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
1522
1523     SET_EXPECT(GetBindInfo);
1524     hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0);
1525     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1526     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
1527
1528     IInternetProtocol_Release(protocol);
1529 }
1530
1531 static void test_file_protocol(void) {
1532     WCHAR buf[INTERNET_MAX_URL_LENGTH], file_name_buf[MAX_PATH];
1533     DWORD size;
1534     ULONG len;
1535     HANDLE file;
1536
1537     static const WCHAR wszFile[] = {'f','i','l','e',':',0};
1538     static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
1539     static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
1540     static const char html_doc[] = "<HTML></HTML>";
1541
1542     trace("Testing file protocol...\n");
1543     tested_protocol = FILE_TEST;
1544
1545     SetLastError(0xdeadbeef);
1546     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1547             FILE_ATTRIBUTE_NORMAL, NULL);
1548     if(!file && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1549     {
1550         win_skip("Detected Win9x or WinMe\n");
1551         return;
1552     }
1553     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1554     if(file == INVALID_HANDLE_VALUE)
1555         return;
1556     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
1557     CloseHandle(file);
1558
1559     file_name = wszIndexHtml;
1560     bindf = 0;
1561     test_file_protocol_url(index_url);
1562     bindf = BINDF_FROMURLMON;
1563     test_file_protocol_url(index_url);
1564     bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
1565     test_file_protocol_url(index_url);
1566
1567     memcpy(buf, wszFile, sizeof(wszFile));
1568     len = sizeof(wszFile)/sizeof(WCHAR)-1;
1569     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1570     buf[len++] = '\\';
1571     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1572
1573     file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
1574     bindf = 0;
1575     test_file_protocol_url(buf);
1576     bindf = BINDF_FROMURLMON;
1577     test_file_protocol_url(buf);
1578
1579     memcpy(buf, wszFile2, sizeof(wszFile2));
1580     len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
1581     file_name_buf[len++] = '\\';
1582     memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1583     lstrcpyW(buf+sizeof(wszFile2)/sizeof(WCHAR)-1, file_name_buf);
1584     file_name = file_name_buf;
1585     bindf = 0;
1586     test_file_protocol_url(buf);
1587     bindf = BINDF_FROMURLMON;
1588     test_file_protocol_url(buf);
1589
1590     buf[sizeof(wszFile2)/sizeof(WCHAR)] = '|';
1591     test_file_protocol_url(buf);
1592
1593     memcpy(buf, wszFile3, sizeof(wszFile3));
1594     len = sizeof(wszFile3)/sizeof(WCHAR)-1;
1595     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1596     buf[len++] = '\\';
1597     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1598
1599     file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
1600     bindf = 0;
1601     test_file_protocol_url(buf);
1602     bindf = BINDF_FROMURLMON;
1603     test_file_protocol_url(buf);
1604
1605     DeleteFileW(wszIndexHtml);
1606
1607     bindf = 0;
1608     test_file_protocol_fail();
1609     bindf = BINDF_FROMURLMON;
1610     test_file_protocol_fail();
1611 }
1612
1613 static BOOL http_protocol_start(LPCWSTR url, BOOL is_first)
1614 {
1615     static BOOL got_user_agent = FALSE;
1616     HRESULT hres;
1617
1618     first_data_notif = TRUE;
1619     state = 0;
1620
1621     SET_EXPECT(GetBindInfo);
1622     if (!(bindf & BINDF_FROMURLMON))
1623         SET_EXPECT(ReportProgress_DIRECTBIND);
1624     SET_EXPECT(GetBindString_USER_AGENT);
1625     SET_EXPECT(GetBindString_ACCEPT_MIMES);
1626     SET_EXPECT(QueryService_HttpNegotiate);
1627     SET_EXPECT(BeginningTransaction);
1628     SET_EXPECT(GetRootSecurityId);
1629     if (http_post_test)
1630         SET_EXPECT(GetBindString_POST_COOKIE);
1631
1632     hres = IInternetProtocol_Start(async_protocol, url, &protocol_sink, &bind_info, 0, 0);
1633     ok(hres == S_OK, "Start failed: %08x\n", hres);
1634     if(FAILED(hres))
1635         return FALSE;
1636
1637     CHECK_CALLED(GetBindInfo);
1638     if (!(bindf & BINDF_FROMURLMON))
1639         CHECK_CALLED(ReportProgress_DIRECTBIND);
1640     if (!got_user_agent)
1641     {
1642         CHECK_CALLED(GetBindString_USER_AGENT);
1643         got_user_agent = TRUE;
1644     }
1645     else todo_wine
1646     {
1647         /* user agent only retrieved once, even with different URLs */
1648         CHECK_NOT_CALLED(GetBindString_USER_AGENT);
1649     }
1650     CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1651     CHECK_CALLED(QueryService_HttpNegotiate);
1652     CHECK_CALLED(BeginningTransaction);
1653     /* GetRootSecurityId called on WinXP but not on Win98 */
1654     CLEAR_CALLED(GetRootSecurityId);
1655     if (http_post_test)
1656         CHECK_CALLED(GetBindString_POST_COOKIE);
1657
1658     return TRUE;
1659 }
1660
1661 static void test_protocol_terminate(IInternetProtocol *protocol)
1662 {
1663     BYTE buf[3600];
1664     DWORD cb;
1665     HRESULT hres;
1666
1667     hres = IInternetProtocol_LockRequest(protocol, 0);
1668     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1669
1670     hres = IInternetProtocol_Read(protocol, buf, 1, &cb);
1671     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1672
1673     hres = IInternetProtocol_Terminate(protocol, 0);
1674     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1675
1676     /* This wait is to give the internet handles being freed in Terminate
1677      * enough time to actually terminate in all cases. Internet handles
1678      * terminate asynchronously and native reuses the main InternetOpen
1679      * handle. The only case in which this seems to be necessary is on
1680      * wine with native wininet and urlmon, resulting in the next time
1681      * test_http_protocol_url being called the first data notification actually
1682      * being an extra last data notification from the previous connection
1683      * about once out of every ten times. */
1684     Sleep(100);
1685
1686     hres = IInternetProtocol_UnlockRequest(protocol);
1687     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1688 }
1689
1690 static void test_http_info(IInternetProtocol *protocol)
1691 {
1692     IWinInetHttpInfo *info;
1693     HRESULT hres;
1694
1695     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&info);
1696     ok(hres == S_OK, "Could not get IWinInterHttpInfo iface: %08x\n", hres);
1697
1698     /* TODO */
1699
1700     IWinInetHttpInfo_Release(info);
1701 }
1702
1703 /* is_first refers to whether this is the first call to this function
1704  * _for this url_ */
1705 static void test_http_protocol_url(LPCWSTR url, BOOL is_https, BOOL is_first)
1706 {
1707     IInternetProtocolInfo *protocol_info;
1708     IClassFactory *factory;
1709     IUnknown *unk;
1710     HRESULT hres;
1711
1712     http_url = url;
1713     http_is_first = is_first;
1714
1715     hres = CoGetClassObject(is_https ? &CLSID_HttpSProtocol : &CLSID_HttpProtocol,
1716             CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
1717     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1718     if(FAILED(hres))
1719         return;
1720
1721     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1722     ok(hres == E_NOINTERFACE,
1723         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1724         hres);
1725
1726     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1727     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1728     IUnknown_Release(unk);
1729     if(FAILED(hres))
1730         return;
1731
1732     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1733                                         (void**)&async_protocol);
1734     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1735     if(SUCCEEDED(hres)) {
1736         BYTE buf[3600];
1737         DWORD cb;
1738         ULONG ref;
1739
1740         test_priority(async_protocol);
1741         test_http_info(async_protocol);
1742
1743         SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1744         SET_EXPECT(ReportProgress_CONNECTING);
1745         SET_EXPECT(ReportProgress_SENDINGREQUEST);
1746         SET_EXPECT(ReportProgress_PROXYDETECTING);
1747         if(! is_https)
1748             SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1749         else
1750             SET_EXPECT(QueryService_HttpSecurity);
1751         if(!(bindf & BINDF_FROMURLMON)) {
1752             SET_EXPECT(OnResponse);
1753             SET_EXPECT(ReportProgress_RAWMIMETYPE);
1754             SET_EXPECT(ReportData);
1755         } else {
1756             SET_EXPECT(Switch);
1757         }
1758
1759         if(!http_protocol_start(url, is_first))
1760             return;
1761
1762         SET_EXPECT(ReportResult);
1763         expect_hrResult = S_OK;
1764
1765         hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
1766         ok((hres == E_PENDING && cb==0) ||
1767            (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
1768
1769         WaitForSingleObject(event_complete, INFINITE);
1770         if(bindf & BINDF_FROMURLMON)
1771             CHECK_CALLED(Switch);
1772         else
1773             CHECK_CALLED(ReportData);
1774         if (is_https)
1775             CLEAR_CALLED(QueryService_HttpSecurity);
1776
1777         while(1) {
1778             if(bindf & BINDF_FROMURLMON)
1779                 SET_EXPECT(Switch);
1780             else
1781                 SET_EXPECT(ReportData);
1782             hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
1783             if(hres == E_PENDING) {
1784                 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
1785                 ok((hres == E_PENDING && cb==0) ||
1786                    (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
1787                 WaitForSingleObject(event_complete, INFINITE);
1788                 if(bindf & BINDF_FROMURLMON)
1789                     CHECK_CALLED(Switch);
1790                 else
1791                     CHECK_CALLED(ReportData);
1792             }else {
1793                 if(bindf & BINDF_FROMURLMON)
1794                     CHECK_NOT_CALLED(Switch);
1795                 else
1796                     CHECK_NOT_CALLED(ReportData);
1797                 if(cb == 0) break;
1798             }
1799         }
1800         ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1801         CHECK_CALLED(ReportResult);
1802         if (is_https)
1803             CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
1804
1805         test_protocol_terminate(async_protocol);
1806         ref = IInternetProtocol_Release(async_protocol);
1807         ok(!ref, "ref=%x\n", hres);
1808     }
1809
1810     IClassFactory_Release(factory);
1811 }
1812
1813 static void test_http_protocol(void)
1814 {
1815     static const WCHAR winehq_url[] =
1816         {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
1817             'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
1818     static const WCHAR posttest_url[] =
1819         {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.',
1820          'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/',
1821          'p','o','s','t','t','e','s','t','.','p','h','p',0};
1822
1823     trace("Testing http protocol (not from urlmon)...\n");
1824     tested_protocol = HTTP_TEST;
1825     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
1826     test_http_protocol_url(winehq_url, FALSE, TRUE);
1827
1828     trace("Testing http protocol (from urlmon)...\n");
1829     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
1830     test_http_protocol_url(winehq_url, FALSE, FALSE);
1831
1832     trace("Testing http protocol (to file)...\n");
1833     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE;
1834     test_http_protocol_url(winehq_url, FALSE, FALSE);
1835
1836     trace("Testing http protocol (post data)...\n");
1837     http_post_test = TRUE;
1838     /* Without this flag we get a ReportProgress_CACHEFILENAMEAVAILABLE
1839      * notification with BINDVERB_POST */
1840     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
1841     test_http_protocol_url(posttest_url, FALSE, TRUE);
1842     http_post_test = FALSE;
1843 }
1844
1845 static void test_https_protocol(void)
1846 {
1847     static const WCHAR codeweavers_url[] =
1848         {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
1849          '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0};
1850
1851     trace("Testing https protocol (from urlmon)...\n");
1852     tested_protocol = HTTPS_TEST;
1853     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
1854     test_http_protocol_url(codeweavers_url, TRUE, TRUE);
1855 }
1856
1857
1858 static void test_ftp_protocol(void)
1859 {
1860     IInternetProtocolInfo *protocol_info;
1861     IClassFactory *factory;
1862     IUnknown *unk;
1863     BYTE buf[4096];
1864     ULONG ref;
1865     DWORD cb;
1866     HRESULT hres;
1867
1868     static const WCHAR ftp_urlW[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
1869     '/','p','u','b','/','o','t','h','e','r','/',
1870     'w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0};
1871
1872     trace("Testing ftp protocol...\n");
1873
1874     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
1875     state = 0;
1876     tested_protocol = FTP_TEST;
1877     first_data_notif = TRUE;
1878     expect_hrResult = E_PENDING;
1879
1880     hres = CoGetClassObject(&CLSID_FtpProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
1881     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1882     if(FAILED(hres))
1883         return;
1884
1885     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1886     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
1887
1888     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1889     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1890     IUnknown_Release(unk);
1891     if(FAILED(hres))
1892         return;
1893
1894     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1895                                         (void**)&async_protocol);
1896     IClassFactory_Release(factory);
1897     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1898
1899     test_priority(async_protocol);
1900     test_http_info(async_protocol);
1901
1902     SET_EXPECT(GetBindInfo);
1903     SET_EXPECT(GetBindString_USER_AGENT);
1904     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1905     SET_EXPECT(ReportProgress_CONNECTING);
1906     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1907     SET_EXPECT(Switch);
1908
1909     hres = IInternetProtocol_Start(async_protocol, ftp_urlW, &protocol_sink, &bind_info, 0, 0);
1910     ok(hres == S_OK, "Start failed: %08x\n", hres);
1911     CHECK_CALLED(GetBindInfo);
1912     todo_wine CHECK_NOT_CALLED(GetBindString_USER_AGENT);
1913
1914     SET_EXPECT(ReportResult);
1915
1916     hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
1917     ok((hres == E_PENDING && cb==0) ||
1918        (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
1919
1920     WaitForSingleObject(event_complete, INFINITE);
1921
1922     while(1) {
1923
1924         hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
1925         if(hres == E_PENDING)
1926             WaitForSingleObject(event_complete, INFINITE);
1927         else
1928             if(cb == 0) break;
1929     }
1930
1931     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1932     CHECK_CALLED(ReportResult);
1933     CHECK_CALLED(Switch);
1934
1935     test_protocol_terminate(async_protocol);
1936
1937     ref = IInternetProtocol_Release(async_protocol);
1938     ok(!ref, "ref=%d\n", ref);
1939 }
1940
1941 static void test_gopher_protocol(void)
1942 {
1943     IInternetProtocolInfo *protocol_info;
1944     IClassFactory *factory;
1945     IUnknown *unk;
1946     HRESULT hres;
1947
1948     trace("Testing gopher protocol...\n");
1949
1950     hres = CoGetClassObject(&CLSID_GopherProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
1951     ok(hres == S_OK ||
1952        hres == REGDB_E_CLASSNOTREG, /* Gopher protocol has been removed as of Vista */
1953        "CoGetClassObject failed: %08x\n", hres);
1954     if(FAILED(hres))
1955         return;
1956
1957     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1958     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
1959
1960     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1961     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1962     IUnknown_Release(unk);
1963     if(FAILED(hres))
1964         return;
1965
1966     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1967                                         (void**)&async_protocol);
1968     IClassFactory_Release(factory);
1969     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1970
1971     test_priority(async_protocol);
1972
1973     IInternetProtocol_Release(async_protocol);
1974 }
1975
1976 static void test_mk_protocol(void)
1977 {
1978     IInternetProtocolInfo *protocol_info;
1979     IInternetProtocol *protocol;
1980     IClassFactory *factory;
1981     IUnknown *unk;
1982     HRESULT hres;
1983
1984     static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
1985                                        ':',':','/','t','e','s','t','.','h','t','m','l',0};
1986     static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
1987
1988     trace("Testing mk protocol...\n");
1989     tested_protocol = MK_TEST;
1990
1991     hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
1992             &IID_IUnknown, (void**)&unk);
1993     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1994
1995     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1996     ok(hres == E_NOINTERFACE,
1997         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1998         hres);
1999
2000     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2001     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2002     IUnknown_Release(unk);
2003     if(FAILED(hres))
2004         return;
2005
2006     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
2007                                         (void**)&protocol);
2008     IClassFactory_Release(factory);
2009     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2010
2011     SET_EXPECT(GetBindInfo);
2012     hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
2013     ok(hres == MK_E_SYNTAX || hres == INET_E_INVALID_URL,
2014        "Start failed: %08x, expected MK_E_SYNTAX or INET_E_INVALID_URL\n", hres);
2015     CLEAR_CALLED(GetBindInfo);
2016
2017     SET_EXPECT(GetBindInfo);
2018     SET_EXPECT(ReportProgress_DIRECTBIND);
2019     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2020     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2021     SET_EXPECT(ReportResult);
2022     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2023
2024     hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
2025     ok(hres == INET_E_RESOURCE_NOT_FOUND ||
2026        hres == INET_E_INVALID_URL, /* win2k3 */
2027        "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND or INET_E_INVALID_URL\n", hres);
2028
2029     if (hres == INET_E_RESOURCE_NOT_FOUND) {
2030         CHECK_CALLED(GetBindInfo);
2031         CLEAR_CALLED(ReportProgress_DIRECTBIND);
2032         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2033         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2034         CHECK_CALLED(ReportResult);
2035     }else {
2036         CLEAR_CALLED(GetBindInfo);
2037         CLEAR_CALLED(ReportProgress_DIRECTBIND);
2038         CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
2039         CLEAR_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2040         CLEAR_CALLED(ReportResult);
2041     }
2042
2043     IInternetProtocol_Release(protocol);
2044 }
2045
2046 static void test_CreateBinding(void)
2047 {
2048     IInternetProtocolSink *sink;
2049     IInternetProtocol *protocol;
2050     IInternetPriority *priority;
2051     IInternetSession *session;
2052     LONG p;
2053     BYTE buf[1000];
2054     DWORD read;
2055     HRESULT hres;
2056
2057     static const WCHAR test_url[] =
2058         {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
2059     static const WCHAR wsz_test[] = {'t','e','s','t',0};
2060
2061     trace("Testing CreateBinding...\n");
2062     tested_protocol = BIND_TEST;
2063     binding_test = TRUE;
2064
2065     hres = CoInternetGetSession(0, &session, 0);
2066     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2067
2068     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
2069     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
2070
2071     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
2072     binding_protocol = protocol;
2073     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
2074     ok(protocol != NULL, "protocol == NULL\n");
2075
2076     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
2077     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
2078
2079     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&sink);
2080     ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres);
2081
2082     hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
2083     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2084     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
2085     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2086     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
2087     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2088
2089     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
2090     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
2091
2092     p = 0xdeadbeef;
2093     hres = IInternetPriority_GetPriority(priority, &p);
2094     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2095     ok(!p, "p=%d\n", p);
2096
2097     ex_priority = 100;
2098     hres = IInternetPriority_SetPriority(priority, 100);
2099     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2100
2101     p = 0xdeadbeef;
2102     hres = IInternetPriority_GetPriority(priority, &p);
2103     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2104     ok(p == 100, "p=%d\n", p);
2105
2106     SET_EXPECT(QueryService_InternetProtocol);
2107     SET_EXPECT(CreateInstance);
2108     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
2109     SET_EXPECT(SetPriority);
2110     SET_EXPECT(Start);
2111
2112     expect_hrResult = S_OK;
2113     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
2114     ok(hres == S_OK, "Start failed: %08x\n", hres);
2115
2116     CHECK_CALLED(QueryService_InternetProtocol);
2117     CHECK_CALLED(CreateInstance);
2118     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
2119     CHECK_CALLED(SetPriority);
2120     CHECK_CALLED(Start);
2121
2122     SET_EXPECT(Read);
2123     read = 0xdeadbeef;
2124     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
2125     ok(hres == S_OK, "Read failed: %08x\n", hres);
2126     ok(read == 100, "read = %d\n", read);
2127     CHECK_CALLED(Read);
2128
2129     SET_EXPECT(Read);
2130     read = 0xdeadbeef;
2131     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
2132     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2133     ok(!read, "read = %d\n", read);
2134     CHECK_CALLED(Read);
2135
2136     p = 0xdeadbeef;
2137     hres = IInternetPriority_GetPriority(priority, &p);
2138     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2139     ok(p == 100, "p=%d\n", p);
2140
2141     hres = IInternetPriority_SetPriority(priority, 101);
2142     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2143
2144     SET_EXPECT(Terminate);
2145     hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
2146     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2147     CHECK_CALLED(Terminate);
2148
2149     SET_EXPECT(Continue);
2150     hres = IInternetProtocolSink_Switch(sink, &protocoldata);
2151     ok(hres == S_OK, "Switch failed: %08x\n", hres);
2152     CHECK_CALLED(Continue);
2153
2154     hres = IInternetProtocolSink_ReportProgress(sink,
2155             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
2156     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
2157
2158     hres = IInternetProtocolSink_ReportResult(sink, S_OK, ERROR_SUCCESS, NULL);
2159     ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres);
2160
2161     hres = IInternetProtocolSink_ReportData(sink, 0, 0, 0);
2162     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2163
2164     IInternetProtocolSink_Release(sink);
2165     IInternetPriority_Release(priority);
2166     IInternetBindInfo_Release(prot_bind_info);
2167     IInternetProtocol_Release(protocol);
2168     IInternetSession_Release(session);
2169 }
2170
2171 static void test_binding(int prot)
2172 {
2173     IInternetProtocol *protocol;
2174     IInternetSession *session;
2175     ULONG ref;
2176     HRESULT hres;
2177
2178     trace("Testing %s binding...\n", debugstr_w(protocol_names[prot]));
2179
2180     tested_protocol = prot;
2181     binding_test = TRUE;
2182     first_data_notif = TRUE;
2183     prot_read = 0;
2184
2185     hres = CoInternetGetSession(0, &session, 0);
2186     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2187
2188     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, protocol_names[prot], 0, NULL, 0);
2189     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
2190
2191     hres = IInternetSession_CreateBinding(session, NULL, binding_urls[prot], NULL, NULL, &protocol, 0);
2192     binding_protocol = protocol;
2193     IInternetSession_Release(session);
2194     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
2195     ok(protocol != NULL, "protocol == NULL\n");
2196
2197     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
2198     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
2199
2200     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
2201     ok(hres == S_OK, "QueryInterface(IID_IInternetProtocolSink) failed: %08x\n", hres);
2202
2203     ex_priority = 0;
2204     SET_EXPECT(QueryService_InternetProtocol);
2205     SET_EXPECT(CreateInstance);
2206     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
2207     SET_EXPECT(SetPriority);
2208     SET_EXPECT(Start);
2209
2210     expect_hrResult = S_OK;
2211     hres = IInternetProtocol_Start(protocol, binding_urls[prot], &protocol_sink, &bind_info, 0, 0);
2212     ok(hres == S_OK, "Start failed: %08x\n", hres);
2213
2214     CHECK_CALLED(QueryService_InternetProtocol);
2215     CHECK_CALLED(CreateInstance);
2216     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
2217     CHECK_CALLED(SetPriority);
2218     CHECK_CALLED(Start);
2219
2220     if(prot == HTTP_TEST || prot == HTTPS_TEST) {
2221         while(prot_state < 4) {
2222             WaitForSingleObject(event_complete, INFINITE);
2223             SET_EXPECT(Continue);
2224             IInternetProtocol_Continue(protocol, pdata);
2225             CHECK_CALLED(Continue);
2226             SetEvent(event_complete2);
2227         }
2228
2229         WaitForSingleObject(event_complete, INFINITE);
2230     }else {
2231         SET_EXPECT(LockRequest);
2232         hres = IInternetProtocol_LockRequest(protocol, 0);
2233         ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2234         CHECK_CALLED(LockRequest);
2235
2236         SET_EXPECT(UnlockRequest);
2237         hres = IInternetProtocol_UnlockRequest(protocol);
2238         ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2239         CHECK_CALLED(UnlockRequest);
2240     }
2241
2242     SET_EXPECT(Terminate);
2243     hres = IInternetProtocol_Terminate(protocol, 0);
2244     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2245     CHECK_CALLED(Terminate);
2246
2247     IInternetBindInfo_Release(prot_bind_info);
2248     IInternetProtocolSink_Release(binding_sink);
2249     ref = IInternetProtocol_Release(protocol);
2250     ok(!ref, "ref=%u, expected 0\n", ref);
2251 }
2252
2253 START_TEST(protocol)
2254 {
2255     OleInitialize(NULL);
2256
2257     event_complete = CreateEvent(NULL, FALSE, FALSE, NULL);
2258     event_complete2 = CreateEvent(NULL, FALSE, FALSE, NULL);
2259
2260     test_file_protocol();
2261     test_http_protocol();
2262     test_https_protocol();
2263     test_ftp_protocol();
2264     test_gopher_protocol();
2265     test_mk_protocol();
2266     test_CreateBinding();
2267     test_binding(FILE_TEST);
2268     test_binding(HTTP_TEST);
2269
2270     CloseHandle(event_complete);
2271     CloseHandle(event_complete2);
2272
2273     OleUninitialize();
2274 }