urlmon: Use a copy of PROTOCOLDATA in Switch/Continue implementation.
[wine] / dlls / urlmon / tests / protocol.c
1 /*
2  * Copyright 2005-2009 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(ReportProgress_LOADINGMIMEHANDLER);
81 DEFINE_EXPECT(ReportProgress_DECODING);
82 DEFINE_EXPECT(ReportData);
83 DEFINE_EXPECT(ReportResult);
84 DEFINE_EXPECT(GetBindString_ACCEPT_MIMES);
85 DEFINE_EXPECT(GetBindString_USER_AGENT);
86 DEFINE_EXPECT(GetBindString_POST_COOKIE);
87 DEFINE_EXPECT(GetBindString_URL);
88 DEFINE_EXPECT(QueryService_HttpNegotiate);
89 DEFINE_EXPECT(QueryService_InternetProtocol);
90 DEFINE_EXPECT(QueryService_HttpSecurity);
91 DEFINE_EXPECT(BeginningTransaction);
92 DEFINE_EXPECT(GetRootSecurityId);
93 DEFINE_EXPECT(OnResponse);
94 DEFINE_EXPECT(Switch);
95 DEFINE_EXPECT(Continue);
96 DEFINE_EXPECT(CreateInstance);
97 DEFINE_EXPECT(Start);
98 DEFINE_EXPECT(Terminate);
99 DEFINE_EXPECT(Read);
100 DEFINE_EXPECT(SetPriority);
101 DEFINE_EXPECT(LockRequest);
102 DEFINE_EXPECT(UnlockRequest);
103 DEFINE_EXPECT(MimeFilter_CreateInstance);
104 DEFINE_EXPECT(MimeFilter_Start);
105 DEFINE_EXPECT(MimeFilter_ReportProgress);
106 DEFINE_EXPECT(MimeFilter_ReportData);
107 DEFINE_EXPECT(MimeFilter_ReportResult);
108 DEFINE_EXPECT(MimeFilter_Terminate);
109 DEFINE_EXPECT(MimeFilter_LockRequest);
110 DEFINE_EXPECT(MimeFilter_UnlockRequest);
111 DEFINE_EXPECT(MimeFilter_Read);
112 DEFINE_EXPECT(MimeFilter_Switch);
113 DEFINE_EXPECT(MimeFilter_Continue);
114
115 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
116 static const WCHAR index_url[] =
117     {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
118
119 static const WCHAR acc_mimeW[] = {'*','/','*',0};
120 static const WCHAR user_agentW[] = {'W','i','n','e',0};
121 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
122 static const WCHAR hostW[] = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
123 static const WCHAR winehq_ipW[] = {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
124 static const WCHAR emptyW[] = {0};
125 static const WCHAR gzipW[] = {'g','z','i','p',0};
126
127 static HRESULT expect_hrResult;
128 static LPCWSTR file_name, http_url, expect_wsz;
129 static IInternetProtocol *async_protocol = NULL;
130 static BOOL first_data_notif = FALSE, http_is_first = FALSE,
131     http_post_test = FALSE;
132 static int state = 0, prot_state;
133 static DWORD bindf, ex_priority , pi;
134 static IInternetProtocol *binding_protocol, *filtered_protocol;
135 static IInternetBindInfo *prot_bind_info;
136 static IInternetProtocolSink *binding_sink, *filtered_sink;
137 static void *expect_pv;
138 static HANDLE event_complete, event_complete2;
139 static BOOL binding_test;
140 static PROTOCOLDATA protocoldata, *pdata;
141 static DWORD prot_read, pi, filter_state;
142 static BOOL security_problem = FALSE;
143 static BOOL async_read_pending, mimefilter_test;
144
145 static enum {
146     FILE_TEST,
147     HTTP_TEST,
148     HTTPS_TEST,
149     FTP_TEST,
150     MK_TEST,
151     BIND_TEST
152 } tested_protocol;
153
154 static const WCHAR protocol_names[][10] = {
155     {'f','i','l','e',0},
156     {'h','t','t','p',0},
157     {'h','t','t','p','s',0},
158     {'f','t','p',0},
159     {'m','k',0},
160     {'t','e','s','t',0}
161 };
162
163 static const WCHAR binding_urls[][130] = {
164     {'f','i','l','e',':','t','e','s','t','.','h','t','m','l',0},
165     {'h','t','t','p',':','/','/','t','e','s','t','/','t','e','s','t','.','h','t','m','l',0},
166     {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
167      '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0},
168     {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
169      '/','p','u','b','/','o','t','h','e','r',
170      '/','w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0},
171     {'m','k',':','t','e','s','t',0},
172     {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0}
173 };
174
175 static const char *debugstr_w(LPCWSTR str)
176 {
177     static char buf[512];
178     if(!str)
179         return "(null)";
180     WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
181     return buf;
182 }
183
184 static const char *debugstr_guid(REFIID riid)
185 {
186     static char buf[50];
187
188     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
189             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
190             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
191             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
192
193     return buf;
194 }
195
196 static int strcmp_wa(LPCWSTR strw, const char *stra)
197 {
198     WCHAR buf[512];
199     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
200     return lstrcmpW(strw, buf);
201 }
202
203 static HRESULT WINAPI HttpSecurity_QueryInterface(IHttpSecurity *iface, REFIID riid, void **ppv)
204 {
205     if(IsEqualGUID(&IID_IUnknown, riid)
206             || IsEqualGUID(&IID_IHttpSecurity, riid)) {
207         *ppv = iface;
208         return S_OK;
209     }
210
211     ok(0, "unexpected call\n");
212     return E_NOINTERFACE;
213 }
214
215 static ULONG WINAPI HttpSecurity_AddRef(IHttpSecurity *iface)
216 {
217     return 2;
218 }
219
220 static ULONG WINAPI HttpSecurity_Release(IHttpSecurity *iface)
221 {
222     return 1;
223 }
224
225 static  HRESULT WINAPI HttpSecurity_GetWindow(IHttpSecurity* iface, REFGUID rguidReason, HWND *phwnd)
226 {
227     trace("HttpSecurity_GetWindow\n");
228
229     return S_FALSE;
230 }
231
232 static HRESULT WINAPI HttpSecurity_OnSecurityProblem(IHttpSecurity *iface, DWORD dwProblem)
233 {
234     trace("Security problem: %u\n", dwProblem);
235     ok(dwProblem == ERROR_INTERNET_SEC_CERT_REV_FAILED, "Expected ERROR_INTERNET_SEC_CERT_REV_FAILED got %u\n", dwProblem);
236
237     /* Only retry once */
238     if (security_problem)
239         return E_ABORT;
240
241     security_problem = TRUE;
242     SET_EXPECT(BeginningTransaction);
243
244     return RPC_E_RETRY;
245 }
246
247 static IHttpSecurityVtbl HttpSecurityVtbl = {
248     HttpSecurity_QueryInterface,
249     HttpSecurity_AddRef,
250     HttpSecurity_Release,
251     HttpSecurity_GetWindow,
252     HttpSecurity_OnSecurityProblem
253 };
254
255 static IHttpSecurity http_security = { &HttpSecurityVtbl };
256
257 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
258 {
259     if(IsEqualGUID(&IID_IUnknown, riid)
260             || IsEqualGUID(&IID_IHttpNegotiate, riid)
261             || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
262         *ppv = iface;
263         return S_OK;
264     }
265
266     ok(0, "unexpected call\n");
267     return E_NOINTERFACE;
268 }
269
270 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
271 {
272     return 2;
273 }
274
275 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
276 {
277     return 1;
278 }
279
280 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
281         LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
282 {
283     LPWSTR addl_headers;
284
285     static const WCHAR wszHeaders[] =
286         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
287          'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
288          'd','e','d','\r','\n',0};
289
290     CHECK_EXPECT(BeginningTransaction);
291
292     if(binding_test)
293         ok(!lstrcmpW(szURL, binding_urls[tested_protocol]), "szURL != http_url\n");
294     else
295         ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
296     ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
297     ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
298     if(pszAdditionalHeaders)
299     {
300         ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
301         if (http_post_test)
302         {
303             addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
304             if (!addl_headers)
305             {
306                 http_post_test = FALSE;
307                 skip("Out of memory\n");
308                 return E_OUTOFMEMORY;
309             }
310             lstrcpyW(addl_headers, wszHeaders);
311             *pszAdditionalHeaders = addl_headers;
312         }
313     }
314
315     return S_OK;
316 }
317
318 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
319         LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
320 {
321     CHECK_EXPECT(OnResponse);
322
323     ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
324     ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
325     ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
326     ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
327
328     return S_OK;
329 }
330
331 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
332         BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
333 {
334     static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
335     
336     CHECK_EXPECT(GetRootSecurityId);
337
338     ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
339     ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
340     ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
341
342     if(pcbSecurityId) {
343         ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
344         *pcbSecurityId = sizeof(sec_id);
345     }
346
347     if(pbSecurityId)
348         memcpy(pbSecurityId, sec_id, sizeof(sec_id));
349
350     return E_FAIL;
351 }
352
353 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
354     HttpNegotiate_QueryInterface,
355     HttpNegotiate_AddRef,
356     HttpNegotiate_Release,
357     HttpNegotiate_BeginningTransaction,
358     HttpNegotiate_OnResponse,
359     HttpNegotiate_GetRootSecurityId
360 };
361
362 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
363
364 static HRESULT QueryInterface(REFIID,void**);
365
366 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
367 {
368     return QueryInterface(riid, ppv);
369 }
370
371 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
372 {
373     return 2;
374 }
375
376 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
377 {
378     return 1;
379 }
380
381 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
382         REFIID riid, void **ppv)
383 {
384     if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
385         CHECK_EXPECT2(QueryService_HttpNegotiate);
386         return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
387     }
388
389     if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
390         ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
391         CHECK_EXPECT(QueryService_InternetProtocol);
392         return E_NOINTERFACE;
393     }
394
395     if(IsEqualGUID(&IID_IHttpSecurity, guidService)) {
396         ok(IsEqualGUID(&IID_IHttpSecurity, riid), "unexpected riid\n");
397         CHECK_EXPECT(QueryService_HttpSecurity);
398         return IHttpSecurity_QueryInterface(&http_security, riid, ppv);
399     }
400
401     ok(0, "unexpected service %s\n", debugstr_guid(guidService));
402     return E_FAIL;
403 }
404
405 static const IServiceProviderVtbl ServiceProviderVtbl = {
406     ServiceProvider_QueryInterface,
407     ServiceProvider_AddRef,
408     ServiceProvider_Release,
409     ServiceProvider_QueryService
410 };
411
412 static IServiceProvider service_provider = { &ServiceProviderVtbl };
413
414 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
415 {
416     return QueryInterface(riid, ppv);
417 }
418
419 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
420 {
421     return 2;
422 }
423
424 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
425 {
426     return 1;
427 }
428
429 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
430 {
431     HRESULT hres;
432
433     if(tested_protocol == FTP_TEST)
434         CHECK_EXPECT2(Switch);
435     else
436         CHECK_EXPECT(Switch);
437
438     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
439     if(binding_test) {
440         ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
441         ok(!memcmp(pProtocolData, &protocoldata, sizeof(PROTOCOLDATA)), "*pProtocolData != protocoldata\n");
442     }
443
444     pdata = pProtocolData;
445
446     if(binding_test) {
447         SetEvent(event_complete);
448         WaitForSingleObject(event_complete2, INFINITE);
449         return S_OK;
450     }
451
452     if (!state) {
453         if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST) {
454             if (http_is_first) {
455                 CLEAR_CALLED(ReportProgress_FINDINGRESOURCE);
456                 CLEAR_CALLED(ReportProgress_CONNECTING);
457                 CLEAR_CALLED(ReportProgress_PROXYDETECTING);
458             } else todo_wine {
459                     CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
460                     /* IE7 does call this */
461                     CLEAR_CALLED(ReportProgress_CONNECTING);
462                 }
463         }
464         if(tested_protocol == FTP_TEST)
465             todo_wine CHECK_CALLED(ReportProgress_SENDINGREQUEST);
466         else if (tested_protocol != HTTPS_TEST)
467             CHECK_CALLED(ReportProgress_SENDINGREQUEST);
468         if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
469             SET_EXPECT(OnResponse);
470             if(tested_protocol == HTTPS_TEST)
471                 SET_EXPECT(ReportProgress_ACCEPTRANGES);
472             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
473             if(bindf & BINDF_NEEDFILE)
474                 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
475         }
476     }
477
478     SET_EXPECT(ReportData);
479     hres = IInternetProtocol_Continue(async_protocol, pProtocolData);
480     ok(hres == S_OK, "Continue failed: %08x\n", hres);
481     if(tested_protocol == FTP_TEST)
482         CLEAR_CALLED(ReportData);
483     else if (! security_problem)
484         CHECK_CALLED(ReportData);
485
486     if (!state) {
487         if (! security_problem)
488         {
489             state = 1;
490             if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
491                 CHECK_CALLED(OnResponse);
492                 if(tested_protocol == HTTPS_TEST)
493                     CHECK_CALLED(ReportProgress_ACCEPTRANGES);
494                 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
495                 if(bindf & BINDF_NEEDFILE)
496                     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
497             }
498         }
499         else
500         {
501             security_problem = FALSE;
502             SET_EXPECT(ReportProgress_CONNECTING);
503         }
504     }
505
506     SetEvent(event_complete);
507
508     return S_OK;
509 }
510
511 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
512         LPCWSTR szStatusText)
513 {
514     static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
515         '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
516     static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
517
518     switch(ulStatusCode) {
519     case BINDSTATUS_MIMETYPEAVAILABLE:
520         CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
521         ok(szStatusText != NULL, "szStatusText == NULL\n");
522         if(szStatusText) {
523             if(tested_protocol == BIND_TEST)
524                 ok(szStatusText == expect_wsz, "unexpected szStatusText\n");
525             else if (http_post_test)
526                 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
527                    !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
528                    "szStatusText != text/plain\n");
529             else if(!mimefilter_test)
530                 ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) &&
531                    !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
532                    "szStatusText != text/html\n");
533         }
534         break;
535     case BINDSTATUS_DIRECTBIND:
536         CHECK_EXPECT2(ReportProgress_DIRECTBIND);
537         ok(szStatusText == NULL, "szStatusText != NULL\n");
538         break;
539     case BINDSTATUS_RAWMIMETYPE:
540         CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
541         ok(szStatusText != NULL, "szStatusText == NULL\n");
542         if(szStatusText)
543             ok(lstrlenW(szStatusText) < lstrlenW(text_htmlW) ||
544                !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
545                "szStatusText != text/html\n");
546         break;
547     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
548         CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
549         ok(szStatusText != NULL, "szStatusText == NULL\n");
550         if(szStatusText) {
551             if(binding_test)
552                 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText\n");
553             else if(tested_protocol == FILE_TEST)
554                 ok(!lstrcmpW(szStatusText, file_name), "szStatusText = \"%s\"\n", debugstr_w(szStatusText));
555             else
556                 ok(szStatusText != NULL, "szStatusText == NULL\n");
557         }
558         break;
559     case BINDSTATUS_FINDINGRESOURCE:
560         CHECK_EXPECT2(ReportProgress_FINDINGRESOURCE);
561         ok(szStatusText != NULL, "szStatusText == NULL\n");
562         break;
563     case BINDSTATUS_CONNECTING:
564         CHECK_EXPECT2(ReportProgress_CONNECTING);
565         ok(szStatusText != NULL, "szStatusText == NULL\n");
566         break;
567     case BINDSTATUS_SENDINGREQUEST:
568         CHECK_EXPECT2(ReportProgress_SENDINGREQUEST);
569         if(tested_protocol == FILE_TEST) {
570             ok(szStatusText != NULL, "szStatusText == NULL\n");
571             if(szStatusText)
572                 ok(!*szStatusText, "wrong szStatusText\n");
573         }
574         break;
575     case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
576         CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
577         ok(szStatusText != NULL, "szStatusText == NULL\n");
578         if(szStatusText)
579             ok(!lstrcmpW(szStatusText, text_htmlW), "szStatusText != text/html\n");
580         break;
581     case BINDSTATUS_PROTOCOLCLASSID:
582         CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
583         ok(szStatusText != NULL, "szStatusText == NULL\n");
584         ok(!lstrcmpW(szStatusText, null_guid), "unexpected szStatusText\n");
585         break;
586     case BINDSTATUS_COOKIE_SENT:
587         CHECK_EXPECT(ReportProgress_COOKIE_SENT);
588         ok(szStatusText == NULL, "szStatusText != NULL\n");
589         break;
590     case BINDSTATUS_REDIRECTING:
591         CHECK_EXPECT(ReportProgress_REDIRECTING);
592         ok(szStatusText == NULL, "szStatusText = %s\n", debugstr_w(szStatusText));
593         break;
594     case BINDSTATUS_ENCODING:
595         CHECK_EXPECT(ReportProgress_ENCODING);
596         ok(!strcmp_wa(szStatusText, "gzip"), "szStatusText = %s\n", debugstr_w(szStatusText));
597         break;
598     case BINDSTATUS_ACCEPTRANGES:
599         CHECK_EXPECT(ReportProgress_ACCEPTRANGES);
600         ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText));
601         break;
602     case BINDSTATUS_PROXYDETECTING:
603         CHECK_EXPECT(ReportProgress_PROXYDETECTING);
604         SET_EXPECT(ReportProgress_CONNECTING);
605         ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText));
606         break;
607     case BINDSTATUS_LOADINGMIMEHANDLER:
608         CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
609         ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText));
610         break;
611     case BINDSTATUS_DECODING:
612         CHECK_EXPECT(ReportProgress_DECODING);
613         ok(!lstrcmpW(szStatusText, gzipW), "szStatusText = %s\n", debugstr_w(szStatusText));
614         break;
615     default:
616         ok(0, "Unexpected status %d\n", ulStatusCode);
617     };
618
619     return S_OK;
620 }
621
622 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
623         ULONG ulProgress, ULONG ulProgressMax)
624 {
625     if(!mimefilter_test && tested_protocol == FILE_TEST) {
626         CHECK_EXPECT2(ReportData);
627
628         ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
629            ulProgress, ulProgressMax);
630         ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
631         /* BSCF_SKIPDRAINDATAFORFILEURLS added in IE8 */
632         ok((grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION)) ||
633            (grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_SKIPDRAINDATAFORFILEURLS)),
634                 "grcfBSCF = %08x\n", grfBSCF);
635     }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST)) {
636         if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
637             CHECK_EXPECT(ReportData);
638         else if (http_post_test)
639             ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
640
641         ok(ulProgress, "ulProgress == 0\n");
642
643         if(first_data_notif) {
644             ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
645                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
646                "grcfBSCF = %08x\n", grfBSCF);
647             first_data_notif = FALSE;
648         } else {
649             ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
650                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
651                || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
652                "grcfBSCF = %08x\n", grfBSCF);
653         }
654
655         if(!(bindf & BINDF_FROMURLMON) &&
656            !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
657             if(!state) {
658                 state = 1;
659                 if(http_is_first) {
660                     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
661                     CHECK_CALLED(ReportProgress_CONNECTING);
662                 } else todo_wine {
663                     CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
664                     CHECK_NOT_CALLED(ReportProgress_CONNECTING);
665                 }
666                 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
667                 CHECK_CALLED(OnResponse);
668                 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
669             }
670             SetEvent(event_complete);
671         }
672     }else {
673         BYTE buf[1000];
674         ULONG read;
675         HRESULT hres;
676
677         CHECK_EXPECT(ReportData);
678
679         if(tested_protocol == BIND_TEST)
680             return S_OK;
681
682         do {
683             if(mimefilter_test)
684                 SET_EXPECT(MimeFilter_Read);
685             else
686                 SET_EXPECT(Read);
687             hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
688             if(mimefilter_test)
689                 CHECK_CALLED(MimeFilter_Read);
690             else
691                 CHECK_CALLED(Read);
692         }while(hres == S_OK);
693     }
694
695     return S_OK;
696 }
697
698 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
699         DWORD dwError, LPCWSTR szResult)
700 {
701     CHECK_EXPECT(ReportResult);
702
703     if(tested_protocol == FTP_TEST)
704         ok(hrResult == E_PENDING || hrResult == S_OK, "hrResult = %08x, expected E_PENDING or S_OK\n", hrResult);
705     else
706         ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
707            hrResult, expect_hrResult);
708     if(SUCCEEDED(hrResult) || tested_protocol == FTP_TEST)
709         ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
710     else
711         ok(dwError != ERROR_SUCCESS ||
712            broken(tested_protocol == MK_TEST), /* Win9x, WinME and NT4 */
713            "dwError == ERROR_SUCCESS\n");
714     ok(!szResult, "szResult != NULL\n");
715
716     return S_OK;
717 }
718
719 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
720     ProtocolSink_QueryInterface,
721     ProtocolSink_AddRef,
722     ProtocolSink_Release,
723     ProtocolSink_Switch,
724     ProtocolSink_ReportProgress,
725     ProtocolSink_ReportData,
726     ProtocolSink_ReportResult
727 };
728
729 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
730
731 static HRESULT WINAPI MimeProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
732 {
733     ok(0, "unexpected call\n");
734     return E_NOTIMPL;
735 }
736
737 static ULONG WINAPI MimeProtocolSink_AddRef(IInternetProtocolSink *iface)
738 {
739     return 2;
740 }
741
742 static ULONG WINAPI MimeProtocolSink_Release(IInternetProtocolSink *iface)
743 {
744     return 1;
745 }
746
747 static HRESULT WINAPI MimeProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
748 {
749     HRESULT hres;
750
751     CHECK_EXPECT(MimeFilter_Switch);
752
753     SET_EXPECT(Switch);
754     hres = IInternetProtocolSink_Switch(filtered_sink, pProtocolData);
755     ok(hres == S_OK, "Switch failed: %08x\n", hres);
756     CHECK_CALLED(Switch);
757
758     return S_OK;
759 }
760
761 static HRESULT WINAPI MimeProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
762         LPCWSTR szStatusText)
763 {
764     CHECK_EXPECT(MimeFilter_ReportProgress);
765     return S_OK;
766 }
767
768 static HRESULT WINAPI MimeProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
769         ULONG ulProgress, ULONG ulProgressMax)
770 {
771     DWORD read = 0;
772     BYTE buf[8192];
773     HRESULT hres;
774
775     CHECK_EXPECT(MimeFilter_ReportData);
776
777     ok(ulProgress, "ulProgress == 0\n");
778
779     if(!filter_state) {
780         SET_EXPECT(Read);
781         hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
782         if(tested_protocol == HTTP_TEST)
783             ok(hres == S_OK || hres == E_PENDING || hres == S_FALSE, "Read failed: %08x\n", hres);
784         else
785             ok(hres == S_OK, "Read failed: %08x\n", hres);
786         CHECK_CALLED(Read);
787
788         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
789         hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, text_htmlW);
790         ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
791         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
792
793         /* FIXME: test BINDSTATUS_CACHEFILENAMEAVAILABLE */
794     }
795
796     SET_EXPECT(ReportData);
797     hres = IInternetProtocolSink_ReportData(filtered_sink, grfBSCF, ulProgress, ulProgressMax);
798     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
799     CHECK_CALLED(ReportData);
800
801     if(!filter_state)
802         filter_state = 1;
803
804     return S_OK;
805 }
806
807 static HRESULT WINAPI MimeProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
808         DWORD dwError, LPCWSTR szResult)
809 {
810     HRESULT hres;
811
812     CHECK_EXPECT(MimeFilter_ReportResult);
813
814     ok(hrResult == S_OK, "hrResult = %08x\n", hrResult);
815     ok(dwError == ERROR_SUCCESS, "dwError = %u\n", dwError);
816     ok(!szResult, "szResult = %s\n", debugstr_w(szResult));
817
818     SET_EXPECT(ReportResult);
819     hres = IInternetProtocolSink_ReportResult(filtered_sink, hrResult, dwError, szResult);
820     ok(SUCCEEDED(hres), "ReportResult failed: %08x\n", hres);
821     CHECK_CALLED(ReportResult);
822
823     return S_OK;
824 }
825
826 static IInternetProtocolSinkVtbl mime_protocol_sink_vtbl = {
827     MimeProtocolSink_QueryInterface,
828     MimeProtocolSink_AddRef,
829     MimeProtocolSink_Release,
830     MimeProtocolSink_Switch,
831     MimeProtocolSink_ReportProgress,
832     MimeProtocolSink_ReportData,
833     MimeProtocolSink_ReportResult
834 };
835
836 static IInternetProtocolSink mime_protocol_sink = { &mime_protocol_sink_vtbl };
837
838 static HRESULT QueryInterface(REFIID riid, void **ppv)
839 {
840     *ppv = NULL;
841
842     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
843         *ppv = &protocol_sink;
844     if(IsEqualGUID(&IID_IServiceProvider, riid))
845         *ppv = &service_provider;
846     if(IsEqualGUID(&IID_IUriContainer, riid))
847         return E_NOINTERFACE; /* TODO */
848
849     if(*ppv)
850         return S_OK;
851
852     ok(0, "unexpected call %s\n", debugstr_guid(riid));
853     return E_NOINTERFACE;
854 }
855
856 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
857 {
858     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
859         *ppv = iface;
860         return S_OK;
861     }
862     return E_NOINTERFACE;
863 }
864
865 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
866 {
867     return 2;
868 }
869
870 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
871 {
872     return 1;
873 }
874
875 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
876 {
877     DWORD cbSize;
878
879     static const CHAR szPostData[] = "mode=Test";
880
881     CHECK_EXPECT(GetBindInfo);
882
883     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
884     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
885     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
886
887     *grfBINDF = bindf;
888     if(binding_test)
889         *grfBINDF |= BINDF_FROMURLMON;
890     cbSize = pbindinfo->cbSize;
891     memset(pbindinfo, 0, cbSize);
892     pbindinfo->cbSize = cbSize;
893
894     if (http_post_test)
895     {
896         /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly
897          * with urlmon on native (Win98 and WinXP) */
898         U(pbindinfo->stgmedData).hGlobal = GlobalAlloc(GPTR, sizeof(szPostData));
899         if (!U(pbindinfo->stgmedData).hGlobal)
900         {
901             http_post_test = FALSE;
902             skip("Out of memory\n");
903             return E_OUTOFMEMORY;
904         }
905         lstrcpy((LPSTR)U(pbindinfo->stgmedData).hGlobal, szPostData);
906         pbindinfo->cbstgmedData = sizeof(szPostData)-1;
907         pbindinfo->dwBindVerb = BINDVERB_POST;
908         pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
909     }
910
911     return S_OK;
912 }
913
914 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
915         LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
916 {
917     ok(ppwzStr != NULL, "ppwzStr == NULL\n");
918     ok(pcElFetched != NULL, "pcElFetched == NULL\n");
919
920     switch(ulStringType) {
921     case BINDSTRING_ACCEPT_MIMES:
922         CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
923         ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
924         if(pcElFetched) {
925             ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
926             *pcElFetched = 1;
927         }
928         if(ppwzStr) {
929             *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
930             memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
931         }
932         return S_OK;
933     case BINDSTRING_USER_AGENT:
934         CHECK_EXPECT(GetBindString_USER_AGENT);
935         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
936         if(pcElFetched) {
937             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
938             *pcElFetched = 1;
939         }
940         if(ppwzStr) {
941             *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
942             memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
943         }
944         return S_OK;
945     case BINDSTRING_POST_COOKIE:
946         CHECK_EXPECT(GetBindString_POST_COOKIE);
947         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
948         if(pcElFetched)
949             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
950         return S_OK;
951     case BINDSTRING_URL: {
952         DWORD size;
953
954         CHECK_EXPECT(GetBindString_URL);
955         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
956         ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
957         *pcElFetched = 1;
958
959         size = (lstrlenW(binding_urls[tested_protocol])+1)*sizeof(WCHAR);
960         *ppwzStr = CoTaskMemAlloc(size);
961         memcpy(*ppwzStr, binding_urls[tested_protocol], size);
962         return S_OK;
963     }
964     default:
965         ok(0, "unexpected call\n");
966     }
967
968     return E_NOTIMPL;
969 }
970
971 static IInternetBindInfoVtbl bind_info_vtbl = {
972     BindInfo_QueryInterface,
973     BindInfo_AddRef,
974     BindInfo_Release,
975     BindInfo_GetBindInfo,
976     BindInfo_GetBindString
977 };
978
979 static IInternetBindInfo bind_info = { &bind_info_vtbl };
980
981 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
982                                                   REFIID riid, void **ppv)
983 {
984     ok(0, "unexpected call\n");
985     return E_NOINTERFACE;
986 }
987
988 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
989 {
990     return 2;
991 }
992
993 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
994 {
995     return 1;
996 }
997
998 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
999 {
1000     CHECK_EXPECT(SetPriority);
1001     ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
1002     return S_OK;
1003 }
1004
1005 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1006 {
1007     ok(0, "unexpected call\n");
1008     return E_NOTIMPL;
1009 }
1010
1011
1012 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1013     InternetPriority_QueryInterface,
1014     InternetPriority_AddRef,
1015     InternetPriority_Release,
1016     InternetPriority_SetPriority,
1017     InternetPriority_GetPriority
1018 };
1019
1020 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
1021
1022 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
1023 {
1024     return 2;
1025 }
1026
1027 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
1028 {
1029     return 1;
1030 }
1031
1032 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
1033         DWORD dwOptions)
1034 {
1035     ok(0, "unexpected call\n");
1036     return E_NOTIMPL;
1037 }
1038
1039 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
1040 {
1041     ok(0, "unexpected call\n");
1042     return E_NOTIMPL;
1043 }
1044
1045 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
1046 {
1047     ok(0, "unexpected call\n");
1048     return E_NOTIMPL;
1049 }
1050
1051 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
1052         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1053 {
1054     ok(0, "unexpected call\n");
1055     return E_NOTIMPL;
1056 }
1057
1058 static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
1059 {
1060     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
1061         *ppv = iface;
1062         return S_OK;
1063     }
1064
1065     if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
1066         trace("IID_IInternetProtocolEx not supported\n");
1067         *ppv = NULL;
1068         return E_NOINTERFACE;
1069     }
1070
1071     if(IsEqualGUID(&IID_IInternetPriority, riid)) {
1072         *ppv = &InternetPriority;
1073         return S_OK;
1074     }
1075
1076     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
1077     *ppv = NULL;
1078     return E_NOINTERFACE;
1079 }
1080
1081 static DWORD WINAPI thread_proc(PVOID arg)
1082 {
1083     HRESULT hres;
1084
1085     memset(&protocoldata, -1, sizeof(protocoldata));
1086
1087     prot_state = 0;
1088
1089     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1090     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1091             BINDSTATUS_FINDINGRESOURCE, hostW);
1092     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1093     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1094
1095     SET_EXPECT(ReportProgress_CONNECTING);
1096     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1097             BINDSTATUS_CONNECTING, winehq_ipW);
1098     CHECK_CALLED(ReportProgress_CONNECTING);
1099     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1100
1101     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1102     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1103             BINDSTATUS_SENDINGREQUEST, NULL);
1104     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1105     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1106
1107     prot_state = 1;
1108     SET_EXPECT(Switch);
1109     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1110     CHECK_CALLED(Switch);
1111     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1112
1113     prot_state = 2;
1114     if(mimefilter_test)
1115         SET_EXPECT(MimeFilter_Switch);
1116     else
1117         SET_EXPECT(Switch);
1118     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1119     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1120     if(mimefilter_test)
1121         CHECK_CALLED(MimeFilter_Switch);
1122     else
1123         CHECK_CALLED(Switch);
1124
1125     prot_state = 2;
1126     if(mimefilter_test)
1127         SET_EXPECT(MimeFilter_Switch);
1128     else
1129         SET_EXPECT(Switch);
1130     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1131     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1132     if(mimefilter_test)
1133         CHECK_CALLED(MimeFilter_Switch);
1134     else
1135         CHECK_CALLED(Switch);
1136
1137     prot_state = 3;
1138     if(mimefilter_test)
1139         SET_EXPECT(MimeFilter_Switch);
1140     else
1141         SET_EXPECT(Switch);
1142     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1143     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1144     if(mimefilter_test)
1145         CHECK_CALLED(MimeFilter_Switch);
1146     else
1147         CHECK_CALLED(Switch);
1148
1149     SetEvent(event_complete);
1150
1151     return 0;
1152 }
1153
1154 static HRESULT WINAPI ProtocolEmul_Start(IInternetProtocol *iface, LPCWSTR szUrl,
1155         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1156         DWORD grfPI, HANDLE_PTR dwReserved)
1157 {
1158     BINDINFO bindinfo, exp_bindinfo;
1159     DWORD cbindf = 0;
1160     HRESULT hres;
1161
1162     CHECK_EXPECT(Start);
1163
1164     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
1165     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
1166     ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
1167     ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
1168     ok(!grfPI, "grfPI = %x\n", grfPI);
1169     ok(!dwReserved, "dwReserved = %lx\n", dwReserved);
1170
1171     if(binding_test)
1172         ok(pOIProtSink == binding_sink, "pOIProtSink != binding_sink\n");
1173
1174     memset(&bindinfo, 0, sizeof(bindinfo));
1175     bindinfo.cbSize = sizeof(bindinfo);
1176     memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
1177     SET_EXPECT(GetBindInfo);
1178     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
1179     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
1180     CHECK_CALLED(GetBindInfo);
1181     ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
1182        cbindf, (bindf|BINDF_FROMURLMON));
1183     ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
1184     ReleaseBindInfo(&bindinfo);
1185
1186     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1187     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
1188     ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
1189     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1190
1191     if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
1192         IServiceProvider *service_provider;
1193         IHttpNegotiate *http_negotiate;
1194         IHttpNegotiate2 *http_negotiate2;
1195         LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
1196         LPWSTR additional_headers = NULL;
1197         BYTE sec_id[100];
1198         DWORD fetched = 0, size = 100;
1199         DWORD tid;
1200
1201         SET_EXPECT(GetBindString_USER_AGENT);
1202         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
1203                                                &ua, 1, &fetched);
1204         CHECK_CALLED(GetBindString_USER_AGENT);
1205         ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
1206         ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
1207         ok(ua != NULL, "ua =  %p\n", ua);
1208         ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", debugstr_w(ua));
1209         CoTaskMemFree(ua);
1210
1211         fetched = 256;
1212         SET_EXPECT(GetBindString_ACCEPT_MIMES);
1213         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
1214                                                accept_mimes, 256, &fetched);
1215         CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1216
1217         ok(hres == S_OK,
1218            "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
1219         ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
1220         ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", debugstr_w(accept_mimes[0]));
1221
1222         hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
1223                                                 (void**)&service_provider);
1224         ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
1225
1226         SET_EXPECT(QueryService_HttpNegotiate);
1227         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1228                 &IID_IHttpNegotiate, (void**)&http_negotiate);
1229         CHECK_CALLED(QueryService_HttpNegotiate);
1230         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1231
1232         SET_EXPECT(BeginningTransaction);
1233         hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
1234                                                    NULL, 0, &additional_headers);
1235         CHECK_CALLED(BeginningTransaction);
1236         IHttpNegotiate_Release(http_negotiate);
1237         ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
1238         ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
1239
1240         SET_EXPECT(QueryService_HttpNegotiate);
1241         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
1242                 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
1243         CHECK_CALLED(QueryService_HttpNegotiate);
1244         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1245
1246         size = 512;
1247         SET_EXPECT(GetRootSecurityId);
1248         hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
1249         CHECK_CALLED(GetRootSecurityId);
1250         IHttpNegotiate2_Release(http_negotiate2);
1251         ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
1252         ok(size == 13, "size=%d\n", size);
1253
1254         IServiceProvider_Release(service_provider);
1255
1256         CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
1257
1258         return S_OK;
1259     }
1260
1261     SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1262     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
1263             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1264     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1265     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1266
1267     if(mimefilter_test) {
1268         SET_EXPECT(MimeFilter_CreateInstance);
1269         SET_EXPECT(MimeFilter_Start);
1270         SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1271     }
1272     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1273     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
1274             mimefilter_test ? gzipW : (expect_wsz = text_htmlW));
1275     ok(hres == S_OK,
1276        "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
1277     if(mimefilter_test) {
1278         CHECK_CALLED(MimeFilter_CreateInstance);
1279         CHECK_CALLED(MimeFilter_Start);
1280         CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1281         todo_wine CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1282     }else {
1283         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1284     }
1285
1286     if(mimefilter_test)
1287         SET_EXPECT(MimeFilter_ReportData);
1288     else
1289         SET_EXPECT(ReportData);
1290     hres = IInternetProtocolSink_ReportData(pOIProtSink,
1291             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, 13, 13);
1292     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1293     if(mimefilter_test)
1294         CHECK_CALLED(MimeFilter_ReportData);
1295     else
1296         CHECK_CALLED(ReportData);
1297
1298     if(tested_protocol == BIND_TEST) {
1299         hres = IInternetProtocol_Terminate(binding_protocol, 0);
1300         ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
1301     }
1302
1303     if(mimefilter_test)
1304         SET_EXPECT(MimeFilter_ReportResult);
1305     else
1306         SET_EXPECT(ReportResult);
1307     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
1308     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1309     if(mimefilter_test)
1310         CHECK_CALLED(MimeFilter_ReportResult);
1311     else
1312         CHECK_CALLED(ReportResult);
1313
1314     return S_OK;
1315 }
1316
1317 static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocol *iface,
1318         PROTOCOLDATA *pProtocolData)
1319 {
1320     DWORD bscf = 0, pr;
1321     HRESULT hres;
1322
1323     CHECK_EXPECT(Continue);
1324
1325     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
1326     if(!pProtocolData || tested_protocol == BIND_TEST)
1327         return S_OK;
1328     if(binding_test) {
1329         ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
1330         ok(!memcmp(pProtocolData, &protocoldata, sizeof(PROTOCOLDATA)), "*pProtocolData != protocoldata\n");
1331     }
1332
1333     switch(prot_state) {
1334     case 1: {
1335         IServiceProvider *service_provider;
1336         IHttpNegotiate *http_negotiate;
1337         static WCHAR header[] = {'?',0};
1338
1339         hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
1340                                                     (void**)&service_provider);
1341         ok(hres == S_OK, "Could not get IServiceProvicder\n");
1342
1343         SET_EXPECT(QueryService_HttpNegotiate);
1344         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1345                                              &IID_IHttpNegotiate, (void**)&http_negotiate);
1346         IServiceProvider_Release(service_provider);
1347         CHECK_CALLED(QueryService_HttpNegotiate);
1348         ok(hres == S_OK, "Could not get IHttpNegotiate\n");
1349
1350         SET_EXPECT(OnResponse);
1351         hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
1352         IHttpNegotiate_Release(http_negotiate);
1353         CHECK_CALLED(OnResponse);
1354         IHttpNegotiate_Release(http_negotiate);
1355         ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
1356
1357         if(mimefilter_test) {
1358             SET_EXPECT(MimeFilter_CreateInstance);
1359             SET_EXPECT(MimeFilter_Start);
1360             SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1361         }else if(!(pi & PI_MIMEVERIFICATION)) {
1362             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1363         }
1364         hres = IInternetProtocolSink_ReportProgress(binding_sink,
1365                 BINDSTATUS_MIMETYPEAVAILABLE, mimefilter_test ? gzipW : text_htmlW);
1366         if(mimefilter_test) {
1367             CHECK_CALLED(MimeFilter_CreateInstance);
1368             CHECK_CALLED(MimeFilter_Start);
1369             CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1370         }else if(!(pi & PI_MIMEVERIFICATION)) {
1371             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1372         }
1373         ok(hres == S_OK,
1374            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
1375
1376         bscf |= BSCF_FIRSTDATANOTIFICATION;
1377         break;
1378     }
1379     case 2:
1380     case 3:
1381         bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
1382         break;
1383     }
1384
1385     pr = prot_read;
1386     if(mimefilter_test) {
1387         SET_EXPECT(MimeFilter_ReportData);
1388     }else if(pi & PI_MIMEVERIFICATION) {
1389         if(pr < 200)
1390             SET_EXPECT(Read);
1391         if(pr == 200) {
1392             SET_EXPECT(Read);
1393             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1394         }
1395         if(pr >= 200)
1396             SET_EXPECT(ReportData);
1397     }else {
1398         SET_EXPECT(ReportData);
1399     }
1400
1401     hres = IInternetProtocolSink_ReportData(binding_sink, bscf, 100, 400);
1402     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1403
1404     if(mimefilter_test) {
1405         SET_EXPECT(MimeFilter_ReportData);
1406     }else if(pi & PI_MIMEVERIFICATION) {
1407         if(pr < 200)
1408             CHECK_CALLED(Read);
1409         if(pr == 200) {
1410             CLEAR_CALLED(Read);
1411             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1412         }
1413     }else {
1414         CHECK_CALLED(ReportData);
1415     }
1416
1417     if(prot_state == 3)
1418         prot_state = 4;
1419
1420     return S_OK;
1421 }
1422
1423 static HRESULT WINAPI ProtocolEmul_Terminate(IInternetProtocol *iface, DWORD dwOptions)
1424 {
1425     CHECK_EXPECT(Terminate);
1426     ok(!dwOptions, "dwOptions=%d\n", dwOptions);
1427     return S_OK;
1428 }
1429
1430 static HRESULT WINAPI ProtocolEmul_Read(IInternetProtocol *iface, void *pv,
1431         ULONG cb, ULONG *pcbRead)
1432 {
1433     if(mimefilter_test) {
1434         CHECK_EXPECT2(Read);
1435     }else if((pi & PI_MIMEVERIFICATION)) {
1436         CHECK_EXPECT2(Read);
1437
1438         if(prot_read < 300) {
1439             ok(pv != expect_pv, "pv == expect_pv\n");
1440             if(prot_read < 300)
1441                 ok(cb == 2048-prot_read, "cb=%d\n", cb);
1442             else
1443                 ok(cb == 700, "cb=%d\n", cb);
1444         }else {
1445             ok(expect_pv <= pv && (BYTE*)pv < (BYTE*)expect_pv + cb, "pv != expect_pv\n");
1446         }
1447     }else {
1448         CHECK_EXPECT(Read);
1449
1450         ok(pv == expect_pv, "pv != expect_pv\n");
1451         ok(cb == 1000, "cb=%d\n", cb);
1452         ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
1453     }
1454     ok(pcbRead != NULL, "pcbRead == NULL\n");
1455
1456     if(prot_state == 3) {
1457         HRESULT hres;
1458
1459         if(mimefilter_test)
1460             SET_EXPECT(MimeFilter_ReportResult);
1461         else
1462             SET_EXPECT(ReportResult);
1463         hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1464         ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1465         if(mimefilter_test)
1466             CHECK_CALLED(MimeFilter_ReportResult);
1467         else
1468             CHECK_CALLED(ReportResult);
1469
1470         return S_FALSE;
1471     }
1472
1473     if((async_read_pending = !async_read_pending)) {
1474         *pcbRead = 0;
1475         return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
1476     }
1477
1478     memset(pv, 'x', 100);
1479     prot_read += *pcbRead = 100;
1480     return S_OK;
1481 }
1482
1483 static HRESULT WINAPI ProtocolEmul_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
1484 {
1485     CHECK_EXPECT(LockRequest);
1486     ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
1487     return S_OK;
1488 }
1489
1490 static HRESULT WINAPI ProtocolEmul_UnlockRequest(IInternetProtocol *iface)
1491 {
1492     CHECK_EXPECT(UnlockRequest);
1493     return S_OK;
1494 }
1495
1496 static const IInternetProtocolVtbl ProtocolVtbl = {
1497     ProtocolEmul_QueryInterface,
1498     Protocol_AddRef,
1499     Protocol_Release,
1500     ProtocolEmul_Start,
1501     ProtocolEmul_Continue,
1502     Protocol_Abort,
1503     ProtocolEmul_Terminate,
1504     Protocol_Suspend,
1505     Protocol_Resume,
1506     ProtocolEmul_Read,
1507     Protocol_Seek,
1508     ProtocolEmul_LockRequest,
1509     ProtocolEmul_UnlockRequest
1510 };
1511
1512 static IInternetProtocol Protocol = { &ProtocolVtbl };
1513
1514 static HRESULT WINAPI MimeProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
1515 {
1516     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
1517         *ppv = iface;
1518         return S_OK;
1519     }
1520
1521     if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
1522         *ppv = &mime_protocol_sink;
1523         return S_OK;
1524     }
1525
1526     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
1527     *ppv = NULL;
1528     return E_NOINTERFACE;
1529 }
1530
1531 static HRESULT WINAPI MimeProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
1532         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1533         DWORD grfPI, HANDLE_PTR dwReserved)
1534 {
1535     PROTOCOLFILTERDATA *data;
1536     LPOLESTR url_str = NULL;
1537     DWORD fetched = 0;
1538     BINDINFO bindinfo;
1539     DWORD cbindf = 0;
1540     HRESULT hres;
1541
1542     CHECK_EXPECT(MimeFilter_Start);
1543
1544     ok(!lstrcmpW(szUrl, gzipW), "wrong url %s\n", debugstr_w(szUrl));
1545     ok(grfPI == (PI_FILTER_MODE|PI_FORCE_ASYNC), "grfPI=%x, expected PI_FILTER_MODE|PI_FORCE_ASYNC\n", grfPI);
1546     ok(dwReserved, "dwReserved == 0\n");
1547     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
1548     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
1549
1550     if(binding_test) {
1551         ok(pOIProtSink != binding_sink, "pOIProtSink == protocol_sink\n");
1552         ok(pOIBindInfo == prot_bind_info, "pOIBindInfo != bind_info\n");
1553     }else {
1554         ok(pOIProtSink == &protocol_sink, "pOIProtSink != protocol_sink\n");
1555         ok(pOIBindInfo == &bind_info, "pOIBindInfo != bind_info\n");
1556     }
1557
1558     data = (void*)dwReserved;
1559     ok(data->cbSize == sizeof(*data), "data->cbSize = %d\n", data->cbSize);
1560     ok(!data->pProtocolSink, "data->pProtocolSink != NULL\n");
1561     ok(data->pProtocol != NULL, "data->pProtocol == NULL\n");
1562     ok(!data->pUnk, "data->pUnk != NULL\n");
1563     ok(!data->dwFilterFlags, "data->dwProtocolFlags = %x\n", data->dwFilterFlags);
1564     if(binding_test) {
1565         IInternetProtocolSink *prot_sink;
1566
1567         IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocolSink, (void**)&prot_sink);
1568         ok(prot_sink == pOIProtSink, "QI(data->pProtocol, IID_IInternetProtocolSink) != pOIProtSink\n");
1569         IInternetProtocolSink_Release(prot_sink);
1570
1571         ok(data->pProtocol != binding_protocol, "data->pProtocol == binding_protocol\n");
1572
1573         filtered_protocol = data->pProtocol;
1574         IInternetProtocol_AddRef(filtered_protocol);
1575     }else {
1576         IInternetProtocol *prot;
1577
1578         IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocol, (void**)&prot);
1579         ok(prot == async_protocol, "QI(data->pProtocol, IID_IInternetProtocol) != async_protocol\n");
1580         IInternetProtocol_Release(prot);
1581
1582         ok(data->pProtocol != async_protocol, "data->pProtocol == async_protocol\n");
1583     }
1584
1585     filtered_sink = pOIProtSink;
1586
1587     SET_EXPECT(ReportProgress_DECODING);
1588     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DECODING, gzipW);
1589     ok(hres == S_OK, "ReportProgress(BINDSTATUS_DECODING) failed: %08x\n", hres);
1590     CHECK_CALLED(ReportProgress_DECODING);
1591
1592     SET_EXPECT(GetBindInfo);
1593     memset(&bindinfo, 0, sizeof(bindinfo));
1594     bindinfo.cbSize = sizeof(bindinfo);
1595     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
1596     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
1597     ok(cbindf == bindf, "cbindf = %x\n", cbindf);
1598     CHECK_CALLED(GetBindInfo);
1599
1600     SET_EXPECT(GetBindString_URL);
1601     hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_URL, &url_str, 1, &fetched);
1602     ok(hres == S_OK, "GetBindString(BINDSTRING_URL) failed: %08x\n", hres);
1603     ok(fetched == 1, "fetched = %d\n", fetched);
1604     ok(!lstrcmpW(url_str, binding_urls[tested_protocol]), "wrong url_str %s\n", debugstr_w(url_str));
1605     CoTaskMemFree(url_str);
1606     CHECK_CALLED(GetBindString_URL);
1607
1608     return S_OK;
1609 }
1610
1611 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
1612         PROTOCOLDATA *pProtocolData)
1613 {
1614     CHECK_EXPECT(MimeFilter_Continue);
1615     return E_NOTIMPL;
1616 }
1617
1618 static HRESULT WINAPI MimeProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
1619 {
1620     HRESULT hres;
1621
1622     CHECK_EXPECT(MimeFilter_Terminate);
1623
1624     ok(!dwOptions, "dwOptions = %x\n", dwOptions);
1625
1626     SET_EXPECT(Terminate);
1627     hres = IInternetProtocol_Terminate(filtered_protocol, dwOptions);
1628     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1629     CHECK_CALLED(Terminate);
1630
1631     return S_OK;
1632 }
1633
1634 static HRESULT WINAPI MimeProtocol_Read(IInternetProtocol *iface, void *pv,
1635         ULONG cb, ULONG *pcbRead)
1636 {
1637     BYTE buf[2096];
1638     DWORD read = 0;
1639     HRESULT hres;
1640
1641     CHECK_EXPECT(MimeFilter_Read);
1642
1643     ok(pv != NULL, "pv == NULL\n");
1644     ok(cb != 0, "cb == 0\n");
1645     ok(pcbRead != NULL, "pcbRead == NULL\n");
1646
1647     SET_EXPECT(Read);
1648     hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
1649     ok(hres == S_OK || hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
1650     CHECK_CALLED(Read);
1651
1652     if(pcbRead) {
1653         ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
1654         *pcbRead = read;
1655     }
1656
1657     memset(pv, 'x', read);
1658     return hres;
1659 }
1660
1661 static HRESULT WINAPI MimeProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
1662 {
1663     HRESULT hres;
1664
1665     CHECK_EXPECT(MimeFilter_LockRequest);
1666
1667     ok(!dwOptions, "dwOptions = %x\n", dwOptions);
1668
1669     SET_EXPECT(LockRequest);
1670     hres = IInternetProtocol_LockRequest(filtered_protocol, dwOptions);
1671     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1672     CHECK_CALLED(LockRequest);
1673
1674     return S_OK;
1675 }
1676
1677 static HRESULT WINAPI MimeProtocol_UnlockRequest(IInternetProtocol *iface)
1678 {
1679     HRESULT hres;
1680
1681     CHECK_EXPECT(MimeFilter_UnlockRequest);
1682
1683     SET_EXPECT(UnlockRequest);
1684     hres = IInternetProtocol_UnlockRequest(filtered_protocol);
1685     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1686     CHECK_CALLED(UnlockRequest);
1687
1688     return S_OK;
1689 }
1690
1691 static const IInternetProtocolVtbl MimeProtocolVtbl = {
1692     MimeProtocol_QueryInterface,
1693     Protocol_AddRef,
1694     Protocol_Release,
1695     MimeProtocol_Start,
1696     Protocol_Continue,
1697     Protocol_Abort,
1698     MimeProtocol_Terminate,
1699     Protocol_Suspend,
1700     Protocol_Resume,
1701     MimeProtocol_Read,
1702     Protocol_Seek,
1703     MimeProtocol_LockRequest,
1704     MimeProtocol_UnlockRequest
1705 };
1706
1707 static IInternetProtocol MimeProtocol = { &MimeProtocolVtbl };
1708
1709 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
1710 {
1711     ok(0, "unexpected call\n");
1712     return E_NOINTERFACE;
1713 }
1714
1715 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
1716 {
1717     return 2;
1718 }
1719
1720 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
1721 {
1722     return 1;
1723 }
1724
1725 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1726                                         REFIID riid, void **ppv)
1727 {
1728     CHECK_EXPECT(CreateInstance);
1729
1730     ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
1731     ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
1732     ok(ppv != NULL, "ppv == NULL\n");
1733
1734     *ppv = &Protocol;
1735     return S_OK;
1736 }
1737
1738 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
1739 {
1740     ok(0, "unexpected call\n");
1741     return S_OK;
1742 }
1743
1744 static const IClassFactoryVtbl ClassFactoryVtbl = {
1745     ClassFactory_QueryInterface,
1746     ClassFactory_AddRef,
1747     ClassFactory_Release,
1748     ClassFactory_CreateInstance,
1749     ClassFactory_LockServer
1750 };
1751
1752 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
1753
1754 static HRESULT WINAPI MimeFilter_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
1755 {
1756     CHECK_EXPECT(MimeFilter_CreateInstance);
1757
1758     ok(!outer, "outer = %p\n", outer);
1759     ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", debugstr_guid(riid));
1760
1761     *ppv = &MimeProtocol;
1762     return S_OK;
1763 }
1764
1765 static const IClassFactoryVtbl MimeFilterCFVtbl = {
1766     ClassFactory_QueryInterface,
1767     ClassFactory_AddRef,
1768     ClassFactory_Release,
1769     MimeFilter_CreateInstance,
1770     ClassFactory_LockServer
1771 };
1772
1773 static IClassFactory mimefilter_cf = { &MimeFilterCFVtbl };
1774
1775 #define TEST_BINDING   1
1776 #define TEST_FILTER    2
1777
1778 static void init_test(int prot, DWORD flags)
1779 {
1780     tested_protocol = prot;
1781     binding_test = (flags & TEST_BINDING) != 0;
1782     first_data_notif = TRUE;
1783     prot_read = 0;
1784     prot_state = 0;
1785     async_read_pending = TRUE;
1786     mimefilter_test = (flags & TEST_FILTER) != 0;
1787     filter_state = 0;
1788     ResetEvent(event_complete);
1789     ResetEvent(event_complete2);
1790     async_protocol = binding_protocol = filtered_protocol = NULL;
1791     filtered_sink = NULL;
1792 }
1793
1794 static void test_priority(IInternetProtocol *protocol)
1795 {
1796     IInternetPriority *priority;
1797     LONG pr;
1798     HRESULT hres;
1799
1800     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
1801                                             (void**)&priority);
1802     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
1803     if(FAILED(hres))
1804         return;
1805
1806     hres = IInternetPriority_GetPriority(priority, &pr);
1807     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1808     ok(pr == 0, "pr=%d, expected 0\n", pr);
1809
1810     hres = IInternetPriority_SetPriority(priority, 1);
1811     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1812
1813     hres = IInternetPriority_GetPriority(priority, &pr);
1814     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1815     ok(pr == 1, "pr=%d, expected 1\n", pr);
1816
1817     IInternetPriority_Release(priority);
1818 }
1819
1820 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url, BOOL is_first)
1821 {
1822     HRESULT hres;
1823
1824     SET_EXPECT(GetBindInfo);
1825     if(!(bindf & BINDF_FROMURLMON))
1826        SET_EXPECT(ReportProgress_DIRECTBIND);
1827     if(is_first) {
1828         SET_EXPECT(ReportProgress_SENDINGREQUEST);
1829         SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1830         if(bindf & BINDF_FROMURLMON)
1831             SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
1832         else
1833             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1834     }
1835     SET_EXPECT(ReportData);
1836     if(is_first)
1837         SET_EXPECT(ReportResult);
1838
1839     expect_hrResult = S_OK;
1840
1841     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
1842     if(hres == INET_E_RESOURCE_NOT_FOUND) {
1843         win_skip("Start failed\n");
1844         return FALSE;
1845     }
1846     ok(hres == S_OK, "Start failed: %08x\n", hres);
1847
1848     CHECK_CALLED(GetBindInfo);
1849     if(!(bindf & BINDF_FROMURLMON))
1850        CHECK_CALLED(ReportProgress_DIRECTBIND);
1851     if(is_first) {
1852         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1853         CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1854         if(bindf & BINDF_FROMURLMON)
1855             CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
1856         else
1857             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1858     }
1859     CHECK_CALLED(ReportData);
1860     if(is_first)
1861         CHECK_CALLED(ReportResult);
1862
1863     return TRUE;
1864 }
1865
1866 static void test_file_protocol_url(LPCWSTR url)
1867 {
1868     IInternetProtocolInfo *protocol_info;
1869     IUnknown *unk;
1870     IClassFactory *factory;
1871     HRESULT hres;
1872
1873     hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
1874             &IID_IUnknown, (void**)&unk);
1875     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1876     if(FAILED(hres))
1877         return;
1878
1879     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1880     ok(hres == E_NOINTERFACE,
1881             "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
1882
1883     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1884     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1885     if(SUCCEEDED(hres)) {
1886         IInternetProtocol *protocol;
1887         BYTE buf[512];
1888         ULONG cb;
1889         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1890         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1891
1892         if(SUCCEEDED(hres)) {
1893             if(file_protocol_start(protocol, url, TRUE)) {
1894                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1895                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1896                 ok(cb == 2, "cb=%u expected 2\n", cb);
1897                 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
1898                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1899                 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
1900                 ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
1901                 ok(cb == 0, "cb=%u expected 0\n", cb);
1902                 hres = IInternetProtocol_UnlockRequest(protocol);
1903                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1904             }
1905
1906             if(file_protocol_start(protocol, url, FALSE)) {
1907                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1908                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1909                 hres = IInternetProtocol_LockRequest(protocol, 0);
1910                 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1911                 hres = IInternetProtocol_UnlockRequest(protocol);
1912                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1913             }
1914
1915             IInternetProtocol_Release(protocol);
1916         }
1917
1918         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1919         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1920
1921         if(SUCCEEDED(hres)) {
1922             if(file_protocol_start(protocol, url, TRUE)) {
1923                 hres = IInternetProtocol_LockRequest(protocol, 0);
1924                 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1925                 hres = IInternetProtocol_Terminate(protocol, 0);
1926                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1927                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1928                 ok(hres == S_OK, "Read failed: %08x\n\n", hres);
1929                 hres = IInternetProtocol_UnlockRequest(protocol);
1930                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1931                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1932                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1933                 hres = IInternetProtocol_Terminate(protocol, 0);
1934                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1935             }
1936
1937             IInternetProtocol_Release(protocol);
1938         }
1939
1940         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1941         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1942
1943         if(SUCCEEDED(hres)) {
1944             if(file_protocol_start(protocol, url, TRUE)) {
1945                 hres = IInternetProtocol_Terminate(protocol, 0);
1946                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1947                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1948                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1949                 ok(cb == 2, "cb=%u expected 2\n", cb);
1950             }
1951
1952             IInternetProtocol_Release(protocol);
1953         }
1954
1955         IClassFactory_Release(factory);
1956     }
1957
1958     IUnknown_Release(unk);
1959 }
1960
1961 static void test_file_protocol_fail(void)
1962 {
1963     IInternetProtocol *protocol;
1964     HRESULT hres;
1965
1966     static const WCHAR index_url2[] =
1967         {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
1968
1969     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1970             &IID_IInternetProtocol, (void**)&protocol);
1971     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1972     if(FAILED(hres))
1973         return;
1974
1975     SET_EXPECT(GetBindInfo);
1976     expect_hrResult = MK_E_SYNTAX;
1977     hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
1978     ok(hres == MK_E_SYNTAX ||
1979        hres == E_INVALIDARG,
1980        "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres);
1981     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
1982
1983     SET_EXPECT(GetBindInfo);
1984     if(!(bindf & BINDF_FROMURLMON))
1985         SET_EXPECT(ReportProgress_DIRECTBIND);
1986     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1987     SET_EXPECT(ReportResult);
1988     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1989     hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
1990     ok(hres == INET_E_RESOURCE_NOT_FOUND,
1991             "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1992     CHECK_CALLED(GetBindInfo);
1993     if(!(bindf & BINDF_FROMURLMON))
1994         CHECK_CALLED(ReportProgress_DIRECTBIND);
1995     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1996     CHECK_CALLED(ReportResult);
1997
1998     IInternetProtocol_Release(protocol);
1999
2000     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2001             &IID_IInternetProtocol, (void**)&protocol);
2002     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2003     if(FAILED(hres))
2004         return;
2005
2006     SET_EXPECT(GetBindInfo);
2007     if(!(bindf & BINDF_FROMURLMON))
2008         SET_EXPECT(ReportProgress_DIRECTBIND);
2009     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2010     SET_EXPECT(ReportResult);
2011     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2012
2013     hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
2014     ok(hres == INET_E_RESOURCE_NOT_FOUND,
2015             "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
2016     CHECK_CALLED(GetBindInfo);
2017     if(!(bindf & BINDF_FROMURLMON))
2018         CHECK_CALLED(ReportProgress_DIRECTBIND);
2019     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2020     CHECK_CALLED(ReportResult);
2021
2022     SET_EXPECT(GetBindInfo);
2023     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
2024     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2025     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2026
2027     SET_EXPECT(GetBindInfo);
2028     hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0);
2029     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2030     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2031
2032     IInternetProtocol_Release(protocol);
2033 }
2034
2035 static void test_file_protocol(void) {
2036     WCHAR buf[INTERNET_MAX_URL_LENGTH], file_name_buf[MAX_PATH];
2037     DWORD size;
2038     ULONG len;
2039     HANDLE file;
2040
2041     static const WCHAR wszFile[] = {'f','i','l','e',':',0};
2042     static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
2043     static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
2044     static const char html_doc[] = "<HTML></HTML>";
2045
2046     trace("Testing file protocol...\n");
2047     init_test(FILE_TEST, 0);
2048
2049     SetLastError(0xdeadbeef);
2050     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2051             FILE_ATTRIBUTE_NORMAL, NULL);
2052     if(!file && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2053     {
2054         win_skip("Detected Win9x or WinMe\n");
2055         return;
2056     }
2057     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
2058     if(file == INVALID_HANDLE_VALUE)
2059         return;
2060     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
2061     CloseHandle(file);
2062
2063     file_name = wszIndexHtml;
2064     bindf = 0;
2065     test_file_protocol_url(index_url);
2066     bindf = BINDF_FROMURLMON;
2067     test_file_protocol_url(index_url);
2068     bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
2069     test_file_protocol_url(index_url);
2070
2071     memcpy(buf, wszFile, sizeof(wszFile));
2072     len = sizeof(wszFile)/sizeof(WCHAR)-1;
2073     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2074     buf[len++] = '\\';
2075     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2076
2077     file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
2078     bindf = 0;
2079     test_file_protocol_url(buf);
2080     bindf = BINDF_FROMURLMON;
2081     test_file_protocol_url(buf);
2082
2083     memcpy(buf, wszFile2, sizeof(wszFile2));
2084     len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
2085     file_name_buf[len++] = '\\';
2086     memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2087     lstrcpyW(buf+sizeof(wszFile2)/sizeof(WCHAR)-1, file_name_buf);
2088     file_name = file_name_buf;
2089     bindf = 0;
2090     test_file_protocol_url(buf);
2091     bindf = BINDF_FROMURLMON;
2092     test_file_protocol_url(buf);
2093
2094     buf[sizeof(wszFile2)/sizeof(WCHAR)] = '|';
2095     test_file_protocol_url(buf);
2096
2097     memcpy(buf, wszFile3, sizeof(wszFile3));
2098     len = sizeof(wszFile3)/sizeof(WCHAR)-1;
2099     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2100     buf[len++] = '\\';
2101     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2102
2103     file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
2104     bindf = 0;
2105     test_file_protocol_url(buf);
2106     bindf = BINDF_FROMURLMON;
2107     test_file_protocol_url(buf);
2108
2109     DeleteFileW(wszIndexHtml);
2110
2111     bindf = 0;
2112     test_file_protocol_fail();
2113     bindf = BINDF_FROMURLMON;
2114     test_file_protocol_fail();
2115 }
2116
2117 static BOOL http_protocol_start(LPCWSTR url, BOOL is_first)
2118 {
2119     static BOOL got_user_agent = FALSE;
2120     HRESULT hres;
2121
2122     first_data_notif = TRUE;
2123     state = 0;
2124
2125     SET_EXPECT(GetBindInfo);
2126     if (!(bindf & BINDF_FROMURLMON))
2127         SET_EXPECT(ReportProgress_DIRECTBIND);
2128     SET_EXPECT(GetBindString_USER_AGENT);
2129     SET_EXPECT(GetBindString_ACCEPT_MIMES);
2130     SET_EXPECT(QueryService_HttpNegotiate);
2131     SET_EXPECT(BeginningTransaction);
2132     SET_EXPECT(GetRootSecurityId);
2133     if (http_post_test)
2134         SET_EXPECT(GetBindString_POST_COOKIE);
2135
2136     hres = IInternetProtocol_Start(async_protocol, url, &protocol_sink, &bind_info, 0, 0);
2137     ok(hres == S_OK, "Start failed: %08x\n", hres);
2138     if(FAILED(hres))
2139         return FALSE;
2140
2141     CHECK_CALLED(GetBindInfo);
2142     if (!(bindf & BINDF_FROMURLMON))
2143         CHECK_CALLED(ReportProgress_DIRECTBIND);
2144     if (!got_user_agent)
2145     {
2146         CHECK_CALLED(GetBindString_USER_AGENT);
2147         got_user_agent = TRUE;
2148     }
2149     else todo_wine
2150     {
2151         /* user agent only retrieved once, even with different URLs */
2152         CHECK_NOT_CALLED(GetBindString_USER_AGENT);
2153     }
2154     CHECK_CALLED(GetBindString_ACCEPT_MIMES);
2155     CHECK_CALLED(QueryService_HttpNegotiate);
2156     CHECK_CALLED(BeginningTransaction);
2157     /* GetRootSecurityId called on WinXP but not on Win98 */
2158     CLEAR_CALLED(GetRootSecurityId);
2159     if (http_post_test)
2160         CHECK_CALLED(GetBindString_POST_COOKIE);
2161
2162     return TRUE;
2163 }
2164
2165 static void test_protocol_terminate(IInternetProtocol *protocol)
2166 {
2167     BYTE buf[3600];
2168     DWORD cb;
2169     HRESULT hres;
2170
2171     hres = IInternetProtocol_LockRequest(protocol, 0);
2172     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2173
2174     hres = IInternetProtocol_Read(protocol, buf, 1, &cb);
2175     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2176
2177     hres = IInternetProtocol_Terminate(protocol, 0);
2178     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2179
2180     /* This wait is to give the internet handles being freed in Terminate
2181      * enough time to actually terminate in all cases. Internet handles
2182      * terminate asynchronously and native reuses the main InternetOpen
2183      * handle. The only case in which this seems to be necessary is on
2184      * wine with native wininet and urlmon, resulting in the next time
2185      * test_http_protocol_url being called the first data notification actually
2186      * being an extra last data notification from the previous connection
2187      * about once out of every ten times. */
2188     Sleep(100);
2189
2190     hres = IInternetProtocol_UnlockRequest(protocol);
2191     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2192 }
2193
2194 static void test_http_info(IInternetProtocol *protocol)
2195 {
2196     IWinInetHttpInfo *info;
2197     HRESULT hres;
2198
2199     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&info);
2200     ok(hres == S_OK, "Could not get IWinInterHttpInfo iface: %08x\n", hres);
2201
2202     /* TODO */
2203
2204     IWinInetHttpInfo_Release(info);
2205 }
2206
2207 /* is_first refers to whether this is the first call to this function
2208  * _for this url_ */
2209 static void test_http_protocol_url(LPCWSTR url, BOOL is_https, BOOL is_first)
2210 {
2211     IInternetProtocolInfo *protocol_info;
2212     IClassFactory *factory;
2213     IUnknown *unk;
2214     HRESULT hres;
2215
2216     http_url = url;
2217     http_is_first = is_first;
2218
2219     hres = CoGetClassObject(is_https ? &CLSID_HttpSProtocol : &CLSID_HttpProtocol,
2220             CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
2221     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2222     if(FAILED(hres))
2223         return;
2224
2225     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2226     ok(hres == E_NOINTERFACE,
2227         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
2228         hres);
2229
2230     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2231     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2232     IUnknown_Release(unk);
2233     if(FAILED(hres))
2234         return;
2235
2236     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
2237                                         (void**)&async_protocol);
2238     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2239     if(SUCCEEDED(hres)) {
2240         BYTE buf[3600];
2241         DWORD cb;
2242         ULONG ref;
2243
2244         test_priority(async_protocol);
2245         test_http_info(async_protocol);
2246
2247         SET_EXPECT(ReportProgress_FINDINGRESOURCE);
2248         SET_EXPECT(ReportProgress_CONNECTING);
2249         SET_EXPECT(ReportProgress_SENDINGREQUEST);
2250         SET_EXPECT(ReportProgress_PROXYDETECTING);
2251         if(! is_https)
2252             SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
2253         else
2254             SET_EXPECT(QueryService_HttpSecurity);
2255         if(!(bindf & BINDF_FROMURLMON)) {
2256             SET_EXPECT(OnResponse);
2257             SET_EXPECT(ReportProgress_RAWMIMETYPE);
2258             SET_EXPECT(ReportData);
2259         } else {
2260             SET_EXPECT(Switch);
2261         }
2262
2263         if(!http_protocol_start(url, is_first))
2264             return;
2265
2266         SET_EXPECT(ReportResult);
2267         expect_hrResult = S_OK;
2268
2269         hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
2270         ok((hres == E_PENDING && cb==0) ||
2271            (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
2272
2273         WaitForSingleObject(event_complete, INFINITE);
2274         if(bindf & BINDF_FROMURLMON)
2275             CHECK_CALLED(Switch);
2276         else
2277             CHECK_CALLED(ReportData);
2278         if (is_https)
2279             CLEAR_CALLED(QueryService_HttpSecurity);
2280
2281         while(1) {
2282             if(bindf & BINDF_FROMURLMON)
2283                 SET_EXPECT(Switch);
2284             else
2285                 SET_EXPECT(ReportData);
2286             hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
2287             if(hres == E_PENDING) {
2288                 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
2289                 ok((hres == E_PENDING && cb==0) ||
2290                    (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
2291                 WaitForSingleObject(event_complete, INFINITE);
2292                 if(bindf & BINDF_FROMURLMON)
2293                     CHECK_CALLED(Switch);
2294                 else
2295                     CHECK_CALLED(ReportData);
2296             }else {
2297                 if(bindf & BINDF_FROMURLMON)
2298                     CHECK_NOT_CALLED(Switch);
2299                 else
2300                     CHECK_NOT_CALLED(ReportData);
2301                 if(cb == 0) break;
2302             }
2303         }
2304         ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2305         CHECK_CALLED(ReportResult);
2306         if (is_https)
2307             CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
2308
2309         test_protocol_terminate(async_protocol);
2310         ref = IInternetProtocol_Release(async_protocol);
2311         ok(!ref, "ref=%x\n", hres);
2312     }
2313
2314     IClassFactory_Release(factory);
2315 }
2316
2317 static void test_http_protocol(void)
2318 {
2319     static const WCHAR winehq_url[] =
2320         {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
2321             'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
2322     static const WCHAR posttest_url[] =
2323         {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.',
2324          'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/',
2325          'p','o','s','t','t','e','s','t','.','p','h','p',0};
2326
2327     trace("Testing http protocol (not from urlmon)...\n");
2328     tested_protocol = HTTP_TEST;
2329     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
2330     test_http_protocol_url(winehq_url, FALSE, TRUE);
2331
2332     trace("Testing http protocol (from urlmon)...\n");
2333     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
2334     test_http_protocol_url(winehq_url, FALSE, FALSE);
2335
2336     trace("Testing http protocol (to file)...\n");
2337     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE;
2338     test_http_protocol_url(winehq_url, FALSE, FALSE);
2339
2340     trace("Testing http protocol (post data)...\n");
2341     http_post_test = TRUE;
2342     /* Without this flag we get a ReportProgress_CACHEFILENAMEAVAILABLE
2343      * notification with BINDVERB_POST */
2344     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
2345     test_http_protocol_url(posttest_url, FALSE, TRUE);
2346     http_post_test = FALSE;
2347 }
2348
2349 static void test_https_protocol(void)
2350 {
2351     static const WCHAR codeweavers_url[] =
2352         {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
2353          '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0};
2354
2355     trace("Testing https protocol (from urlmon)...\n");
2356     init_test(HTTPS_TEST, 0);
2357     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
2358     test_http_protocol_url(codeweavers_url, TRUE, TRUE);
2359 }
2360
2361
2362 static void test_ftp_protocol(void)
2363 {
2364     IInternetProtocolInfo *protocol_info;
2365     IClassFactory *factory;
2366     IUnknown *unk;
2367     BYTE buf[4096];
2368     ULONG ref;
2369     DWORD cb;
2370     HRESULT hres;
2371
2372     static const WCHAR ftp_urlW[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
2373     '/','p','u','b','/','o','t','h','e','r','/',
2374     'w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0};
2375
2376     trace("Testing ftp protocol...\n");
2377
2378     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
2379     state = 0;
2380     tested_protocol = FTP_TEST;
2381     first_data_notif = TRUE;
2382     expect_hrResult = E_PENDING;
2383
2384     hres = CoGetClassObject(&CLSID_FtpProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
2385     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2386     if(FAILED(hres))
2387         return;
2388
2389     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2390     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
2391
2392     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2393     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2394     IUnknown_Release(unk);
2395     if(FAILED(hres))
2396         return;
2397
2398     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
2399                                         (void**)&async_protocol);
2400     IClassFactory_Release(factory);
2401     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2402
2403     test_priority(async_protocol);
2404     test_http_info(async_protocol);
2405
2406     SET_EXPECT(GetBindInfo);
2407     SET_EXPECT(GetBindString_USER_AGENT);
2408     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
2409     SET_EXPECT(ReportProgress_CONNECTING);
2410     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2411     SET_EXPECT(Switch);
2412
2413     hres = IInternetProtocol_Start(async_protocol, ftp_urlW, &protocol_sink, &bind_info, 0, 0);
2414     ok(hres == S_OK, "Start failed: %08x\n", hres);
2415     CHECK_CALLED(GetBindInfo);
2416     todo_wine CHECK_NOT_CALLED(GetBindString_USER_AGENT);
2417
2418     SET_EXPECT(ReportResult);
2419
2420     hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
2421     ok((hres == E_PENDING && cb==0) ||
2422        (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
2423
2424     WaitForSingleObject(event_complete, INFINITE);
2425
2426     while(1) {
2427
2428         hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
2429         if(hres == E_PENDING)
2430             WaitForSingleObject(event_complete, INFINITE);
2431         else
2432             if(cb == 0) break;
2433     }
2434
2435     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2436     CHECK_CALLED(ReportResult);
2437     CHECK_CALLED(Switch);
2438
2439     test_protocol_terminate(async_protocol);
2440
2441     ref = IInternetProtocol_Release(async_protocol);
2442     ok(!ref, "ref=%d\n", ref);
2443 }
2444
2445 static void test_gopher_protocol(void)
2446 {
2447     IInternetProtocolInfo *protocol_info;
2448     IClassFactory *factory;
2449     IUnknown *unk;
2450     HRESULT hres;
2451
2452     trace("Testing gopher protocol...\n");
2453
2454     hres = CoGetClassObject(&CLSID_GopherProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
2455     ok(hres == S_OK ||
2456        hres == REGDB_E_CLASSNOTREG, /* Gopher protocol has been removed as of Vista */
2457        "CoGetClassObject failed: %08x\n", hres);
2458     if(FAILED(hres))
2459         return;
2460
2461     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2462     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
2463
2464     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2465     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2466     IUnknown_Release(unk);
2467     if(FAILED(hres))
2468         return;
2469
2470     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
2471                                         (void**)&async_protocol);
2472     IClassFactory_Release(factory);
2473     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2474
2475     test_priority(async_protocol);
2476
2477     IInternetProtocol_Release(async_protocol);
2478 }
2479
2480 static void test_mk_protocol(void)
2481 {
2482     IInternetProtocolInfo *protocol_info;
2483     IInternetProtocol *protocol;
2484     IClassFactory *factory;
2485     IUnknown *unk;
2486     HRESULT hres;
2487
2488     static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
2489                                        ':',':','/','t','e','s','t','.','h','t','m','l',0};
2490     static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
2491
2492     trace("Testing mk protocol...\n");
2493     init_test(MK_TEST, 0);
2494
2495     hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
2496             &IID_IUnknown, (void**)&unk);
2497     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2498
2499     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2500     ok(hres == E_NOINTERFACE,
2501         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
2502         hres);
2503
2504     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2505     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2506     IUnknown_Release(unk);
2507     if(FAILED(hres))
2508         return;
2509
2510     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
2511                                         (void**)&protocol);
2512     IClassFactory_Release(factory);
2513     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2514
2515     SET_EXPECT(GetBindInfo);
2516     hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
2517     ok(hres == MK_E_SYNTAX || hres == INET_E_INVALID_URL,
2518        "Start failed: %08x, expected MK_E_SYNTAX or INET_E_INVALID_URL\n", hres);
2519     CLEAR_CALLED(GetBindInfo);
2520
2521     SET_EXPECT(GetBindInfo);
2522     SET_EXPECT(ReportProgress_DIRECTBIND);
2523     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2524     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2525     SET_EXPECT(ReportResult);
2526     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2527
2528     hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
2529     ok(hres == INET_E_RESOURCE_NOT_FOUND ||
2530        hres == INET_E_INVALID_URL, /* win2k3 */
2531        "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND or INET_E_INVALID_URL\n", hres);
2532
2533     if (hres == INET_E_RESOURCE_NOT_FOUND) {
2534         CHECK_CALLED(GetBindInfo);
2535         CLEAR_CALLED(ReportProgress_DIRECTBIND);
2536         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2537         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2538         CHECK_CALLED(ReportResult);
2539     }else {
2540         CLEAR_CALLED(GetBindInfo);
2541         CLEAR_CALLED(ReportProgress_DIRECTBIND);
2542         CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
2543         CLEAR_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2544         CLEAR_CALLED(ReportResult);
2545     }
2546
2547     IInternetProtocol_Release(protocol);
2548 }
2549
2550 static void test_CreateBinding(void)
2551 {
2552     IInternetProtocol *protocol;
2553     IInternetPriority *priority;
2554     IInternetSession *session;
2555     LONG p;
2556     BYTE buf[1000];
2557     DWORD read;
2558     HRESULT hres;
2559
2560     static const WCHAR test_url[] =
2561         {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
2562     static const WCHAR wsz_test[] = {'t','e','s','t',0};
2563
2564     trace("Testing CreateBinding...\n");
2565     init_test(BIND_TEST, TEST_BINDING);
2566
2567     hres = CoInternetGetSession(0, &session, 0);
2568     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2569
2570     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
2571     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
2572
2573     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
2574     binding_protocol = protocol;
2575     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
2576     ok(protocol != NULL, "protocol == NULL\n");
2577
2578     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
2579     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
2580
2581     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
2582     ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres);
2583
2584     hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
2585     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2586     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
2587     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2588     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
2589     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2590
2591     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
2592     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
2593
2594     p = 0xdeadbeef;
2595     hres = IInternetPriority_GetPriority(priority, &p);
2596     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2597     ok(!p, "p=%d\n", p);
2598
2599     ex_priority = 100;
2600     hres = IInternetPriority_SetPriority(priority, 100);
2601     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2602
2603     p = 0xdeadbeef;
2604     hres = IInternetPriority_GetPriority(priority, &p);
2605     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2606     ok(p == 100, "p=%d\n", p);
2607
2608     SET_EXPECT(QueryService_InternetProtocol);
2609     SET_EXPECT(CreateInstance);
2610     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
2611     SET_EXPECT(SetPriority);
2612     SET_EXPECT(Start);
2613
2614     expect_hrResult = S_OK;
2615     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
2616     ok(hres == S_OK, "Start failed: %08x\n", hres);
2617
2618     CHECK_CALLED(QueryService_InternetProtocol);
2619     CHECK_CALLED(CreateInstance);
2620     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
2621     CHECK_CALLED(SetPriority);
2622     CHECK_CALLED(Start);
2623
2624     SET_EXPECT(Read);
2625     read = 0xdeadbeef;
2626     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
2627     ok(hres == S_OK, "Read failed: %08x\n", hres);
2628     ok(read == 100, "read = %d\n", read);
2629     CHECK_CALLED(Read);
2630
2631     SET_EXPECT(Read);
2632     read = 0xdeadbeef;
2633     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
2634     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2635     ok(!read, "read = %d\n", read);
2636     CHECK_CALLED(Read);
2637
2638     p = 0xdeadbeef;
2639     hres = IInternetPriority_GetPriority(priority, &p);
2640     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2641     ok(p == 100, "p=%d\n", p);
2642
2643     hres = IInternetPriority_SetPriority(priority, 101);
2644     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2645
2646     SET_EXPECT(Terminate);
2647     hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
2648     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2649     CHECK_CALLED(Terminate);
2650
2651     SET_EXPECT(Continue);
2652     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
2653     ok(hres == S_OK, "Switch failed: %08x\n", hres);
2654     CHECK_CALLED(Continue);
2655
2656     hres = IInternetProtocolSink_ReportProgress(binding_sink,
2657             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
2658     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
2659
2660     hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
2661     ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres);
2662
2663     hres = IInternetProtocolSink_ReportData(binding_sink, 0, 0, 0);
2664     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2665
2666     IInternetProtocolSink_Release(binding_sink);
2667     IInternetPriority_Release(priority);
2668     IInternetBindInfo_Release(prot_bind_info);
2669     IInternetProtocol_Release(protocol);
2670     IInternetSession_Release(session);
2671 }
2672
2673 static void test_binding(int prot, DWORD grf_pi, BOOL test_filter)
2674 {
2675     IInternetProtocol *protocol;
2676     IInternetSession *session;
2677     ULONG ref;
2678     HRESULT hres;
2679
2680     trace("Testing %s binding (grfPI %x%s)...\n", debugstr_w(protocol_names[prot]), grf_pi,
2681           test_filter ? " testing MIME filter" : "");
2682     init_test(prot, TEST_BINDING | (test_filter ? TEST_FILTER : 0));
2683     pi = grf_pi;
2684
2685     hres = CoInternetGetSession(0, &session, 0);
2686     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2687
2688     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, protocol_names[prot], 0, NULL, 0);
2689     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
2690
2691     hres = IInternetSession_CreateBinding(session, NULL, binding_urls[prot], NULL, NULL, &protocol, 0);
2692     binding_protocol = protocol;
2693     IInternetSession_Release(session);
2694     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
2695     ok(protocol != NULL, "protocol == NULL\n");
2696
2697     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
2698     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
2699
2700     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
2701     ok(hres == S_OK, "QueryInterface(IID_IInternetProtocolSink) failed: %08x\n", hres);
2702
2703     ex_priority = 0;
2704     SET_EXPECT(QueryService_InternetProtocol);
2705     SET_EXPECT(CreateInstance);
2706     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
2707     SET_EXPECT(SetPriority);
2708     SET_EXPECT(Start);
2709
2710     expect_hrResult = S_OK;
2711     hres = IInternetProtocol_Start(protocol, binding_urls[prot], &protocol_sink, &bind_info, pi, 0);
2712     ok(hres == S_OK, "Start failed: %08x\n", hres);
2713
2714     CHECK_CALLED(QueryService_InternetProtocol);
2715     CHECK_CALLED(CreateInstance);
2716     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
2717     CHECK_CALLED(SetPriority);
2718     CHECK_CALLED(Start);
2719
2720     if(prot == HTTP_TEST || prot == HTTPS_TEST) {
2721         while(prot_state < 4) {
2722             WaitForSingleObject(event_complete, INFINITE);
2723             if(mimefilter_test && filtered_protocol) {
2724                 SET_EXPECT(Continue);
2725                 IInternetProtocol_Continue(filtered_protocol, pdata);
2726                 CHECK_CALLED(Continue);
2727             }else {
2728                 SET_EXPECT(Continue);
2729                 IInternetProtocol_Continue(protocol, pdata);
2730                 CHECK_CALLED(Continue);
2731             }
2732             SetEvent(event_complete2);
2733         }
2734         WaitForSingleObject(event_complete, INFINITE);
2735     }else {
2736         if(mimefilter_test)
2737             SET_EXPECT(MimeFilter_LockRequest);
2738         else
2739             SET_EXPECT(LockRequest);
2740         hres = IInternetProtocol_LockRequest(protocol, 0);
2741         ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2742         if(mimefilter_test)
2743             CHECK_CALLED(MimeFilter_LockRequest);
2744         else
2745             CHECK_CALLED(LockRequest);
2746
2747         if(mimefilter_test)
2748             SET_EXPECT(MimeFilter_UnlockRequest);
2749         else
2750             SET_EXPECT(UnlockRequest);
2751         hres = IInternetProtocol_UnlockRequest(protocol);
2752         ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2753         if(mimefilter_test)
2754             CHECK_CALLED(MimeFilter_UnlockRequest);
2755         else
2756             CHECK_CALLED(UnlockRequest);
2757     }
2758
2759     if(mimefilter_test)
2760         SET_EXPECT(MimeFilter_Terminate);
2761     else
2762         SET_EXPECT(Terminate);
2763     hres = IInternetProtocol_Terminate(protocol, 0);
2764     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2765     if(mimefilter_test)
2766         CHECK_CALLED(MimeFilter_Terminate);
2767     else
2768         CHECK_CALLED(Terminate);
2769
2770     if(filtered_protocol)
2771         IInternetProtocol_Release(filtered_protocol);
2772     IInternetBindInfo_Release(prot_bind_info);
2773     IInternetProtocolSink_Release(binding_sink);
2774     ref = IInternetProtocol_Release(protocol);
2775     ok(!ref, "ref=%u, expected 0\n", ref);
2776 }
2777
2778 static void register_filter(void)
2779 {
2780     IInternetSession *session;
2781     HRESULT hres;
2782
2783     static const WCHAR gzipW[] = {'g','z','i','p',0};
2784
2785     CoInternetGetSession(0, &session, 0);
2786
2787     hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, gzipW);
2788     ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2789
2790     IInternetSession_Release(session);
2791 }
2792
2793 START_TEST(protocol)
2794 {
2795     OleInitialize(NULL);
2796
2797     event_complete = CreateEvent(NULL, FALSE, FALSE, NULL);
2798     event_complete2 = CreateEvent(NULL, FALSE, FALSE, NULL);
2799
2800     register_filter();
2801
2802     test_file_protocol();
2803     test_http_protocol();
2804     test_https_protocol();
2805     test_ftp_protocol();
2806     test_gopher_protocol();
2807     test_mk_protocol();
2808     test_CreateBinding();
2809     test_binding(FILE_TEST, 0, FALSE);
2810     test_binding(HTTP_TEST, 0, FALSE);
2811     test_binding(FILE_TEST, PI_MIMEVERIFICATION, FALSE);
2812     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, FALSE);
2813     test_binding(FILE_TEST, PI_MIMEVERIFICATION, TRUE);
2814     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TRUE);
2815
2816     CloseHandle(event_complete);
2817     CloseHandle(event_complete2);
2818
2819     OleUninitialize();
2820 }