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