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