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