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