1 /*
2  * Copyright 2005-2011 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(GetBindString_ROOTDOC_URL);
94 DEFINE_EXPECT(QueryService_HttpNegotiate);
95 DEFINE_EXPECT(QueryService_InternetProtocol);
96 DEFINE_EXPECT(QueryService_HttpSecurity);
97 DEFINE_EXPECT(QueryService_IBindCallbackRedirect);
98 DEFINE_EXPECT(QueryInterface_IWinInetInfo);
99 DEFINE_EXPECT(QueryInterface_IWinInetHttpInfo);
100 DEFINE_EXPECT(BeginningTransaction);
101 DEFINE_EXPECT(GetRootSecurityId);
102 DEFINE_EXPECT(OnResponse);
103 DEFINE_EXPECT(Switch);
104 DEFINE_EXPECT(Continue);
105 DEFINE_EXPECT(CreateInstance);
106 DEFINE_EXPECT(Start);
107 DEFINE_EXPECT(StartEx);
108 DEFINE_EXPECT(Terminate);
109 DEFINE_EXPECT(Read);
110 DEFINE_EXPECT(Read2);
111 DEFINE_EXPECT(SetPriority);
112 DEFINE_EXPECT(LockRequest);
113 DEFINE_EXPECT(UnlockRequest);
114 DEFINE_EXPECT(Abort);
115 DEFINE_EXPECT(MimeFilter_CreateInstance);
116 DEFINE_EXPECT(MimeFilter_Start);
117 DEFINE_EXPECT(MimeFilter_ReportData);
118 DEFINE_EXPECT(MimeFilter_ReportResult);
119 DEFINE_EXPECT(MimeFilter_Terminate);
120 DEFINE_EXPECT(MimeFilter_LockRequest);
121 DEFINE_EXPECT(MimeFilter_UnlockRequest);
122 DEFINE_EXPECT(MimeFilter_Read);
123 DEFINE_EXPECT(MimeFilter_Switch);
124 DEFINE_EXPECT(MimeFilter_Continue);
125 DEFINE_EXPECT(Stream_Seek);
126 DEFINE_EXPECT(Stream_Read);
127 DEFINE_EXPECT(Redirect);
128 
129 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
130 static const WCHAR index_url[] =
131     {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
132 
133 static const WCHAR acc_mimeW[] = {'*','/','*',0};
134 static const WCHAR user_agentW[] = {'W','i','n','e',0};
135 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
136 static const WCHAR hostW[] = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
137 static const WCHAR winehq_ipW[] = {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
138 static const WCHAR emptyW[] = {0};
139 static const WCHAR pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
140 static const WCHAR gifW[] = {'i','m','a','g','e','/','g','i','f',0};
141 
142 static HRESULT expect_hrResult;
143 static LPCWSTR file_name, http_url, expect_wsz;
144 static IInternetProtocol *async_protocol = NULL;
145 static BOOL first_data_notif, http_is_first, test_redirect, redirect_on_continue;
146 static int prot_state, read_report_data, post_stream_read;
147 static DWORD bindf, ex_priority , pi, bindinfo_options;
148 static IInternetProtocol *binding_protocol, *filtered_protocol;
149 static IInternetBindInfo *prot_bind_info;
150 static IInternetProtocolSink *binding_sink, *filtered_sink;
151 static void *expect_pv;
152 static HANDLE event_complete, event_complete2, event_continue, event_continue_done;
153 static BOOL binding_test;
154 static PROTOCOLDATA protocoldata, *pdata, continue_protdata;
155 static DWORD prot_read, filter_state, http_post_test, thread_id;
156 static BOOL security_problem, test_async_req, impl_protex;
157 static BOOL async_read_pending, mimefilter_test, direct_read, wait_for_switch, emulate_prot, short_read, test_abort;
158 static BOOL empty_file, no_mime, bind_from_cache, file_with_hash;
159 
160 enum {
161     STATE_CONNECTING,
162     STATE_SENDINGREQUEST,
163     STATE_STARTDOWNLOADING,
164     STATE_DOWNLOADING
165 } state;
166 
167 static enum {
168     FILE_TEST,
169     HTTP_TEST,
170     HTTPS_TEST,
171     FTP_TEST,
172     MK_TEST,
173     ITS_TEST,
174     BIND_TEST
175 } tested_protocol;
176 
177 static const WCHAR protocol_names[][10] = {
178     {'f','i','l','e',0},
179     {'h','t','t','p',0},
180     {'h','t','t','p','s',0},
181     {'f','t','p',0},
182     {'m','k',0},
183     {'i','t','s',0},
184     {'t','e','s','t',0}
185 };
186 
187 static const WCHAR binding_urls[][130] = {
188     {'f','i','l','e',':','t','e','s','t','.','h','t','m','l',0},
189     {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
190      'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0},
191     {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
192      '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0},
193     {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
194      '/','p','u','b','/','o','t','h','e','r',
195      '/','w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0},
196     {'m','k',':','t','e','s','t',0},
197     {'i','t','s',':','t','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0},
198     {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0}
199 };
200 
201 static const CHAR post_data[] = "mode=Test";
202 
203 static int strcmp_wa(LPCWSTR strw, const char *stra)
204 {
205     CHAR buf[512];
206     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
207     return lstrcmpA(stra, buf);
208 }
209 
210 static const char *w2a(LPCWSTR str)
211 {
212     static char buf[INTERNET_MAX_URL_LENGTH];
213     WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
214     return buf;
215 }
216 
217 static HRESULT WINAPI HttpSecurity_QueryInterface(IHttpSecurity *iface, REFIID riid, void **ppv)
218 {
219     if(IsEqualGUID(&IID_IUnknown, riid)
220             || IsEqualGUID(&IID_IHttpSecurity, riid)) {
221         *ppv = iface;
222         return S_OK;
223     }
224 
225     ok(0, "unexpected call\n");
226     return E_NOINTERFACE;
227 }
228 
229 static ULONG WINAPI HttpSecurity_AddRef(IHttpSecurity *iface)
230 {
231     return 2;
232 }
233 
234 static ULONG WINAPI HttpSecurity_Release(IHttpSecurity *iface)
235 {
236     return 1;
237 }
238 
239 static  HRESULT WINAPI HttpSecurity_GetWindow(IHttpSecurity* iface, REFGUID rguidReason, HWND *phwnd)
240 {
241     trace("HttpSecurity_GetWindow\n");
242 
243     return S_FALSE;
244 }
245 
246 static HRESULT WINAPI HttpSecurity_OnSecurityProblem(IHttpSecurity *iface, DWORD dwProblem)
247 {
248     trace("Security problem: %u\n", dwProblem);
249     ok(dwProblem == ERROR_INTERNET_SEC_CERT_REV_FAILED, "Expected ERROR_INTERNET_SEC_CERT_REV_FAILED got %u\n", dwProblem);
250 
251     /* Only retry once */
252     if (security_problem)
253         return E_ABORT;
254 
255     security_problem = TRUE;
256     SET_EXPECT(BeginningTransaction);
257 
258     return RPC_E_RETRY;
259 }
260 
261 static IHttpSecurityVtbl HttpSecurityVtbl = {
262     HttpSecurity_QueryInterface,
263     HttpSecurity_AddRef,
264     HttpSecurity_Release,
265     HttpSecurity_GetWindow,
266     HttpSecurity_OnSecurityProblem
267 };
268 
269 static IHttpSecurity http_security = { &HttpSecurityVtbl };
270 
271 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
272 {
273     if(IsEqualGUID(&IID_IUnknown, riid)
274             || IsEqualGUID(&IID_IHttpNegotiate, riid)
275             || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
276         *ppv = iface;
277         return S_OK;
278     }
279 
280     ok(0, "unexpected call\n");
281     return E_NOINTERFACE;
282 }
283 
284 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
285 {
286     return 2;
287 }
288 
289 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
290 {
291     return 1;
292 }
293 
294 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
295         LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
296 {
297     LPWSTR addl_headers;
298 
299     static const WCHAR wszHeaders[] =
300         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
301          'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
302          'd','e','d','\r','\n',0};
303 
304     CHECK_EXPECT(BeginningTransaction);
305 
306     if(binding_test)
307         ok(!lstrcmpW(szURL, binding_urls[tested_protocol]), "szURL != http_url\n");
308     else
309         ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
310     ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
311     ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
312     if(pszAdditionalHeaders)
313     {
314         ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
315         if (http_post_test)
316         {
317             addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
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 WINAPI BindCallbackRedirect_QueryInterface(IBindCallbackRedirect *iface, REFIID riid, void **ppv)
373 {
374     ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
375     *ppv = NULL;
376     return E_NOINTERFACE;
377 }
378 
379 static ULONG WINAPI BindCallbackRedirect_AddRef(IBindCallbackRedirect *iface)
380 {
381     return 2;
382 }
383 
384 static ULONG WINAPI BindCallbackRedirect_Release(IBindCallbackRedirect *iface)
385 {
386     return 1;
387 }
388 
389 static HRESULT WINAPI BindCallbackRedirect_Redirect(IBindCallbackRedirect *iface, const WCHAR *url, VARIANT_BOOL *cancel)
390 {
391     CHECK_EXPECT(Redirect);
392     *cancel = VARIANT_FALSE;
393     return S_OK;
394 }
395 
396 static const IBindCallbackRedirectVtbl BindCallbackRedirectVtbl = {
397     BindCallbackRedirect_QueryInterface,
398     BindCallbackRedirect_AddRef,
399     BindCallbackRedirect_Release,
400     BindCallbackRedirect_Redirect
401 };
402 
403 static IBindCallbackRedirect redirect_callback = { &BindCallbackRedirectVtbl };
404 
405 static HRESULT QueryInterface(REFIID,void**);
406 
407 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
408 {
409     return QueryInterface(riid, ppv);
410 }
411 
412 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
413 {
414     return 2;
415 }
416 
417 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
418 {
419     return 1;
420 }
421 
422 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
423         REFIID riid, void **ppv)
424 {
425     if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
426         CHECK_EXPECT2(QueryService_HttpNegotiate);
427         return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
428     }
429 
430     if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
431         ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
432         CHECK_EXPECT(QueryService_InternetProtocol);
433         return E_NOINTERFACE;
434     }
435 
436     if(IsEqualGUID(&IID_IHttpSecurity, guidService)) {
437         ok(IsEqualGUID(&IID_IHttpSecurity, riid), "unexpected riid\n");
438         CHECK_EXPECT(QueryService_HttpSecurity);
439         return IHttpSecurity_QueryInterface(&http_security, riid, ppv);
440     }
441 
442     if(IsEqualGUID(&IID_IBindCallbackRedirect, guidService)) {
443         CHECK_EXPECT(QueryService_IBindCallbackRedirect);
444         ok(IsEqualGUID(&IID_IBindCallbackRedirect, riid), "riid = %s\n", wine_dbgstr_guid(riid));
445         *ppv = &redirect_callback;
446         return S_OK;
447     }
448 
449     if(IsEqualGUID(&IID_IGetBindHandle, guidService)) {
450         trace("QueryService(IID_IGetBindHandle)\n");
451         *ppv = NULL;
452         return E_NOINTERFACE;
453     }
454 
455     if(IsEqualGUID(&IID_IWindowForBindingUI, guidService)) {
456         trace("QueryService(IID_IWindowForBindingUI)\n");
457         *ppv = NULL;
458         return E_NOINTERFACE;
459     }
460 
461     ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService));
462     return E_FAIL;
463 }
464 
465 static const IServiceProviderVtbl ServiceProviderVtbl = {
466     ServiceProvider_QueryInterface,
467     ServiceProvider_AddRef,
468     ServiceProvider_Release,
469     ServiceProvider_QueryService
470 };
471 
472 static IServiceProvider service_provider = { &ServiceProviderVtbl };
473 
474 static HRESULT WINAPI Stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
475 {
476     static const IID IID_strm_unknown = {0x2f68429a,0x199a,0x4043,{0x93,0x11,0xf2,0xfe,0x7c,0x13,0xcc,0xb9}};
477 
478     if(!IsEqualGUID(&IID_strm_unknown, riid)) /* IE11 */
479         ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
480 
481     *ppv = NULL;
482     return E_NOINTERFACE;
483 }
484 
485 static ULONG WINAPI Stream_AddRef(IStream *iface)
486 {
487     return 2;
488 }
489 
490 static ULONG WINAPI Stream_Release(IStream *iface)
491 {
492     return 1;
493 }
494 
495 static HRESULT WINAPI Stream_Read(IStream *iface, void *pv,
496         ULONG cb, ULONG *pcbRead)
497 {
498     CHECK_EXPECT2(Stream_Read);
499 
500     ok(GetCurrentThreadId() != thread_id, "wrong thread %d\n", GetCurrentThreadId());
501 
502     ok(pv != NULL, "pv == NULL\n");
503     ok(cb == 0x20000 || broken(cb == 0x2000), "cb = %d\n", cb);
504     ok(pcbRead != NULL, "pcbRead == NULL\n");
505 
506     if(post_stream_read) {
507         *pcbRead = 0;
508         return S_FALSE;
509     }
510 
511     memcpy(pv, post_data, sizeof(post_data)-1);
512     post_stream_read += *pcbRead = sizeof(post_data)-1;
513     return S_OK;
514 }
515 
516 static HRESULT WINAPI Stream_Write(IStream *iface, const void *pv,
517         ULONG cb, ULONG *pcbWritten)
518 {
519     ok(0, "unexpected call\n");
520     return E_NOTIMPL;
521 }
522 
523 static HRESULT WINAPI Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
524         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
525 {
526     CHECK_EXPECT(Stream_Seek);
527 
528     ok(!dlibMove.QuadPart, "dlibMove != 0\n");
529     ok(dwOrigin == STREAM_SEEK_SET, "dwOrigin = %d\n", dwOrigin);
530     ok(!plibNewPosition, "plibNewPosition == NULL\n");
531 
532     return S_OK;
533 }
534 
535 static HRESULT WINAPI Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
536 {
537     ok(0, "unexpected call\n");
538     return E_NOTIMPL;
539 }
540 
541 static HRESULT WINAPI Stream_CopyTo(IStream *iface, IStream *pstm,
542         ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
543 {
544     ok(0, "unexpected call\n");
545     return E_NOTIMPL;
546 }
547 
548 static HRESULT WINAPI Stream_Commit(IStream *iface, DWORD grfCommitFlags)
549 {
550     ok(0, "unexpected call\n");
551     return E_NOTIMPL;
552 }
553 
554 static HRESULT WINAPI Stream_Revert(IStream *iface)
555 {
556     ok(0, "unexpected call\n");
557     return E_NOTIMPL;
558 }
559 
560 static HRESULT WINAPI Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
561         ULARGE_INTEGER cb, DWORD dwLockType)
562 {
563     ok(0, "unexpected call\n");
564     return E_NOTIMPL;
565 }
566 
567 static HRESULT WINAPI Stream_UnlockRegion(IStream *iface,
568         ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
569 {
570     ok(0, "unexpected call\n");
571     return E_NOTIMPL;
572 }
573 
574 static HRESULT WINAPI Stream_Stat(IStream *iface, STATSTG *pstatstg,
575         DWORD dwStatFlag)
576 {
577     ok(0, "unexpected call\n");
578     return E_NOTIMPL;
579 }
580 
581 static HRESULT WINAPI Stream_Clone(IStream *iface, IStream **ppstm)
582 {
583     ok(0, "unexpected call\n");
584     return E_NOTIMPL;
585 }
586 
587 static const IStreamVtbl StreamVtbl = {
588     Stream_QueryInterface,
589     Stream_AddRef,
590     Stream_Release,
591     Stream_Read,
592     Stream_Write,
593     Stream_Seek,
594     Stream_SetSize,
595     Stream_CopyTo,
596     Stream_Commit,
597     Stream_Revert,
598     Stream_LockRegion,
599     Stream_UnlockRegion,
600     Stream_Stat,
601     Stream_Clone
602 };
603 
604 static IStream Stream = { &StreamVtbl };
605 
606 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
607 {
608     return QueryInterface(riid, ppv);
609 }
610 
611 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
612 {
613     return 2;
614 }
615 
616 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
617 {
618     return 1;
619 }
620 
621 static void call_continue(PROTOCOLDATA *protocol_data)
622 {
623     HRESULT hres;
624 
625     if (winetest_debug > 1)
626         trace("continue in state %d\n", state);
627 
628     if(state == STATE_CONNECTING) {
629         if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST) {
630             if (http_is_first){
631                 CLEAR_CALLED(ReportProgress_FINDINGRESOURCE);
632                 CLEAR_CALLED(ReportProgress_PROXYDETECTING);
633             }
634             CLEAR_CALLED(ReportProgress_CONNECTING);
635         }
636         if(tested_protocol == FTP_TEST)
637             todo_wine CHECK_CALLED(ReportProgress_SENDINGREQUEST);
638         else if (tested_protocol != HTTPS_TEST)
639             CHECK_CALLED(ReportProgress_SENDINGREQUEST);
640         if(test_redirect && !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
641             CHECK_CALLED(ReportProgress_REDIRECTING);
642         state = test_async_req ? STATE_SENDINGREQUEST : STATE_STARTDOWNLOADING;
643     }
644 
645     switch(state) {
646     case STATE_SENDINGREQUEST:
647         SET_EXPECT(Stream_Read);
648         SET_EXPECT(ReportProgress_SENDINGREQUEST);
649         break;
650     case STATE_STARTDOWNLOADING:
651         if((tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST)
652            && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))) {
653             SET_EXPECT(OnResponse);
654             if(tested_protocol == HTTPS_TEST || test_redirect || test_abort || empty_file)
655                 SET_EXPECT(ReportProgress_ACCEPTRANGES);
656             SET_EXPECT(ReportProgress_ENCODING);
657             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
658             if(bindf & BINDF_NEEDFILE)
659                 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
660         }
661     default:
662         break;
663     }
664 
665     if(state != STATE_SENDINGREQUEST && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)))
666         SET_EXPECT(ReportData);
667     hres = IInternetProtocol_Continue(async_protocol, protocol_data);
668     ok(hres == S_OK, "Continue failed: %08x\n", hres);
669     if(tested_protocol == FTP_TEST || security_problem)
670         CLEAR_CALLED(ReportData);
671     else if(state != STATE_SENDINGREQUEST && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)))
672         CHECK_CALLED(ReportData);
673 
674     switch(state) {
675     case STATE_SENDINGREQUEST:
676         CHECK_CALLED(Stream_Read);
677         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
678         state = STATE_STARTDOWNLOADING;
679         break;
680     case STATE_STARTDOWNLOADING:
681         if(!security_problem) {
682             state = STATE_DOWNLOADING;
683             if((tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST)
684                && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))) {
685                 CHECK_CALLED(OnResponse);
686                 if(tested_protocol == HTTPS_TEST || empty_file)
687                     CHECK_CALLED(ReportProgress_ACCEPTRANGES);
688                 else if(test_redirect || test_abort)
689                     CLEAR_CALLED(ReportProgress_ACCEPTRANGES);
690                 CLEAR_CALLED(ReportProgress_ENCODING);
691                 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
692                 if(bindf & BINDF_NEEDFILE)
693                     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
694             }
695         }
696         else
697         {
698             security_problem = FALSE;
699             SET_EXPECT(ReportProgress_CONNECTING);
700         }
701     default:
702         break;
703     }
704 }
705 
706 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
707 {
708     if(tested_protocol == FTP_TEST)
709         CHECK_EXPECT2(Switch);
710     else
711         CHECK_EXPECT(Switch);
712 
713     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
714     if(binding_test) {
715         ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
716         ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
717            pProtocolData->grfFlags, protocoldata.grfFlags );
718         ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
719            pProtocolData->dwState, protocoldata.dwState );
720         ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
721            pProtocolData->pData, protocoldata.pData );
722         ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
723            pProtocolData->cbData, protocoldata.cbData );
724     }
725 
726     pdata = pProtocolData;
727 
728     if(binding_test) {
729         SetEvent(event_complete);
730         ok( WaitForSingleObject(event_complete2, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
731         return S_OK;
732     }if(direct_read) {
733         continue_protdata = *pProtocolData;
734         SetEvent(event_continue);
735         ok( WaitForSingleObject(event_continue_done, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
736     }else {
737         call_continue(pProtocolData);
738         SetEvent(event_complete);
739     }
740 
741     return S_OK;
742 }
743 
744 static const char *status_names[] =
745 {
746     "0",
747     "FINDINGRESOURCE",
748     "CONNECTING",
749     "REDIRECTING",
750     "BEGINDOWNLOADDATA",
751     "DOWNLOADINGDATA",
752     "ENDDOWNLOADDATA",
753     "BEGINDOWNLOADCOMPONENTS",
754     "INSTALLINGCOMPONENTS",
755     "ENDDOWNLOADCOMPONENTS",
756     "USINGCACHEDCOPY",
757     "SENDINGREQUEST",
758     "CLASSIDAVAILABLE",
759     "MIMETYPEAVAILABLE",
760     "CACHEFILENAMEAVAILABLE",
761     "BEGINSYNCOPERATION",
762     "ENDSYNCOPERATION",
763     "BEGINUPLOADDATA",
764     "UPLOADINGDATA",
765     "ENDUPLOADINGDATA",
766     "PROTOCOLCLASSID",
767     "ENCODING",
768     "VERIFIEDMIMETYPEAVAILABLE",
769     "CLASSINSTALLLOCATION",
770     "DECODING",
771     "LOADINGMIMEHANDLER",
772     "CONTENTDISPOSITIONATTACH",
773     "FILTERREPORTMIMETYPE",
774     "CLSIDCANINSTANTIATE",
775     "IUNKNOWNAVAILABLE",
776     "DIRECTBIND",
777     "RAWMIMETYPE",
778     "PROXYDETECTING",
779     "ACCEPTRANGES",
780     "COOKIE_SENT",
781     "COMPACT_POLICY_RECEIVED",
782     "COOKIE_SUPPRESSED",
783     "COOKIE_STATE_UNKNOWN",
784     "COOKIE_STATE_ACCEPT",
785     "COOKIE_STATE_REJECT",
786     "COOKIE_STATE_PROMPT",
787     "COOKIE_STATE_LEASH",
788     "COOKIE_STATE_DOWNGRADE",
789     "POLICY_HREF",
790     "P3P_HEADER",
791     "SESSION_COOKIE_RECEIVED",
792     "PERSISTENT_COOKIE_RECEIVED",
793     "SESSION_COOKIES_ALLOWED",
794     "CACHECONTROL",
795     "CONTENTDISPOSITIONFILENAME",
796     "MIMETEXTPLAINMISMATCH",
797     "PUBLISHERAVAILABLE",
798     "DISPLAYNAMEAVAILABLE"
799 };
800 
801 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
802         LPCWSTR szStatusText)
803 {
804     static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
805         '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
806     static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
807 
808     if (winetest_debug > 1)
809     {
810         if (ulStatusCode < sizeof(status_names)/sizeof(status_names[0]))
811             trace( "progress: %s %s\n", status_names[ulStatusCode], wine_dbgstr_w(szStatusText) );
812         else
813             trace( "progress: %u %s\n", ulStatusCode, wine_dbgstr_w(szStatusText) );
814     }
815 
816     switch(ulStatusCode) {
817     case BINDSTATUS_MIMETYPEAVAILABLE:
818         CHECK_EXPECT2(ReportProgress_MIMETYPEAVAILABLE);
819         if(tested_protocol != FILE_TEST && tested_protocol != ITS_TEST && !mimefilter_test && (pi & PI_MIMEVERIFICATION)) {
820             if(!short_read || !direct_read)
821                 CHECK_CALLED(Read); /* set in Continue */
822             else if(short_read)
823                 CHECK_CALLED(Read2); /* set in Read */
824         }
825         ok(szStatusText != NULL, "szStatusText == NULL\n");
826         if(szStatusText) {
827             if(tested_protocol == BIND_TEST)
828                 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText %s\n", wine_dbgstr_w(szStatusText));
829             else if (http_post_test)
830                 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
831                    !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
832                    "szStatusText != text/plain\n");
833             else if(empty_file)
834                 ok(!strcmp_wa(szStatusText, "application/javascript"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
835             else if((pi & PI_MIMEVERIFICATION) && emulate_prot && !mimefilter_test
836                     && tested_protocol==HTTP_TEST && !short_read)
837                 ok(lstrlenW(gifW) <= lstrlenW(szStatusText) &&
838                    !memcmp(szStatusText, gifW, lstrlenW(gifW)*sizeof(WCHAR)),
839                    "szStatusText != image/gif\n");
840             else if(!mimefilter_test)
841                 ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) &&
842                    !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
843                    "szStatusText != text/html\n");
844         }
845         break;
846     case BINDSTATUS_DIRECTBIND:
847         CHECK_EXPECT2(ReportProgress_DIRECTBIND);
848         ok(szStatusText == NULL, "szStatusText != NULL\n");
849         break;
850     case BINDSTATUS_RAWMIMETYPE:
851         CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
852         ok(szStatusText != NULL, "szStatusText == NULL\n");
853         if(szStatusText)
854             ok(lstrlenW(szStatusText) < lstrlenW(text_htmlW) ||
855                !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
856                "szStatusText != text/html\n");
857         break;
858     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
859         CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
860         ok(szStatusText != NULL, "szStatusText == NULL\n");
861         if(szStatusText) {
862             if(binding_test)
863                 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText\n");
864             else if(tested_protocol == FILE_TEST)
865                 ok(!lstrcmpW(szStatusText, file_name), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
866             else
867                 ok(szStatusText != NULL, "szStatusText == NULL\n");
868         }
869         break;
870     case BINDSTATUS_FINDINGRESOURCE:
871         CHECK_EXPECT2(ReportProgress_FINDINGRESOURCE);
872         ok(szStatusText != NULL, "szStatusText == NULL\n");
873         break;
874     case BINDSTATUS_CONNECTING:
875         CHECK_EXPECT2(ReportProgress_CONNECTING);
876         ok(szStatusText != NULL, "szStatusText == NULL\n");
877         break;
878     case BINDSTATUS_SENDINGREQUEST:
879         CHECK_EXPECT2(ReportProgress_SENDINGREQUEST);
880         if(tested_protocol == FILE_TEST || tested_protocol == ITS_TEST) {
881             ok(szStatusText != NULL, "szStatusText == NULL\n");
882             if(szStatusText)
883                 ok(!*szStatusText, "wrong szStatusText\n");
884         }
885         break;
886     case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
887         CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
888         ok(szStatusText != NULL, "szStatusText == NULL\n");
889         if(szStatusText)
890             ok(!strcmp_wa(szStatusText, "text/html"), "szStatusText != text/html\n");
891         break;
892     case BINDSTATUS_PROTOCOLCLASSID:
893         CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
894         ok(szStatusText != NULL, "szStatusText == NULL\n");
895         ok(!lstrcmpW(szStatusText, null_guid), "unexpected classid %s\n", wine_dbgstr_w(szStatusText));
896         break;
897     case BINDSTATUS_COOKIE_SENT:
898         CHECK_EXPECT2(ReportProgress_COOKIE_SENT);
899         ok(szStatusText == NULL, "szStatusText != NULL\n");
900         break;
901     case BINDSTATUS_REDIRECTING:
902         CHECK_EXPECT(ReportProgress_REDIRECTING);
903         if(test_redirect)
904             ok(!strcmp_wa(szStatusText, "http://test.winehq.org/tests/hello.html"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
905         else
906             ok(szStatusText == NULL, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
907         break;
908     case BINDSTATUS_ENCODING:
909         CHECK_EXPECT(ReportProgress_ENCODING);
910         ok(!strcmp_wa(szStatusText, "gzip"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
911         break;
912     case BINDSTATUS_ACCEPTRANGES:
913         CHECK_EXPECT(ReportProgress_ACCEPTRANGES);
914         ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
915         break;
916     case BINDSTATUS_PROXYDETECTING:
917         if(!called_ReportProgress_PROXYDETECTING)
918             SET_EXPECT(ReportProgress_CONNECTING);
919         CHECK_EXPECT2(ReportProgress_PROXYDETECTING);
920         ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
921         break;
922     case BINDSTATUS_LOADINGMIMEHANDLER:
923         CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
924         ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
925         break;
926     case BINDSTATUS_DECODING:
927         CHECK_EXPECT(ReportProgress_DECODING);
928         ok(!lstrcmpW(szStatusText, pjpegW), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
929         break;
930     case BINDSTATUS_RESERVED_7:
931         trace("BINDSTATUS_RESERVED_7\n");
932         break;
933     case BINDSTATUS_RESERVED_8:
934         trace("BINDSTATUS_RESERVED_8\n");
935         break;
936     default:
937         ok(0, "Unexpected status %d (%d)\n", ulStatusCode, ulStatusCode-BINDSTATUS_LAST);
938     };
939 
940     return S_OK;
941 }
942 
943 static void test_http_info(IInternetProtocol *protocol)
944 {
945     IWinInetHttpInfo *info;
946     char buf[1024];
947     DWORD size, len;
948     HRESULT hres;
949 
950     static const WCHAR connectionW[] = {'c','o','n','n','e','c','t','i','o','n',0};
951 
952     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&info);
953     ok(hres == S_OK, "Could not get IWinInterHttpInfo iface: %08x\n", hres);
954 
955     size = sizeof(buf);
956     strcpy(buf, "connection");
957     hres = IWinInetHttpInfo_QueryInfo(info, HTTP_QUERY_CUSTOM, buf, &size, NULL, NULL);
958     if(tested_protocol != FTP_TEST) {
959         ok(hres == S_OK, "QueryInfo failed: %08x\n", hres);
960 
961         ok(!strcmp(buf, "Keep-Alive"), "buf = %s\n", buf);
962         len = strlen(buf);
963         ok(size == len, "size = %u, expected %u\n", size, len);
964 
965         size = sizeof(buf);
966         memcpy(buf, connectionW, sizeof(connectionW));
967         hres = IWinInetHttpInfo_QueryInfo(info, HTTP_QUERY_CUSTOM, buf, &size, NULL, NULL);
968         ok(hres == S_FALSE, "QueryInfo returned %08x\n", hres);
969     }else {
970         ok(hres == S_FALSE, "QueryInfo failed: %08x\n", hres);
971     }
972 
973     IWinInetHttpInfo_Release(info);
974 }
975 
976 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
977         ULONG ulProgress, ULONG ulProgressMax)
978 {
979     HRESULT hres;
980 
981     static int rec_depth;
982     rec_depth++;
983 
984     if(!mimefilter_test && (tested_protocol == FILE_TEST || tested_protocol == ITS_TEST)) {
985         CHECK_EXPECT2(ReportData);
986 
987         ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
988            ulProgress, ulProgressMax);
989         if(!file_with_hash)
990             ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
991         /* BSCF_SKIPDRAINDATAFORFILEURLS added in IE8 */
992         if(tested_protocol == FILE_TEST)
993             ok((grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION)) ||
994                (grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_SKIPDRAINDATAFORFILEURLS)),
995                "grcfBSCF = %08x\n", grfBSCF);
996         else
997             ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
998     }else if(bind_from_cache) {
999         CHECK_EXPECT(ReportData);
1000 
1001         ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
1002         ok(ulProgress == 1000, "ulProgress = %u\n", ulProgress);
1003         ok(!ulProgressMax, "ulProgressMax = %u\n", ulProgressMax);
1004     }else if(direct_read) {
1005         BYTE buf[14096];
1006         ULONG read;
1007 
1008         if(!read_report_data && rec_depth == 1) {
1009             BOOL reported_all_data = called_ReportData2;
1010 
1011             CHECK_EXPECT2(ReportData);
1012 
1013             if(short_read) {
1014                 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE)
1015                    || grfBSCF == BSCF_FIRSTDATANOTIFICATION, /* < IE8 */
1016                    "grcfBSCF = %08x\n", grfBSCF);
1017                 CHECK_CALLED(Read); /* Set in Continue */
1018                 first_data_notif = FALSE;
1019             }else if(first_data_notif) {
1020                 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
1021                 first_data_notif = FALSE;
1022             }else if(reported_all_data) {
1023                 ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION),
1024                    "grcfBSCF = %08x\n", grfBSCF);
1025             }else if(!direct_read) {
1026                 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
1027             }
1028 
1029             do {
1030                 read = 0;
1031                 if(emulate_prot)
1032                     SET_EXPECT(Read);
1033                 else
1034                     SET_EXPECT(ReportData2);
1035                 SET_EXPECT(ReportResult);
1036                 if(!emulate_prot)
1037                     SET_EXPECT(Switch);
1038                 hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
1039                 ok(hres == E_PENDING || hres == S_FALSE || hres == S_OK, "Read failed: %08x\n", hres);
1040                 if(hres == S_OK)
1041                     ok(read, "read == 0\n");
1042                 if(reported_all_data)
1043                     ok(hres == S_FALSE, "Read failed: %08x, expected S_FALSE\n", hres);
1044                 if(!emulate_prot && hres != E_PENDING)
1045                     CHECK_NOT_CALLED(Switch); /* otherwise checked in wait_for_switch loop */
1046                 if(emulate_prot)
1047                     CHECK_CALLED(Read);
1048                 if(!reported_all_data && called_ReportData2) {
1049                     if(!emulate_prot)
1050                         CHECK_CALLED(ReportData2);
1051                     CHECK_CALLED(ReportResult);
1052                     reported_all_data = TRUE;
1053                 }else {
1054                     if(!emulate_prot)
1055                         CHECK_NOT_CALLED(ReportData2);
1056                     CHECK_NOT_CALLED(ReportResult);
1057                 }
1058             }while(hres == S_OK);
1059             if(hres == S_FALSE)
1060                 wait_for_switch = FALSE;
1061         }else {
1062             CHECK_EXPECT(ReportData2);
1063 
1064             ok(grfBSCF & BSCF_LASTDATANOTIFICATION, "grfBSCF = %08x\n", grfBSCF);
1065 
1066             read = 0xdeadbeef;
1067             if(emulate_prot)
1068                 SET_EXPECT(Read2);
1069             hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
1070             if(emulate_prot)
1071                 CHECK_CALLED(Read2);
1072             ok(hres == S_FALSE, "Read returned: %08x, expected E_FALSE\n", hres);
1073             ok(!read, "read = %d\n", read);
1074         }
1075     }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST
1076             || tested_protocol == FTP_TEST)) {
1077         if(empty_file)
1078             CHECK_EXPECT2(ReportData);
1079         else if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
1080             CHECK_EXPECT(ReportData);
1081         else if (http_post_test)
1082             ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
1083 
1084         if(empty_file) {
1085             ok(!ulProgress, "ulProgress = %d\n", ulProgress);
1086             ok(!ulProgressMax, "ulProgressMax = %d\n", ulProgressMax);
1087         }else {
1088             ok(ulProgress, "ulProgress == 0\n");
1089         }
1090 
1091         if(empty_file) {
1092             ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION),
1093                "grcfBSCF = %08x\n", grfBSCF);
1094             first_data_notif = FALSE;
1095         }else if(first_data_notif) {
1096             ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
1097                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
1098                "grcfBSCF = %08x\n", grfBSCF);
1099             first_data_notif = FALSE;
1100         } else {
1101             ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
1102                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
1103                || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
1104                "grcfBSCF = %08x\n", grfBSCF);
1105         }
1106 
1107         if((grfBSCF & BSCF_FIRSTDATANOTIFICATION) && !binding_test)
1108             test_http_info(async_protocol);
1109 
1110         if(!(bindf & BINDF_FROMURLMON) &&
1111            !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
1112             if(state == STATE_CONNECTING) {
1113                 state = STATE_DOWNLOADING;
1114                 if(http_is_first) {
1115                     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1116                     CHECK_CALLED(ReportProgress_CONNECTING);
1117                 }
1118                 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1119                 CHECK_CALLED(OnResponse);
1120                 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
1121             }
1122             SetEvent(event_complete);
1123         }
1124     }else if(!read_report_data) {
1125         BYTE buf[1000];
1126         ULONG read;
1127         HRESULT hres;
1128 
1129         CHECK_EXPECT(ReportData);
1130 
1131         if(tested_protocol != BIND_TEST) {
1132             do {
1133                 if(mimefilter_test)
1134                     SET_EXPECT(MimeFilter_Read);
1135                 else if(rec_depth > 1)
1136                     SET_EXPECT(Read2);
1137                 else
1138                     SET_EXPECT(Read);
1139                 hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
1140                 if(mimefilter_test)
1141                     CHECK_CALLED(MimeFilter_Read);
1142                 else if(rec_depth > 1)
1143                     CHECK_CALLED(Read2);
1144                 else
1145                     CHECK_CALLED(Read);
1146             }while(hres == S_OK);
1147         }
1148     }
1149 
1150     rec_depth--;
1151     return S_OK;
1152 }
1153 
1154 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1155         DWORD dwError, LPCWSTR szResult)
1156 {
1157     CHECK_EXPECT(ReportResult);
1158 
1159     if(tested_protocol == FTP_TEST)
1160         ok(hrResult == E_PENDING || hrResult == S_OK, "hrResult = %08x, expected E_PENDING or S_OK\n", hrResult);
1161     else
1162         ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
1163            hrResult, expect_hrResult);
1164 #ifdef __REACTOS__
1165     if(!winetest_interactive && tested_protocol != FTP_TEST && hrResult != expect_hrResult) {
1166         skip("CORE-10360/ROSTESTS-192: Test might hang, skipping the rest!\n");
1167         exit(1);
1168     }
1169 #endif
1170     if(SUCCEEDED(hrResult) || tested_protocol == FTP_TEST || test_abort || hrResult == INET_E_REDIRECT_FAILED)
1171         ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
1172     else
1173         ok(dwError != ERROR_SUCCESS ||
1174            broken(tested_protocol == MK_TEST), /* WinME and NT4 */
1175            "dwError == ERROR_SUCCESS\n");
1176 
1177     if(hrResult == INET_E_REDIRECT_FAILED)
1178         ok(!strcmp_wa(szResult, "http://test.winehq.org/tests/hello.html"), "szResult = %s\n", wine_dbgstr_w(szResult));
1179     else
1180         ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1181 
1182     if(direct_read)
1183         SET_EXPECT(ReportData); /* checked after main loop */
1184 
1185     return S_OK;
1186 }
1187 
1188 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
1189     ProtocolSink_QueryInterface,
1190     ProtocolSink_AddRef,
1191     ProtocolSink_Release,
1192     ProtocolSink_Switch,
1193     ProtocolSink_ReportProgress,
1194     ProtocolSink_ReportData,
1195     ProtocolSink_ReportResult
1196 };
1197 
1198 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
1199 
1200 static HRESULT WINAPI MimeProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
1201 {
1202     if(IsEqualGUID(&IID_IUnknown, riid)
1203             || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
1204         *ppv = iface;
1205         return S_OK;
1206     }
1207 
1208     ok(0, "unexpected call\n");
1209     return E_NOTIMPL;
1210 }
1211 
1212 static ULONG WINAPI MimeProtocolSink_AddRef(IInternetProtocolSink *iface)
1213 {
1214     return 2;
1215 }
1216 
1217 static ULONG WINAPI MimeProtocolSink_Release(IInternetProtocolSink *iface)
1218 {
1219     return 1;
1220 }
1221 
1222 static HRESULT WINAPI MimeProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
1223 {
1224     HRESULT hres;
1225 
1226     CHECK_EXPECT(MimeFilter_Switch);
1227 
1228     SET_EXPECT(Switch);
1229     hres = IInternetProtocolSink_Switch(filtered_sink, pProtocolData);
1230     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1231     CHECK_CALLED(Switch);
1232 
1233     return S_OK;
1234 }
1235 
1236 static HRESULT WINAPI MimeProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
1237         LPCWSTR szStatusText)
1238 {
1239     switch(ulStatusCode) {
1240     case BINDSTATUS_LOADINGMIMEHANDLER:
1241         /*
1242          * IE9 for some reason (bug?) calls this on mime handler's protocol sink instead of the
1243          * main protocol sink. We check ReportProgress_LOADINGMIMEHANDLER both here and in
1244          * ProtocolSink_ReportProgress to workaround it.
1245          */
1246         CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1247         ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
1248         break;
1249     default:
1250         ok(0, "Unexpected status code %d\n", ulStatusCode);
1251     }
1252 
1253     return S_OK;
1254 }
1255 
1256 static HRESULT WINAPI MimeProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
1257         ULONG ulProgress, ULONG ulProgressMax)
1258 {
1259     DWORD read = 0;
1260     BYTE buf[8192];
1261     HRESULT hres;
1262     BOOL report_mime = FALSE;
1263 
1264     CHECK_EXPECT(MimeFilter_ReportData);
1265 
1266     if(!filter_state && !no_mime) {
1267         SET_EXPECT(Read);
1268         hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
1269         if(tested_protocol == HTTP_TEST)
1270             ok(hres == S_OK || hres == E_PENDING || hres == S_FALSE, "Read failed: %08x\n", hres);
1271         else
1272             ok(hres == S_OK, "Read failed: %08x\n", hres);
1273         CHECK_CALLED(Read);
1274 
1275         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1276         hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, text_htmlW);
1277         ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1278         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1279 
1280         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1281         hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW);
1282         ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1283         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1284 
1285         /* FIXME: test BINDSTATUS_CACHEFILENAMEAVAILABLE */
1286     }
1287 
1288     if(no_mime && prot_read<200) {
1289         SET_EXPECT(Read);
1290     }else if(no_mime && prot_read<300) {
1291         report_mime = TRUE;
1292         SET_EXPECT(Read);
1293         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1294         SET_EXPECT(ReportData);
1295     }else if(!read_report_data) {
1296         SET_EXPECT(ReportData);
1297     }
1298     hres = IInternetProtocolSink_ReportData(filtered_sink, grfBSCF, ulProgress, ulProgressMax);
1299     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1300     if(no_mime && prot_read<=200) {
1301         CHECK_CALLED(Read);
1302     }else if(report_mime) {
1303         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1304         CHECK_CALLED(ReportData);
1305     }else if(!read_report_data) {
1306         CHECK_CALLED(ReportData);
1307     }
1308 
1309     if(!filter_state)
1310         filter_state = 1;
1311 
1312     return S_OK;
1313 }
1314 
1315 static HRESULT WINAPI MimeProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1316         DWORD dwError, LPCWSTR szResult)
1317 {
1318     HRESULT hres;
1319 
1320     CHECK_EXPECT(MimeFilter_ReportResult);
1321 
1322     ok(hrResult == S_OK, "hrResult = %08x\n", hrResult);
1323     ok(dwError == ERROR_SUCCESS, "dwError = %u\n", dwError);
1324     ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1325 
1326     SET_EXPECT(ReportResult);
1327     hres = IInternetProtocolSink_ReportResult(filtered_sink, hrResult, dwError, szResult);
1328     ok(SUCCEEDED(hres), "ReportResult failed: %08x\n", hres);
1329     CHECK_CALLED(ReportResult);
1330 
1331     return S_OK;
1332 }
1333 
1334 static IInternetProtocolSinkVtbl mime_protocol_sink_vtbl = {
1335     MimeProtocolSink_QueryInterface,
1336     MimeProtocolSink_AddRef,
1337     MimeProtocolSink_Release,
1338     MimeProtocolSink_Switch,
1339     MimeProtocolSink_ReportProgress,
1340     MimeProtocolSink_ReportData,
1341     MimeProtocolSink_ReportResult
1342 };
1343 
1344 static IInternetProtocolSink mime_protocol_sink = { &mime_protocol_sink_vtbl };
1345 
1346 static HRESULT QueryInterface(REFIID riid, void **ppv)
1347 {
1348     static const IID IID_undocumented = {0x58DFC7D0,0x5381,0x43E5,{0x9D,0x72,0x4C,0xDD,0xE4,0xCB,0x0F,0x1A}};
1349     static const IID IID_undocumentedIE10 = {0xc28722e5,0xbc1a,0x4c55,{0xa6,0x8d,0x33,0x21,0x9f,0x69,0x89,0x10}};
1350 
1351     *ppv = NULL;
1352 
1353     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
1354         *ppv = &protocol_sink;
1355     if(IsEqualGUID(&IID_IServiceProvider, riid))
1356         *ppv = &service_provider;
1357     if(IsEqualGUID(&IID_IUriContainer, riid))
1358         return E_NOINTERFACE; /* TODO */
1359 
1360     /* NOTE: IE8 queries for undocumented {58DFC7D0-5381-43E5-9D72-4CDDE4CB0F1A} interface. */
1361     if(IsEqualGUID(&IID_undocumented, riid))
1362         return E_NOINTERFACE;
1363     /* NOTE: IE10 queries for undocumented {c28722e5-bc1a-4c55-a68d-33219f698910} interface. */
1364     if(IsEqualGUID(&IID_undocumentedIE10, riid))
1365         return E_NOINTERFACE;
1366 
1367     if(*ppv)
1368         return S_OK;
1369 
1370     ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
1371     return E_NOINTERFACE;
1372 }
1373 
1374 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
1375 {
1376     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
1377         *ppv = iface;
1378         return S_OK;
1379     }
1380     return E_NOINTERFACE;
1381 }
1382 
1383 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
1384 {
1385     return 2;
1386 }
1387 
1388 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
1389 {
1390     return 1;
1391 }
1392 
1393 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
1394 {
1395     DWORD cbSize;
1396 
1397     CHECK_EXPECT(GetBindInfo);
1398 
1399     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
1400     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
1401     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
1402 
1403     *grfBINDF = bindf;
1404     if(binding_test)
1405         *grfBINDF |= BINDF_FROMURLMON;
1406     cbSize = pbindinfo->cbSize;
1407     memset(pbindinfo, 0, cbSize);
1408     pbindinfo->cbSize = cbSize;
1409     pbindinfo->dwOptions = bindinfo_options;
1410 
1411     if(http_post_test)
1412     {
1413         pbindinfo->cbstgmedData = sizeof(post_data)-1;
1414         pbindinfo->dwBindVerb = BINDVERB_POST;
1415         pbindinfo->stgmedData.tymed = http_post_test;
1416 
1417         if(http_post_test == TYMED_HGLOBAL) {
1418             HGLOBAL data;
1419 
1420             /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly */
1421             data = GlobalAlloc(GPTR, sizeof(post_data));
1422             memcpy(data, post_data, sizeof(post_data));
1423             U(pbindinfo->stgmedData).hGlobal = data;
1424         }else {
1425             U(pbindinfo->stgmedData).pstm = &Stream;
1426         }
1427     }
1428 
1429     return S_OK;
1430 }
1431 
1432 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
1433         LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1434 {
1435     ok(ppwzStr != NULL, "ppwzStr == NULL\n");
1436     ok(pcElFetched != NULL, "pcElFetched == NULL\n");
1437 
1438     switch(ulStringType) {
1439     case BINDSTRING_ACCEPT_MIMES:
1440         CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
1441         ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
1442         if(pcElFetched) {
1443             ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
1444             *pcElFetched = 1;
1445         }
1446         if(ppwzStr) {
1447             *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
1448             memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
1449         }
1450         return S_OK;
1451     case BINDSTRING_USER_AGENT:
1452         CHECK_EXPECT(GetBindString_USER_AGENT);
1453         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1454         if(pcElFetched) {
1455             ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1456             *pcElFetched = 1;
1457         }
1458         if(ppwzStr) {
1459             *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
1460             memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
1461         }
1462         return S_OK;
1463     case BINDSTRING_POST_COOKIE:
1464         CHECK_EXPECT(GetBindString_POST_COOKIE);
1465         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1466         if(pcElFetched)
1467             ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1468         return S_OK;
1469     case BINDSTRING_URL: {
1470         DWORD size;
1471 
1472         CHECK_EXPECT(GetBindString_URL);
1473         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1474         ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1475         *pcElFetched = 1;
1476 
1477         size = (lstrlenW(binding_urls[tested_protocol])+1)*sizeof(WCHAR);
1478         *ppwzStr = CoTaskMemAlloc(size);
1479         memcpy(*ppwzStr, binding_urls[tested_protocol], size);
1480         return S_OK;
1481     }
1482     case BINDSTRING_ROOTDOC_URL:
1483         CHECK_EXPECT(GetBindString_ROOTDOC_URL);
1484         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1485         return E_NOTIMPL;
1486     case BINDSTRING_ENTERPRISE_ID:
1487         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1488         return E_NOTIMPL;
1489     default:
1490         ok(0, "unexpected ulStringType %d\n", ulStringType);
1491     }
1492 
1493     return E_NOTIMPL;
1494 }
1495 
1496 static IInternetBindInfoVtbl bind_info_vtbl = {
1497     BindInfo_QueryInterface,
1498     BindInfo_AddRef,
1499     BindInfo_Release,
1500     BindInfo_GetBindInfo,
1501     BindInfo_GetBindString
1502 };
1503 
1504 static IInternetBindInfo bind_info = { &bind_info_vtbl };
1505 
1506 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1507                                                   REFIID riid, void **ppv)
1508 {
1509     ok(0, "unexpected call\n");
1510     return E_NOINTERFACE;
1511 }
1512 
1513 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1514 {
1515     return 2;
1516 }
1517 
1518 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1519 {
1520     return 1;
1521 }
1522 
1523 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1524 {
1525     CHECK_EXPECT(SetPriority);
1526     ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
1527     return S_OK;
1528 }
1529 
1530 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1531 {
1532     ok(0, "unexpected call\n");
1533     return E_NOTIMPL;
1534 }
1535 
1536 
1537 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1538     InternetPriority_QueryInterface,
1539     InternetPriority_AddRef,
1540     InternetPriority_Release,
1541     InternetPriority_SetPriority,
1542     InternetPriority_GetPriority
1543 };
1544 
1545 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
1546 
1547 static ULONG WINAPI Protocol_AddRef(IInternetProtocolEx *iface)
1548 {
1549     return 2;
1550 }
1551 
1552 static ULONG WINAPI Protocol_Release(IInternetProtocolEx *iface)
1553 {
1554     return 1;
1555 }
1556 
1557 static HRESULT WINAPI Protocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
1558         DWORD dwOptions)
1559 {
1560     HRESULT hres;
1561 
1562     CHECK_EXPECT(Abort);
1563 
1564     SET_EXPECT(ReportResult);
1565     hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1566     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1567     CHECK_CALLED(ReportResult);
1568 
1569     return S_OK;
1570 }
1571 
1572 static HRESULT WINAPI Protocol_Suspend(IInternetProtocolEx *iface)
1573 {
1574     ok(0, "unexpected call\n");
1575     return E_NOTIMPL;
1576 }
1577 
1578 static HRESULT WINAPI Protocol_Resume(IInternetProtocolEx *iface)
1579 {
1580     ok(0, "unexpected call\n");
1581     return E_NOTIMPL;
1582 }
1583 
1584 static HRESULT WINAPI Protocol_Seek(IInternetProtocolEx *iface,
1585         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1586 {
1587     ok(0, "unexpected call\n");
1588     return E_NOTIMPL;
1589 }
1590 
1591 static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
1592 {
1593     static const IID unknown_iid = {0x7daf9908,0x8415,0x4005,{0x95,0xae, 0xbd,0x27,0xf6,0xe3,0xdc,0x00}};
1594 
1595     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
1596         *ppv = iface;
1597         return S_OK;
1598     }
1599 
1600     if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
1601         if(impl_protex) {
1602             *ppv = iface;
1603             return S_OK;
1604         }
1605         *ppv = NULL;
1606         return E_NOINTERFACE;
1607     }
1608 
1609     if(IsEqualGUID(&IID_IInternetPriority, riid)) {
1610         *ppv = &InternetPriority;
1611         return S_OK;
1612     }
1613 
1614     if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
1615         CHECK_EXPECT(QueryInterface_IWinInetInfo);
1616         *ppv = NULL;
1617         return E_NOINTERFACE;
1618     }
1619 
1620     if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
1621         CHECK_EXPECT(QueryInterface_IWinInetHttpInfo);
1622         *ppv = NULL;
1623         return E_NOINTERFACE;
1624     }
1625 
1626     if(!IsEqualGUID(riid, &unknown_iid)) /* IE10 */
1627         ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
1628     *ppv = NULL;
1629     return E_NOINTERFACE;
1630 }
1631 
1632 static DWORD WINAPI thread_proc(PVOID arg)
1633 {
1634     BOOL redirect_only = redirect_on_continue;
1635     HRESULT hres;
1636 
1637     memset(&protocoldata, -1, sizeof(protocoldata));
1638 
1639     prot_state = 0;
1640 
1641     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1642     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1643             BINDSTATUS_FINDINGRESOURCE, hostW);
1644     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1645     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1646 
1647     SET_EXPECT(ReportProgress_CONNECTING);
1648     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1649             BINDSTATUS_CONNECTING, winehq_ipW);
1650     CHECK_CALLED(ReportProgress_CONNECTING);
1651     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1652 
1653     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1654     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1655             BINDSTATUS_SENDINGREQUEST, NULL);
1656     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1657     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1658 
1659     prot_state = 1;
1660     SET_EXPECT(Switch);
1661     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1662     CHECK_CALLED(Switch);
1663     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1664 
1665     if(redirect_only) {
1666         prot_state = 0;
1667         return 0;
1668     }
1669 
1670     if(!short_read) {
1671         prot_state = 2;
1672         if(mimefilter_test)
1673             SET_EXPECT(MimeFilter_Switch);
1674         else
1675             SET_EXPECT(Switch);
1676         hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1677         ok(hres == S_OK, "Switch failed: %08x\n", hres);
1678         if(mimefilter_test)
1679             CHECK_CALLED(MimeFilter_Switch);
1680         else
1681             CHECK_CALLED(Switch);
1682 
1683         if(test_abort) {
1684             SetEvent(event_complete);
1685             return 0;
1686         }
1687 
1688         prot_state = 2;
1689         if(mimefilter_test)
1690             SET_EXPECT(MimeFilter_Switch);
1691         else
1692             SET_EXPECT(Switch);
1693         hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1694         ok(hres == S_OK, "Switch failed: %08x\n", hres);
1695         if(mimefilter_test)
1696             CHECK_CALLED(MimeFilter_Switch);
1697         else
1698             CHECK_CALLED(Switch);
1699 
1700         prot_state = 3;
1701         if(mimefilter_test)
1702             SET_EXPECT(MimeFilter_Switch);
1703         else
1704             SET_EXPECT(Switch);
1705         hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1706         ok(hres == S_OK, "Switch failed: %08x\n", hres);
1707         if(mimefilter_test)
1708             CHECK_CALLED(MimeFilter_Switch);
1709         else
1710             CHECK_CALLED(Switch);
1711     }
1712 
1713     SetEvent(event_complete);
1714 
1715     return 0;
1716 }
1717 
1718 static void protocol_start(IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD pi)
1719 {
1720     BINDINFO bindinfo, exp_bindinfo;
1721     DWORD cbindf = 0;
1722     HRESULT hres;
1723 
1724     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
1725     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
1726     ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
1727     ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
1728     ok(!pi, "pi = %x\n", pi);
1729 
1730     if(binding_test)
1731         ok(pOIProtSink == binding_sink, "pOIProtSink != binding_sink\n");
1732 
1733     memset(&bindinfo, 0, sizeof(bindinfo));
1734     bindinfo.cbSize = sizeof(bindinfo);
1735     memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
1736     if(test_redirect)
1737         exp_bindinfo.dwOptions = bindinfo_options;
1738     SET_EXPECT(GetBindInfo);
1739     if(redirect_on_continue && (bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
1740         SET_EXPECT(QueryService_IBindCallbackRedirect);
1741     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
1742     if(redirect_on_continue && (bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
1743         CHECK_CALLED(QueryService_IBindCallbackRedirect);
1744     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
1745     CHECK_CALLED(GetBindInfo);
1746     ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
1747        cbindf, (bindf|BINDF_FROMURLMON));
1748     ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
1749     pReleaseBindInfo(&bindinfo);
1750 
1751     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1752     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
1753     ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
1754     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1755 
1756     if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
1757         IServiceProvider *service_provider;
1758         IHttpNegotiate *http_negotiate;
1759         IHttpNegotiate2 *http_negotiate2;
1760         LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
1761         LPWSTR additional_headers = NULL;
1762         BYTE sec_id[100];
1763         DWORD fetched = 0, size = 100;
1764         DWORD tid;
1765 
1766         SET_EXPECT(GetBindString_USER_AGENT);
1767         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
1768                                                &ua, 1, &fetched);
1769         CHECK_CALLED(GetBindString_USER_AGENT);
1770         ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
1771         ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
1772         ok(ua != NULL, "ua =  %p\n", ua);
1773         ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", wine_dbgstr_w(ua));
1774         CoTaskMemFree(ua);
1775 
1776         fetched = 256;
1777         SET_EXPECT(GetBindString_ACCEPT_MIMES);
1778         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
1779                                                accept_mimes, 256, &fetched);
1780         CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1781 
1782         ok(hres == S_OK,
1783            "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
1784         ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
1785         ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", wine_dbgstr_w(accept_mimes[0]));
1786         CoTaskMemFree(accept_mimes[0]);
1787 
1788         hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
1789                                                 (void**)&service_provider);
1790         ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
1791 
1792         SET_EXPECT(QueryService_HttpNegotiate);
1793         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1794                 &IID_IHttpNegotiate, (void**)&http_negotiate);
1795         CHECK_CALLED(QueryService_HttpNegotiate);
1796         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1797 
1798         SET_EXPECT(BeginningTransaction);
1799         hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
1800                                                    NULL, 0, &additional_headers);
1801         CHECK_CALLED(BeginningTransaction);
1802         IHttpNegotiate_Release(http_negotiate);
1803         ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
1804         ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
1805 
1806         SET_EXPECT(QueryService_HttpNegotiate);
1807         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
1808                 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
1809         CHECK_CALLED(QueryService_HttpNegotiate);
1810         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1811 
1812         size = 512;
1813         SET_EXPECT(GetRootSecurityId);
1814         hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
1815         CHECK_CALLED(GetRootSecurityId);
1816         IHttpNegotiate2_Release(http_negotiate2);
1817         ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
1818         ok(size == 13, "size=%d\n", size);
1819 
1820         IServiceProvider_Release(service_provider);
1821 
1822         CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
1823         return;
1824     }
1825 
1826     SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1827     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
1828             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1829     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1830     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1831 
1832     if(mimefilter_test) {
1833         SET_EXPECT(MimeFilter_CreateInstance);
1834         SET_EXPECT(MimeFilter_Start);
1835         SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1836     }
1837     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1838     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
1839             mimefilter_test ? pjpegW : (expect_wsz = text_htmlW));
1840     ok(hres == S_OK,
1841        "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
1842     if(mimefilter_test) {
1843         CHECK_CALLED(MimeFilter_CreateInstance);
1844         CHECK_CALLED(MimeFilter_Start);
1845         CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1846         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1847     }else {
1848         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1849     }
1850 
1851     if(mimefilter_test)
1852         SET_EXPECT(MimeFilter_ReportData);
1853     else
1854         SET_EXPECT(ReportData);
1855     hres = IInternetProtocolSink_ReportData(pOIProtSink,
1856             BSCF_FIRSTDATANOTIFICATION | (tested_protocol == ITS_TEST ? BSCF_DATAFULLYAVAILABLE : BSCF_LASTDATANOTIFICATION),
1857             13, 13);
1858     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1859     if(mimefilter_test)
1860         CHECK_CALLED(MimeFilter_ReportData);
1861     else
1862         CHECK_CALLED(ReportData);
1863 
1864     if(tested_protocol == ITS_TEST) {
1865         SET_EXPECT(ReportData);
1866         hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
1867         ok(hres == S_OK, "ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres);
1868         CHECK_CALLED(ReportData);
1869     }
1870 
1871     if(tested_protocol == BIND_TEST) {
1872         hres = IInternetProtocol_Terminate(binding_protocol, 0);
1873         ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
1874     }
1875 
1876     if(mimefilter_test)
1877         SET_EXPECT(MimeFilter_ReportResult);
1878     else
1879         SET_EXPECT(ReportResult);
1880     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
1881     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1882     if(mimefilter_test)
1883         CHECK_CALLED(MimeFilter_ReportResult);
1884     else
1885         CHECK_CALLED(ReportResult);
1886 }
1887 
1888 static HRESULT WINAPI ProtocolEmul_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
1889         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1890         DWORD grfPI, HANDLE_PTR dwReserved)
1891 {
1892     CHECK_EXPECT(Start);
1893 
1894     ok(!dwReserved, "dwReserved = %lx\n", dwReserved);
1895     protocol_start(pOIProtSink, pOIBindInfo, grfPI);
1896     return S_OK;
1897 }
1898 
1899 static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocolEx *iface,
1900         PROTOCOLDATA *pProtocolData)
1901 {
1902     DWORD bscf = 0, pr;
1903     HRESULT hres;
1904 
1905     CHECK_EXPECT(Continue);
1906 
1907     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
1908     if(!pProtocolData || tested_protocol == BIND_TEST)
1909         return S_OK;
1910     if(binding_test) {
1911         ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
1912         ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
1913            pProtocolData->grfFlags, protocoldata.grfFlags );
1914         ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
1915            pProtocolData->dwState, protocoldata.dwState );
1916         ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
1917            pProtocolData->pData, protocoldata.pData );
1918         ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
1919            pProtocolData->cbData, protocoldata.cbData );
1920     }
1921 
1922     switch(prot_state) {
1923     case 1: {
1924         IServiceProvider *service_provider;
1925         IHttpNegotiate *http_negotiate;
1926         static const WCHAR header[] = {'?',0};
1927         static const WCHAR redirect_urlW[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',
1928                                               '/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
1929 
1930         if(redirect_on_continue) {
1931             redirect_on_continue = FALSE;
1932 
1933             if(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)
1934                 SET_EXPECT(Redirect);
1935             SET_EXPECT(ReportProgress_REDIRECTING);
1936             SET_EXPECT(Terminate);
1937             SET_EXPECT(QueryService_InternetProtocol);
1938             SET_EXPECT(CreateInstance);
1939             SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
1940             SET_EXPECT(SetPriority);
1941             SET_EXPECT(Start);
1942             hres = IInternetProtocolSink_ReportResult(binding_sink, INET_E_REDIRECT_FAILED, ERROR_SUCCESS, redirect_urlW);
1943             ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1944             if(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)
1945                 CHECK_CALLED(Redirect);
1946             CHECK_CALLED(ReportProgress_REDIRECTING);
1947             CHECK_CALLED(Terminate);
1948             CHECK_CALLED(QueryService_InternetProtocol);
1949             CHECK_CALLED(CreateInstance);
1950             CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
1951             todo_wine CHECK_NOT_CALLED(SetPriority);
1952             CHECK_CALLED(Start);
1953 
1954             return S_OK;
1955         }
1956 
1957         hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
1958                                                     (void**)&service_provider);
1959         ok(hres == S_OK, "Could not get IServiceProvicder\n");
1960 
1961         SET_EXPECT(QueryService_HttpNegotiate);
1962         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1963                                              &IID_IHttpNegotiate, (void**)&http_negotiate);
1964         IServiceProvider_Release(service_provider);
1965         CHECK_CALLED(QueryService_HttpNegotiate);
1966         ok(hres == S_OK, "Could not get IHttpNegotiate\n");
1967 
1968         SET_EXPECT(OnResponse);
1969         hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
1970         IHttpNegotiate_Release(http_negotiate);
1971         CHECK_CALLED(OnResponse);
1972         IHttpNegotiate_Release(http_negotiate);
1973         ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
1974 
1975         if(mimefilter_test) {
1976             SET_EXPECT(MimeFilter_CreateInstance);
1977             SET_EXPECT(MimeFilter_Start);
1978             SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1979         }else if(!(pi & PI_MIMEVERIFICATION)) {
1980             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1981         }
1982         hres = IInternetProtocolSink_ReportProgress(binding_sink,
1983                 BINDSTATUS_MIMETYPEAVAILABLE, mimefilter_test ? pjpegW : text_htmlW);
1984         if(mimefilter_test) {
1985             CHECK_CALLED(MimeFilter_CreateInstance);
1986             CHECK_CALLED(MimeFilter_Start);
1987             CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1988         }else if(!(pi & PI_MIMEVERIFICATION)) {
1989             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1990         }
1991         ok(hres == S_OK,
1992            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
1993 
1994         bscf |= BSCF_FIRSTDATANOTIFICATION;
1995         break;
1996     }
1997     case 2:
1998     case 3:
1999         bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
2000         break;
2001     }
2002 
2003     pr = prot_read;
2004     if(mimefilter_test)
2005         SET_EXPECT(MimeFilter_ReportData);
2006     if((!mimefilter_test || no_mime) && (pi & PI_MIMEVERIFICATION)) {
2007         if(pr < 200)
2008             SET_EXPECT(Read); /* checked in ReportData for short_read */
2009         if(pr == 200) {
2010             if(!mimefilter_test)
2011                 SET_EXPECT(Read); /* checked in BINDSTATUS_MIMETYPEAVAILABLE or ReportData */
2012             SET_EXPECT(GetBindInfo);
2013             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2014         }
2015         if(pr >= 200)
2016             SET_EXPECT(ReportData);
2017     }else {
2018         SET_EXPECT(ReportData);
2019     }
2020 
2021     hres = IInternetProtocolSink_ReportData(binding_sink, bscf, pr, 400);
2022     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2023 
2024     if(mimefilter_test) {
2025         SET_EXPECT(MimeFilter_ReportData);
2026     }else if(pi & PI_MIMEVERIFICATION) {
2027         if(!short_read && pr < 200)
2028             CHECK_CALLED(Read);
2029         if(pr == 200) {
2030             CLEAR_CALLED(GetBindInfo); /* IE9 */
2031             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2032         }
2033     }else {
2034         CHECK_CALLED(ReportData);
2035     }
2036 
2037     if(prot_state == 3)
2038         prot_state = 4;
2039 
2040     return S_OK;
2041 }
2042 
2043 static HRESULT WINAPI ProtocolEmul_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2044 {
2045     CHECK_EXPECT(Terminate);
2046     ok(!dwOptions, "dwOptions=%d\n", dwOptions);
2047     return S_OK;
2048 }
2049 
2050 static HRESULT WINAPI ProtocolEmul_Read(IInternetProtocolEx *iface, void *pv,
2051         ULONG cb, ULONG *pcbRead)
2052 {
2053     if(read_report_data)
2054         CHECK_EXPECT2(Read2);
2055 
2056     if(mimefilter_test || short_read) {
2057         if(!read_report_data)
2058             CHECK_EXPECT2(Read);
2059     }else if((pi & PI_MIMEVERIFICATION)) {
2060         if(!read_report_data)
2061             CHECK_EXPECT2(Read);
2062 
2063         if(prot_read < 300) {
2064             ok(pv != expect_pv, "pv == expect_pv\n");
2065             if(prot_read < 300)
2066                 ok(cb == 2048-prot_read, "cb=%d\n", cb);
2067             else
2068                 ok(cb == 700, "cb=%d\n", cb);
2069         }else {
2070             ok(expect_pv <= pv && (BYTE*)pv < (BYTE*)expect_pv + cb, "pv != expect_pv\n");
2071         }
2072     }else {
2073         if(!read_report_data)
2074             CHECK_EXPECT(Read);
2075 
2076         ok(pv == expect_pv, "pv != expect_pv\n");
2077         ok(cb == 1000, "cb=%d\n", cb);
2078         ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
2079     }
2080     ok(pcbRead != NULL, "pcbRead == NULL\n");
2081 
2082     if(prot_state == 3 || (short_read && prot_state != 4)) {
2083         HRESULT hres;
2084 
2085         prot_state = 4;
2086         if(short_read) {
2087             SET_EXPECT(Read2); /* checked in BINDSTATUS_MIMETYPEAVAILABLE */
2088             SET_EXPECT(GetBindInfo);
2089             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2090         }
2091         if(mimefilter_test)
2092             SET_EXPECT(MimeFilter_ReportData);
2093         else if(direct_read)
2094             SET_EXPECT(ReportData2);
2095         read_report_data++;
2096         hres = IInternetProtocolSink_ReportData(binding_sink,
2097                 BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION, 0, 0);
2098         read_report_data--;
2099         ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2100         if(short_read) {
2101             CLEAR_CALLED(GetBindInfo); /* IE9 */
2102             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2103         }
2104         if(mimefilter_test)
2105             CHECK_CALLED(MimeFilter_ReportData);
2106         else if(direct_read)
2107             CHECK_CALLED(ReportData2);
2108 
2109         if(mimefilter_test)
2110             SET_EXPECT(MimeFilter_ReportResult);
2111         else
2112             SET_EXPECT(ReportResult);
2113         hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
2114         ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
2115         if(mimefilter_test)
2116             CHECK_CALLED(MimeFilter_ReportResult);
2117         else
2118             CHECK_CALLED(ReportResult);
2119 
2120         if(cb > 100)
2121             cb = 100;
2122         memset(pv, 'x', cb);
2123         if(cb>6)
2124             memcpy(pv, "gif87a", 6);
2125         prot_read += *pcbRead = cb;
2126         return S_OK;
2127     }
2128 
2129     if(prot_state == 4) {
2130         *pcbRead = 0;
2131         return S_FALSE;
2132     }
2133 
2134     if((async_read_pending = !async_read_pending)) {
2135         *pcbRead = 0;
2136         return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
2137     }
2138 
2139     if(cb > 100)
2140         cb = 100;
2141     memset(pv, 'x', cb);
2142     if(cb>6)
2143         memcpy(pv, "gif87a", 6);
2144     prot_read += *pcbRead = cb;
2145     return S_OK;
2146 }
2147 
2148 static HRESULT WINAPI ProtocolEmul_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2149 {
2150     CHECK_EXPECT(LockRequest);
2151     ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
2152     return S_OK;
2153 }
2154 
2155 static HRESULT WINAPI ProtocolEmul_UnlockRequest(IInternetProtocolEx *iface)
2156 {
2157     CHECK_EXPECT(UnlockRequest);
2158     return S_OK;
2159 }
2160 
2161 static HRESULT WINAPI ProtocolEmul_StartEx(IInternetProtocolEx *iface, IUri *pUri,
2162         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2163         DWORD grfPI, HANDLE *dwReserved)
2164 {
2165     CHECK_EXPECT(StartEx);
2166     ok(!dwReserved, "dwReserved = %p\n", dwReserved);
2167     protocol_start(pOIProtSink, pOIBindInfo, grfPI);
2168     return S_OK;
2169 }
2170 
2171 static const IInternetProtocolExVtbl ProtocolVtbl = {
2172     ProtocolEmul_QueryInterface,
2173     Protocol_AddRef,
2174     Protocol_Release,
2175     ProtocolEmul_Start,
2176     ProtocolEmul_Continue,
2177     Protocol_Abort,
2178     ProtocolEmul_Terminate,
2179     Protocol_Suspend,
2180     Protocol_Resume,
2181     ProtocolEmul_Read,
2182     Protocol_Seek,
2183     ProtocolEmul_LockRequest,
2184     ProtocolEmul_UnlockRequest,
2185     ProtocolEmul_StartEx
2186 };
2187 
2188 static IInternetProtocolEx Protocol = { &ProtocolVtbl };
2189 
2190 static HRESULT WINAPI MimeProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
2191 {
2192     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
2193         *ppv = iface;
2194         return S_OK;
2195     }
2196 
2197     if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
2198         *ppv = &mime_protocol_sink;
2199         return S_OK;
2200     }
2201 
2202     ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
2203     *ppv = NULL;
2204     return E_NOINTERFACE;
2205 }
2206 
2207 static HRESULT WINAPI MimeProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
2208         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2209         DWORD grfPI, HANDLE_PTR dwReserved)
2210 {
2211     PROTOCOLFILTERDATA *data;
2212     LPOLESTR url_str = NULL;
2213     DWORD fetched = 0;
2214     BINDINFO bindinfo;
2215     DWORD cbindf = 0;
2216     HRESULT hres;
2217 
2218     CHECK_EXPECT(MimeFilter_Start);
2219 
2220     ok(!lstrcmpW(szUrl, pjpegW), "wrong url %s\n", wine_dbgstr_w(szUrl));
2221     ok(grfPI == (PI_FILTER_MODE|PI_FORCE_ASYNC), "grfPI=%x, expected PI_FILTER_MODE|PI_FORCE_ASYNC\n", grfPI);
2222     ok(dwReserved, "dwReserved == 0\n");
2223     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
2224     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
2225 
2226     if(binding_test) {
2227         ok(pOIProtSink != binding_sink, "pOIProtSink == protocol_sink\n");
2228         ok(pOIBindInfo == prot_bind_info, "pOIBindInfo != bind_info\n");
2229     }else {
2230         ok(pOIProtSink == &protocol_sink, "pOIProtSink != protocol_sink\n");
2231         ok(pOIBindInfo == &bind_info, "pOIBindInfo != bind_info\n");
2232     }
2233 
2234     data = (void*)dwReserved;
2235     ok(data->cbSize == sizeof(*data), "data->cbSize = %d\n", data->cbSize);
2236     ok(!data->pProtocolSink, "data->pProtocolSink != NULL\n");
2237     ok(data->pProtocol != NULL, "data->pProtocol == NULL\n");
2238     ok(!data->pUnk, "data->pUnk != NULL\n");
2239     ok(!data->dwFilterFlags, "data->dwProtocolFlags = %x\n", data->dwFilterFlags);
2240     if(binding_test) {
2241         IInternetProtocolSink *prot_sink;
2242 
2243         IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocolSink, (void**)&prot_sink);
2244         ok(prot_sink == pOIProtSink, "QI(data->pProtocol, IID_IInternetProtocolSink) != pOIProtSink\n");
2245         IInternetProtocolSink_Release(prot_sink);
2246 
2247         ok(data->pProtocol != binding_protocol, "data->pProtocol == binding_protocol\n");
2248 
2249         filtered_protocol = data->pProtocol;
2250         IInternetProtocol_AddRef(filtered_protocol);
2251     }else {
2252         IInternetProtocol *prot;
2253 
2254         IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocol, (void**)&prot);
2255         ok(prot == async_protocol, "QI(data->pProtocol, IID_IInternetProtocol) != async_protocol\n");
2256         IInternetProtocol_Release(prot);
2257 
2258         ok(data->pProtocol != async_protocol, "data->pProtocol == async_protocol\n");
2259     }
2260 
2261     filtered_sink = pOIProtSink;
2262 
2263     SET_EXPECT(ReportProgress_DECODING);
2264     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DECODING, pjpegW);
2265     ok(hres == S_OK, "ReportProgress(BINDSTATUS_DECODING) failed: %08x\n", hres);
2266     CHECK_CALLED(ReportProgress_DECODING);
2267 
2268     SET_EXPECT(GetBindInfo);
2269     memset(&bindinfo, 0, sizeof(bindinfo));
2270     bindinfo.cbSize = sizeof(bindinfo);
2271     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
2272     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
2273     ok(cbindf == (bindf|BINDF_FROMURLMON), "cbindf = %x, expected %x\n", cbindf, bindf);
2274     CHECK_CALLED(GetBindInfo);
2275 
2276     SET_EXPECT(GetBindString_URL);
2277     hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_URL, &url_str, 1, &fetched);
2278     ok(hres == S_OK, "GetBindString(BINDSTRING_URL) failed: %08x\n", hres);
2279     ok(fetched == 1, "fetched = %d\n", fetched);
2280     ok(!lstrcmpW(url_str, binding_urls[tested_protocol]), "wrong url_str %s\n", wine_dbgstr_w(url_str));
2281     CoTaskMemFree(url_str);
2282     CHECK_CALLED(GetBindString_URL);
2283 
2284     return S_OK;
2285 }
2286 
2287 static HRESULT WINAPI Protocol_Continue(IInternetProtocolEx *iface,
2288         PROTOCOLDATA *pProtocolData)
2289 {
2290     CHECK_EXPECT(MimeFilter_Continue);
2291     return E_NOTIMPL;
2292 }
2293 
2294 static HRESULT WINAPI MimeProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2295 {
2296     HRESULT hres;
2297 
2298     CHECK_EXPECT(MimeFilter_Terminate);
2299 
2300     ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2301 
2302     SET_EXPECT(Terminate);
2303     hres = IInternetProtocol_Terminate(filtered_protocol, dwOptions);
2304     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2305     CHECK_CALLED(Terminate);
2306 
2307     return S_OK;
2308 }
2309 
2310 static HRESULT WINAPI MimeProtocol_Read(IInternetProtocolEx *iface, void *pv,
2311         ULONG cb, ULONG *pcbRead)
2312 {
2313     BYTE buf[2096];
2314     DWORD read = 0;
2315     HRESULT hres;
2316 
2317     CHECK_EXPECT(MimeFilter_Read);
2318 
2319     ok(pv != NULL, "pv == NULL\n");
2320     ok(cb != 0, "cb == 0\n");
2321     ok(pcbRead != NULL, "pcbRead == NULL\n");
2322 
2323     if(read_report_data)
2324         SET_EXPECT(Read2);
2325     else
2326         SET_EXPECT(Read);
2327     hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
2328     ok(hres == S_OK || hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
2329     if(read_report_data)
2330         CHECK_CALLED(Read2);
2331     else
2332         CHECK_CALLED(Read);
2333 
2334     if(pcbRead) {
2335         ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
2336         *pcbRead = read;
2337     }
2338 
2339     memset(pv, 'x', read);
2340     return hres;
2341 }
2342 
2343 static HRESULT WINAPI MimeProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2344 {
2345     HRESULT hres;
2346 
2347     CHECK_EXPECT(MimeFilter_LockRequest);
2348 
2349     ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2350 
2351     SET_EXPECT(LockRequest);
2352     hres = IInternetProtocol_LockRequest(filtered_protocol, dwOptions);
2353     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2354     CHECK_CALLED(LockRequest);
2355 
2356     return S_OK;
2357 }
2358 
2359 static HRESULT WINAPI MimeProtocol_UnlockRequest(IInternetProtocolEx *iface)
2360 {
2361     HRESULT hres;
2362 
2363     CHECK_EXPECT(MimeFilter_UnlockRequest);
2364 
2365     SET_EXPECT(UnlockRequest);
2366     hres = IInternetProtocol_UnlockRequest(filtered_protocol);
2367     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2368     CHECK_CALLED(UnlockRequest);
2369 
2370     return S_OK;
2371 }
2372 
2373 static const IInternetProtocolExVtbl MimeProtocolVtbl = {
2374     MimeProtocol_QueryInterface,
2375     Protocol_AddRef,
2376     Protocol_Release,
2377     MimeProtocol_Start,
2378     Protocol_Continue,
2379     Protocol_Abort,
2380     MimeProtocol_Terminate,
2381     Protocol_Suspend,
2382     Protocol_Resume,
2383     MimeProtocol_Read,
2384     Protocol_Seek,
2385     MimeProtocol_LockRequest,
2386     MimeProtocol_UnlockRequest
2387 };
2388 
2389 static IInternetProtocolEx MimeProtocol = { &MimeProtocolVtbl };
2390 
2391 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
2392 {
2393     ok(0, "unexpected call\n");
2394     return E_NOINTERFACE;
2395 }
2396 
2397 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
2398 {
2399     return 2;
2400 }
2401 
2402 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
2403 {
2404     return 1;
2405 }
2406 
2407 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
2408         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
2409         DWORD *pcchResult, DWORD dwReserved)
2410 {
2411     ok(0, "unexpected call %d\n", ParseAction);
2412     return E_NOTIMPL;
2413 }
2414 
2415 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
2416         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
2417         LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
2418 {
2419     ok(0, "unexpected call\n");
2420     return E_NOTIMPL;
2421 }
2422 
2423 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
2424         LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
2425 {
2426     ok(0, "unexpected call\n");
2427     return E_NOTIMPL;
2428 }
2429 
2430 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
2431         LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
2432         DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
2433 {
2434     ok(0, "unexpected call\n");
2435     return E_NOTIMPL;
2436 }
2437 
2438 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
2439     InternetProtocolInfo_QueryInterface,
2440     InternetProtocolInfo_AddRef,
2441     InternetProtocolInfo_Release,
2442     InternetProtocolInfo_ParseUrl,
2443     InternetProtocolInfo_CombineUrl,
2444     InternetProtocolInfo_CompareUrl,
2445     InternetProtocolInfo_QueryInfo
2446 };
2447 
2448 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
2449 
2450 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2451 {
2452     if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
2453         *ppv = &protocol_info;
2454         return S_OK;
2455     }
2456 
2457     ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
2458     return E_NOINTERFACE;
2459 }
2460 
2461 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
2462 {
2463     return 2;
2464 }
2465 
2466 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
2467 {
2468     return 1;
2469 }
2470 
2471 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
2472                                         REFIID riid, void **ppv)
2473 {
2474     CHECK_EXPECT(CreateInstance);
2475 
2476     ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
2477     ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2478     ok(ppv != NULL, "ppv == NULL\n");
2479 
2480     *ppv = &Protocol;
2481     return S_OK;
2482 }
2483 
2484 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
2485 {
2486     ok(0, "unexpected call\n");
2487     return S_OK;
2488 }
2489 
2490 static const IClassFactoryVtbl ClassFactoryVtbl = {
2491     ClassFactory_QueryInterface,
2492     ClassFactory_AddRef,
2493     ClassFactory_Release,
2494     ClassFactory_CreateInstance,
2495     ClassFactory_LockServer
2496 };
2497 
2498 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
2499 
2500 static HRESULT WINAPI MimeFilter_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
2501 {
2502     CHECK_EXPECT(MimeFilter_CreateInstance);
2503 
2504     ok(!outer, "outer = %p\n", outer);
2505     ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2506 
2507     *ppv = &MimeProtocol;
2508     return S_OK;
2509 }
2510 
2511 static const IClassFactoryVtbl MimeFilterCFVtbl = {
2512     ClassFactory_QueryInterface,
2513     ClassFactory_AddRef,
2514     ClassFactory_Release,
2515     MimeFilter_CreateInstance,
2516     ClassFactory_LockServer
2517 };
2518 
2519 static IClassFactory mimefilter_cf = { &MimeFilterCFVtbl };
2520 
2521 #define TEST_BINDING     0x0001
2522 #define TEST_FILTER      0x0002
2523 #define TEST_FIRST_HTTP  0x0004
2524 #define TEST_DIRECT_READ 0x0008
2525 #define TEST_POST        0x0010
2526 #define TEST_EMULATEPROT 0x0020
2527 #define TEST_SHORT_READ  0x0040
2528 #define TEST_REDIRECT    0x0080
2529 #define TEST_ABORT       0x0100
2530 #define TEST_ASYNCREQ    0x0200
2531 #define TEST_USEIURI     0x0400
2532 #define TEST_IMPLPROTEX  0x0800
2533 #define TEST_EMPTY       0x1000
2534 #define TEST_NOMIME      0x2000
2535 #define TEST_FROMCACHE   0x4000
2536 #define TEST_DISABLEAUTOREDIRECT  0x8000
2537 
2538 static void register_filter(BOOL do_register)
2539 {
2540     IInternetSession *session;
2541     HRESULT hres;
2542 
2543     hres = pCoInternetGetSession(0, &session, 0);
2544     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2545 
2546     if(do_register) {
2547         hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, pjpegW);
2548         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2549         hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, gifW);
2550         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2551     }else {
2552         hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, pjpegW);
2553         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2554         hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, gifW);
2555         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2556     }
2557 
2558     IInternetSession_Release(session);
2559 }
2560 
2561 static void init_test(int prot, DWORD flags)
2562 {
2563     tested_protocol = prot;
2564     binding_test = (flags & TEST_BINDING) != 0;
2565     first_data_notif = TRUE;
2566     prot_read = 0;
2567     prot_state = 0;
2568     async_read_pending = TRUE;
2569     mimefilter_test = (flags & TEST_FILTER) != 0;
2570     no_mime = (flags & TEST_NOMIME) != 0;
2571     filter_state = 0;
2572     post_stream_read = 0;
2573     ResetEvent(event_complete);
2574     ResetEvent(event_complete2);
2575     ResetEvent(event_continue);
2576     ResetEvent(event_continue_done);
2577     async_protocol = binding_protocol = filtered_protocol = NULL;
2578     filtered_sink = NULL;
2579     http_is_first = (flags & TEST_FIRST_HTTP) != 0;
2580     first_data_notif = TRUE;
2581     state = STATE_CONNECTING;
2582     test_async_req = (flags & TEST_ASYNCREQ) != 0;
2583     direct_read = (flags & TEST_DIRECT_READ) != 0;
2584     emulate_prot = (flags & TEST_EMULATEPROT) != 0;
2585     wait_for_switch = TRUE;
2586     short_read = (flags & TEST_SHORT_READ) != 0;
2587     http_post_test = TYMED_NULL;
2588     redirect_on_continue = test_redirect = (flags & TEST_REDIRECT) != 0;
2589     test_abort = (flags & TEST_ABORT) != 0;
2590     impl_protex = (flags & TEST_IMPLPROTEX) != 0;
2591     empty_file = (flags & TEST_EMPTY) != 0;
2592     bind_from_cache = (flags & TEST_FROMCACHE) != 0;
2593     file_with_hash = FALSE;
2594 
2595     bindinfo_options = 0;
2596     if(flags & TEST_DISABLEAUTOREDIRECT)
2597         bindinfo_options |= BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS;
2598 
2599     register_filter(mimefilter_test);
2600 }
2601 
2602 static void test_priority(IInternetProtocol *protocol)
2603 {
2604     IInternetPriority *priority;
2605     LONG pr;
2606     HRESULT hres;
2607 
2608     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
2609                                             (void**)&priority);
2610     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
2611     if(FAILED(hres))
2612         return;
2613 
2614     hres = IInternetPriority_GetPriority(priority, &pr);
2615     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2616     ok(pr == 0, "pr=%d, expected 0\n", pr);
2617 
2618     hres = IInternetPriority_SetPriority(priority, 1);
2619     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2620 
2621     hres = IInternetPriority_GetPriority(priority, &pr);
2622     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2623     ok(pr == 1, "pr=%d, expected 1\n", pr);
2624 
2625     IInternetPriority_Release(priority);
2626 }
2627 
2628 static void test_early_abort(const CLSID *clsid)
2629 {
2630     IInternetProtocol *protocol;
2631     HRESULT hres;
2632 
2633     hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2634             &IID_IInternetProtocol, (void**)&protocol);
2635     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2636 
2637     hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
2638     ok(hres == S_OK, "Abort failed: %08x\n", hres);
2639 
2640     hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
2641     ok(hres == S_OK, "Abort failed: %08x\n", hres);
2642 
2643     IInternetProtocol_Release(protocol);
2644 }
2645 
2646 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url,
2647         IInternetProtocolEx *protocolex, IUri *uri, BOOL is_first)
2648 {
2649     HRESULT hres;
2650 
2651     SET_EXPECT(GetBindInfo);
2652     if(!(bindf & BINDF_FROMURLMON))
2653        SET_EXPECT(ReportProgress_DIRECTBIND);
2654     if(is_first) {
2655         SET_EXPECT(ReportProgress_SENDINGREQUEST);
2656         SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
2657         if(bindf & BINDF_FROMURLMON)
2658             SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2659         else
2660             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2661     }
2662     SET_EXPECT(ReportData);
2663     if(is_first)
2664         SET_EXPECT(ReportResult);
2665 
2666     expect_hrResult = S_OK;
2667 
2668     if(protocolex) {
2669         hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
2670         ok(hres == S_OK, "StartEx failed: %08x\n", hres);
2671     }else {
2672         hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
2673         if(hres == INET_E_RESOURCE_NOT_FOUND) {
2674             win_skip("Start failed\n");
2675             return FALSE;
2676         }
2677         ok(hres == S_OK, "Start failed: %08x\n", hres);
2678     }
2679 
2680     CHECK_CALLED(GetBindInfo);
2681     if(!(bindf & BINDF_FROMURLMON))
2682         CLEAR_CALLED(ReportProgress_DIRECTBIND); /* Not called by IE10 */
2683     if(is_first) {
2684         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2685         CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
2686         if(bindf & BINDF_FROMURLMON)
2687             CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2688         else
2689             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2690     }
2691     CHECK_CALLED(ReportData);
2692     if(is_first)
2693         CHECK_CALLED(ReportResult);
2694 
2695     return TRUE;
2696 }
2697 
2698 static void test_file_protocol_url(LPCWSTR url)
2699 {
2700     IInternetProtocolInfo *protocol_info;
2701     IUnknown *unk;
2702     IClassFactory *factory;
2703     IInternetProtocol *protocol;
2704     BYTE buf[512];
2705     ULONG cb;
2706     HRESULT hres;
2707 
2708     hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
2709             &IID_IUnknown, (void**)&unk);
2710     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2711     if(FAILED(hres))
2712         return;
2713 
2714     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2715     ok(hres == E_NOINTERFACE,
2716             "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
2717 
2718     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2719     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2720     IUnknown_Release(unk);
2721     if(FAILED(hres))
2722         return;
2723 
2724     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2725     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2726 
2727     if(SUCCEEDED(hres)) {
2728         if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2729             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2730             ok(hres == S_OK, "Read failed: %08x\n", hres);
2731             ok(cb == 2, "cb=%u expected 2\n", cb);
2732             buf[2] = 0;
2733             ok(!memcmp(buf, file_with_hash ? "XX" : "<H", 2), "Unexpected data %s\n", buf);
2734             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2735             ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2736             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2737             ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
2738             ok(cb == 0, "cb=%u expected 0\n", cb);
2739             hres = IInternetProtocol_UnlockRequest(protocol);
2740             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2741         }
2742 
2743         if(file_protocol_start(protocol, url, NULL, NULL, FALSE)) {
2744             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2745             ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2746             hres = IInternetProtocol_LockRequest(protocol, 0);
2747             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2748             hres = IInternetProtocol_UnlockRequest(protocol);
2749             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2750         }
2751 
2752         IInternetProtocol_Release(protocol);
2753     }
2754 
2755     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2756     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2757     if(SUCCEEDED(hres)) {
2758         if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2759             hres = IInternetProtocol_LockRequest(protocol, 0);
2760             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2761             hres = IInternetProtocol_Terminate(protocol, 0);
2762             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2763             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2764             ok(hres == S_OK, "Read failed: %08x\n\n", hres);
2765             hres = IInternetProtocol_UnlockRequest(protocol);
2766             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2767             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2768             todo_wine_if(file_with_hash) /* FIXME: An effect of UnlockRequest call? */
2769                 ok(hres == S_OK, "Read failed: %08x\n", hres);
2770             hres = IInternetProtocol_Terminate(protocol, 0);
2771             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2772         }
2773 
2774         IInternetProtocol_Release(protocol);
2775     }
2776 
2777     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2778     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2779     if(SUCCEEDED(hres)) {
2780         if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2781             hres = IInternetProtocol_Terminate(protocol, 0);
2782             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2783             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2784             ok(hres == S_OK, "Read failed: %08x\n", hres);
2785             ok(cb == 2, "cb=%u expected 2\n", cb);
2786         }
2787 
2788         IInternetProtocol_Release(protocol);
2789     }
2790 
2791     if(pCreateUri) {
2792         IInternetProtocolEx *protocolex;
2793         IUri *uri;
2794 
2795         hres = pCreateUri(url, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
2796         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2797 
2798         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2799         ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2800 
2801         if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2802             hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2803             ok(hres == S_OK, "Read failed: %08x\n", hres);
2804             hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2805             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2806             hres = IInternetProtocolEx_UnlockRequest(protocolex);
2807             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2808         }
2809 
2810         IUri_Release(uri);
2811         IInternetProtocolEx_Release(protocolex);
2812 
2813         hres = pCreateUri(url, 0, 0, &uri);
2814         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2815 
2816         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2817         ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2818 
2819         if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2820             hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2821             ok(hres == S_OK, "Read failed: %08x\n", hres);
2822             hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2823             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2824             hres = IInternetProtocolEx_UnlockRequest(protocolex);
2825             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2826         }
2827 
2828         IUri_Release(uri);
2829         IInternetProtocolEx_Release(protocolex);
2830     }else {
2831         win_skip("Skipping file protocol StartEx tests\n");
2832     }
2833 
2834     IClassFactory_Release(factory);
2835 }
2836 
2837 static void test_file_protocol_fail(void)
2838 {
2839     IInternetProtocol *protocol;
2840     HRESULT hres;
2841 
2842     static const WCHAR index_url2[] =
2843         {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
2844 
2845     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2846             &IID_IInternetProtocol, (void**)&protocol);
2847     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2848     if(FAILED(hres))
2849         return;
2850 
2851     SET_EXPECT(GetBindInfo);
2852     expect_hrResult = MK_E_SYNTAX;
2853     hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
2854     ok(hres == MK_E_SYNTAX ||
2855        hres == E_INVALIDARG,
2856        "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres);
2857     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2858 
2859     SET_EXPECT(GetBindInfo);
2860     if(!(bindf & BINDF_FROMURLMON))
2861         SET_EXPECT(ReportProgress_DIRECTBIND);
2862     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2863     SET_EXPECT(ReportResult);
2864     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2865     hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
2866     ok(hres == INET_E_RESOURCE_NOT_FOUND,
2867             "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
2868     CHECK_CALLED(GetBindInfo);
2869     if(!(bindf & BINDF_FROMURLMON))
2870         CHECK_CALLED(ReportProgress_DIRECTBIND);
2871     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2872     CHECK_CALLED(ReportResult);
2873 
2874     IInternetProtocol_Release(protocol);
2875 
2876     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2877             &IID_IInternetProtocol, (void**)&protocol);
2878     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2879     if(FAILED(hres))
2880         return;
2881 
2882     SET_EXPECT(GetBindInfo);
2883     if(!(bindf & BINDF_FROMURLMON))
2884         SET_EXPECT(ReportProgress_DIRECTBIND);
2885     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2886     SET_EXPECT(ReportResult);
2887     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2888 
2889     hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
2890     ok(hres == INET_E_RESOURCE_NOT_FOUND,
2891             "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
2892     CHECK_CALLED(GetBindInfo);
2893     if(!(bindf & BINDF_FROMURLMON))
2894         CHECK_CALLED(ReportProgress_DIRECTBIND);
2895     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2896     CHECK_CALLED(ReportResult);
2897 
2898     SET_EXPECT(GetBindInfo);
2899     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
2900     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2901     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2902 
2903     SET_EXPECT(GetBindInfo);
2904     hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0);
2905     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2906     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2907 
2908     IInternetProtocol_Release(protocol);
2909 }
2910 
2911 static void test_file_protocol(void) {
2912     WCHAR buf[INTERNET_MAX_URL_LENGTH], file_name_buf[MAX_PATH];
2913     DWORD size;
2914     ULONG len;
2915     HANDLE file;
2916 
2917     static const WCHAR wszFile[] = {'f','i','l','e',':',0};
2918     static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
2919     static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
2920     static const WCHAR wszFile4[] = {'f','i','l','e',':','\\','\\',0};
2921     static const char html_doc[] = "<HTML></HTML>";
2922     static const WCHAR fragmentW[] = {'#','f','r','a','g',0};
2923 
2924     trace("Testing file protocol...\n");
2925     init_test(FILE_TEST, 0);
2926 
2927     SetLastError(0xdeadbeef);
2928     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2929             FILE_ATTRIBUTE_NORMAL, NULL);
2930     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
2931     if(file == INVALID_HANDLE_VALUE)
2932         return;
2933     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
2934     CloseHandle(file);
2935 
2936     file_name = wszIndexHtml;
2937     bindf = 0;
2938     test_file_protocol_url(index_url);
2939     bindf = BINDF_FROMURLMON;
2940     test_file_protocol_url(index_url);
2941     bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
2942     test_file_protocol_url(index_url);
2943 
2944     memcpy(buf, wszFile, sizeof(wszFile));
2945     len = sizeof(wszFile)/sizeof(WCHAR)-1;
2946     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2947     buf[len++] = '\\';
2948     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2949 
2950     file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
2951     bindf = 0;
2952     test_file_protocol_url(buf);
2953     bindf = BINDF_FROMURLMON;
2954     test_file_protocol_url(buf);
2955 
2956     memcpy(buf, wszFile2, sizeof(wszFile2));
2957     len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
2958     file_name_buf[len++] = '\\';
2959     memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2960     lstrcpyW(buf+sizeof(wszFile2)/sizeof(WCHAR)-1, file_name_buf);
2961     file_name = file_name_buf;
2962     bindf = 0;
2963     test_file_protocol_url(buf);
2964     bindf = BINDF_FROMURLMON;
2965     test_file_protocol_url(buf);
2966 
2967     buf[sizeof(wszFile2)/sizeof(WCHAR)] = '|';
2968     test_file_protocol_url(buf);
2969 
2970     memcpy(buf, wszFile3, sizeof(wszFile3));
2971     len = sizeof(wszFile3)/sizeof(WCHAR)-1;
2972     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2973     buf[len++] = '\\';
2974     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2975 
2976     file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
2977     bindf = 0;
2978     test_file_protocol_url(buf);
2979     bindf = BINDF_FROMURLMON;
2980     test_file_protocol_url(buf);
2981 
2982     memcpy(buf, wszFile4, sizeof(wszFile4));
2983     len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
2984     file_name_buf[len++] = '\\';
2985     memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2986     lstrcpyW(buf+sizeof(wszFile4)/sizeof(WCHAR)-1, file_name_buf);
2987     file_name = file_name_buf;
2988     bindf = 0;
2989     test_file_protocol_url(buf);
2990     bindf = BINDF_FROMURLMON;
2991     test_file_protocol_url(buf);
2992 
2993     buf[sizeof(wszFile4)/sizeof(WCHAR)] = '|';
2994     test_file_protocol_url(buf);
2995 
2996     /* Fragment part of URL is skipped if the file doesn't exist. */
2997     lstrcatW(buf, fragmentW);
2998     test_file_protocol_url(buf);
2999 
3000     /* Fragment part is considered a part of the file name, if the file exsists. */
3001     len = lstrlenW(file_name_buf);
3002     lstrcpyW(file_name_buf+len, fragmentW);
3003     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
3004             FILE_ATTRIBUTE_NORMAL, NULL);
3005     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
3006     WriteFile(file, "XXX", 3, &size, NULL);
3007     CloseHandle(file);
3008     file_name_buf[len] = 0;
3009 
3010     file_with_hash = TRUE;
3011     test_file_protocol_url(buf);
3012 
3013     DeleteFileW(wszIndexHtml);
3014     DeleteFileW(file_name_buf);
3015 
3016     bindf = 0;
3017     test_file_protocol_fail();
3018     bindf = BINDF_FROMURLMON;
3019     test_file_protocol_fail();
3020 }
3021 
3022 static void create_cache_entry(const WCHAR *urlw)
3023 {
3024     FILETIME now, tomorrow, yesterday;
3025     char file_path[MAX_PATH];
3026     BYTE content[1000];
3027     ULARGE_INTEGER li;
3028     const char *url;
3029     HANDLE file;
3030     DWORD size;
3031     unsigned i;
3032     BOOL res;
3033 
3034     BYTE cache_headers[] = "HTTP/1.1 200 OK\r\n\r\n";
3035 
3036     trace("Testing cache read...\n");
3037 
3038     url = w2a(urlw);
3039 
3040     for(i = 0; i < sizeof(content); i++)
3041         content[i] = '0' + (i%10);
3042 
3043     GetSystemTimeAsFileTime(&now);
3044     li.u.HighPart = now.dwHighDateTime;
3045     li.u.LowPart = now.dwLowDateTime;
3046     li.QuadPart += (LONGLONG)10000000 * 3600 * 24;
3047     tomorrow.dwHighDateTime = li.u.HighPart;
3048     tomorrow.dwLowDateTime = li.u.LowPart;
3049     li.QuadPart -= (LONGLONG)10000000 * 3600 * 24 * 2;
3050     yesterday.dwHighDateTime = li.u.HighPart;
3051     yesterday.dwLowDateTime = li.u.LowPart;
3052 
3053     res = CreateUrlCacheEntryA(url, sizeof(content), "", file_path, 0);
3054     ok(res, "CreateUrlCacheEntryA failed: %u\n", GetLastError());
3055 
3056     file = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
3057     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
3058 
3059     WriteFile(file, content, sizeof(content), &size, NULL);
3060     CloseHandle(file);
3061 
3062     res = CommitUrlCacheEntryA(url, file_path, tomorrow, yesterday, NORMAL_CACHE_ENTRY,
3063                                cache_headers, sizeof(cache_headers)-1, "", 0);
3064     ok(res, "CommitUrlCacheEntryA failed: %u\n", GetLastError());
3065 }
3066 
3067 static BOOL http_protocol_start(LPCWSTR url, BOOL use_iuri)
3068 {
3069     static BOOL got_user_agent = FALSE;
3070     IUri *uri = NULL;
3071     HRESULT hres;
3072 
3073     if(use_iuri && pCreateUri) {
3074         hres = pCreateUri(url, 0, 0, &uri);
3075         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
3076     }
3077 
3078     SET_EXPECT(GetBindInfo);
3079     if (!(bindf & BINDF_FROMURLMON))
3080         SET_EXPECT(ReportProgress_DIRECTBIND);
3081     if(!got_user_agent)
3082         SET_EXPECT(GetBindString_USER_AGENT);
3083     SET_EXPECT(GetBindString_ROOTDOC_URL);
3084     SET_EXPECT(GetBindString_ACCEPT_MIMES);
3085     SET_EXPECT(QueryService_HttpNegotiate);
3086     SET_EXPECT(BeginningTransaction);
3087     SET_EXPECT(GetRootSecurityId);
3088     if(http_post_test) {
3089         SET_EXPECT(GetBindString_POST_COOKIE);
3090         if(http_post_test == TYMED_ISTREAM)
3091             SET_EXPECT(Stream_Seek);
3092     }
3093     if(bind_from_cache) {
3094         SET_EXPECT(OnResponse);
3095         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
3096         SET_EXPECT(ReportData);
3097     }
3098 
3099     if(uri) {
3100         IInternetProtocolEx *protocolex;
3101 
3102         hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3103         ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3104 
3105         hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
3106         ok(hres == S_OK, "Start failed: %08x\n", hres);
3107 
3108         IInternetProtocolEx_Release(protocolex);
3109         IUri_Release(uri);
3110     }else {
3111         hres = IInternetProtocol_Start(async_protocol, url, &protocol_sink, &bind_info, 0, 0);
3112         ok(hres == S_OK, "Start failed: %08x\n", hres);
3113     }
3114     if(FAILED(hres))
3115         return FALSE;
3116 
3117     CHECK_CALLED(GetBindInfo);
3118     if (!(bindf & BINDF_FROMURLMON))
3119         CHECK_CALLED(ReportProgress_DIRECTBIND);
3120     if (!got_user_agent)
3121     {
3122         CHECK_CALLED(GetBindString_USER_AGENT);
3123         got_user_agent = TRUE;
3124     }
3125     CLEAR_CALLED(GetBindString_ROOTDOC_URL); /* New in IE11 */
3126     CHECK_CALLED(GetBindString_ACCEPT_MIMES);
3127     CHECK_CALLED(QueryService_HttpNegotiate);
3128     CHECK_CALLED(BeginningTransaction);
3129     /* GetRootSecurityId called on WinXP but not on Win98 */
3130     CLEAR_CALLED(GetRootSecurityId);
3131     if(http_post_test) {
3132         CHECK_CALLED(GetBindString_POST_COOKIE);
3133         if(http_post_test == TYMED_ISTREAM)
3134             CHECK_CALLED(Stream_Seek);
3135     }
3136     if(bind_from_cache) {
3137         CHECK_CALLED(OnResponse);
3138         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3139         CHECK_CALLED(ReportData);
3140     }
3141 
3142     return TRUE;
3143 }
3144 
3145 static void test_protocol_terminate(IInternetProtocol *protocol)
3146 {
3147     BYTE buf[3600];
3148     DWORD cb;
3149     HRESULT hres;
3150 
3151     hres = IInternetProtocol_LockRequest(protocol, 0);
3152     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
3153 
3154     hres = IInternetProtocol_Read(protocol, buf, 1, &cb);
3155     ok(hres == (test_abort ? S_OK : S_FALSE), "Read failed: %08x\n", hres);
3156 
3157     hres = IInternetProtocol_Terminate(protocol, 0);
3158     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3159 
3160     /* This wait is to give the internet handles being freed in Terminate
3161      * enough time to actually terminate in all cases. Internet handles
3162      * terminate asynchronously and native reuses the main InternetOpen
3163      * handle. The only case in which this seems to be necessary is on
3164      * wine with native wininet and urlmon, resulting in the next time
3165      * test_http_protocol_url being called the first data notification actually
3166      * being an extra last data notification from the previous connection
3167      * about once out of every ten times. */
3168     Sleep(100);
3169 
3170     hres = IInternetProtocol_UnlockRequest(protocol);
3171     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
3172 }
3173 
3174 /* is_first refers to whether this is the first call to this function
3175  * _for this url_ */
3176 static void test_http_protocol_url(LPCWSTR url, int prot, DWORD flags, DWORD tymed)
3177 {
3178     IInternetProtocolInfo *protocol_info;
3179     IClassFactory *factory;
3180     IUnknown *unk;
3181     HRESULT hres;
3182 
3183     init_test(prot, flags);
3184     http_url = url;
3185     http_post_test = tymed;
3186     if(flags & TEST_FROMCACHE)
3187         create_cache_entry(url);
3188 
3189     hres = CoGetClassObject(prot == HTTPS_TEST ? &CLSID_HttpSProtocol : &CLSID_HttpProtocol,
3190             CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3191     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3192     if(FAILED(hres))
3193         return;
3194 
3195     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3196     ok(hres == E_NOINTERFACE,
3197         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
3198         hres);
3199 
3200     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3201     ok(hres == S_OK, "Could not get IClassFactory interface\n");
3202     IUnknown_Release(unk);
3203     if(FAILED(hres))
3204         return;
3205 
3206     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3207                                         (void**)&async_protocol);
3208     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3209     if(SUCCEEDED(hres)) {
3210         BYTE buf[3600];
3211         DWORD cb;
3212         ULONG ref;
3213 
3214         test_priority(async_protocol);
3215 
3216         SET_EXPECT(ReportProgress_COOKIE_SENT);
3217         if(http_is_first) {
3218             SET_EXPECT(ReportProgress_FINDINGRESOURCE);
3219             SET_EXPECT(ReportProgress_CONNECTING);
3220         }
3221         SET_EXPECT(ReportProgress_SENDINGREQUEST);
3222         if(test_redirect && !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
3223             SET_EXPECT(ReportProgress_REDIRECTING);
3224         SET_EXPECT(ReportProgress_PROXYDETECTING);
3225         if(prot == HTTP_TEST)
3226             SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
3227         else
3228             SET_EXPECT(QueryService_HttpSecurity);
3229         if(!(bindf & BINDF_FROMURLMON)) {
3230             SET_EXPECT(OnResponse);
3231             SET_EXPECT(ReportProgress_RAWMIMETYPE);
3232             SET_EXPECT(ReportData);
3233         } else {
3234             SET_EXPECT(Switch);
3235         }
3236 
3237         if(!http_protocol_start(url, (flags & TEST_USEIURI) != 0)) {
3238             IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3239             IInternetProtocol_Release(async_protocol);
3240             return;
3241         }
3242 
3243         if(!direct_read && !test_abort && !bind_from_cache)
3244             SET_EXPECT(ReportResult);
3245 
3246         if(flags & TEST_DISABLEAUTOREDIRECT)
3247             expect_hrResult = INET_E_REDIRECT_FAILED;
3248         else if(test_abort)
3249             expect_hrResult = E_ABORT;
3250         else
3251             expect_hrResult = S_OK;
3252 
3253         if(direct_read) {
3254             SET_EXPECT(Switch);
3255             while(wait_for_switch) {
3256                 ok( WaitForSingleObject(event_continue, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3257                 CHECK_CALLED(Switch); /* Set in ReportData */
3258                 call_continue(&continue_protdata);
3259                 SetEvent(event_continue_done);
3260             }
3261         }else if(bind_from_cache) {
3262             BYTE buf[1500];
3263 
3264             hres = IInternetProtocol_Read(async_protocol, buf, 100, &cb);
3265             ok(hres == S_OK && cb == 100, "Read failed: %08x (%d bytes)\n", hres, cb);
3266 
3267             SET_EXPECT(ReportResult);
3268             hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3269             ok(hres == S_OK && cb == 900, "Read failed: %08x (%d bytes)\n", hres, cb);
3270             CHECK_CALLED(ReportResult);
3271 
3272             hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3273             ok(hres == S_FALSE && !cb, "Read failed: %08x (%d bytes)\n", hres, cb);
3274         }else {
3275             hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3276             ok((hres == E_PENDING && cb==0) ||
3277                (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3278 
3279             ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3280             if(bindf & BINDF_FROMURLMON)
3281                 CHECK_CALLED(Switch);
3282             else
3283                 CHECK_CALLED(ReportData);
3284             if(prot == HTTPS_TEST)
3285                 CLEAR_CALLED(QueryService_HttpSecurity);
3286 
3287             while(1) {
3288                 if(bindf & BINDF_FROMURLMON)
3289                     SET_EXPECT(Switch);
3290                 else
3291                     SET_EXPECT(ReportData);
3292                 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3293                 if(hres == E_PENDING) {
3294                     hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3295                     ok((hres == E_PENDING && cb==0) ||
3296                        (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3297                     ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3298                     if(bindf & BINDF_FROMURLMON)
3299                         CHECK_CALLED(Switch);
3300                     else
3301                         CHECK_CALLED(ReportData);
3302 
3303                     if(test_abort) {
3304                         HRESULT hres;
3305 
3306                         SET_EXPECT(ReportResult);
3307                         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3308                         ok(hres == S_OK, "Abort failed: %08x\n", hres);
3309                         CHECK_CALLED(ReportResult);
3310 
3311                         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3312                         ok(hres == INET_E_RESULT_DISPATCHED || hres == S_OK /* IE10 */, "Abort failed: %08x\n", hres);
3313                         break;
3314                     }
3315                 }else {
3316                     if(bindf & BINDF_FROMURLMON)
3317                         CHECK_NOT_CALLED(Switch);
3318                     else
3319                         CHECK_NOT_CALLED(ReportData);
3320                     if(cb == 0) break;
3321                 }
3322             }
3323             if(!test_abort) {
3324                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3325                 CHECK_CALLED(ReportResult);
3326             }
3327         }
3328         if(prot == HTTPS_TEST)
3329             CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3330 
3331         if (prot == HTTP_TEST || prot == HTTPS_TEST)
3332             CLEAR_CALLED(ReportProgress_COOKIE_SENT);
3333 
3334         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3335         ok(hres == INET_E_RESULT_DISPATCHED || hres == S_OK /* IE10 */, "Abort failed: %08x\n", hres);
3336 
3337         test_protocol_terminate(async_protocol);
3338 
3339         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3340         ok(hres == S_OK, "Abort failed: %08x\n", hres);
3341 
3342         ref = IInternetProtocol_Release(async_protocol);
3343         ok(!ref, "ref=%x\n", ref);
3344     }
3345 
3346     IClassFactory_Release(factory);
3347 
3348     if(flags & TEST_FROMCACHE) {
3349         BOOL res;
3350 
3351         res = DeleteUrlCacheEntryW(url);
3352         ok(res, "DeleteUrlCacheEntryA failed: %u\n", GetLastError());
3353     }
3354 }
3355 
3356 static void test_http_protocol(void)
3357 {
3358     static const WCHAR posttest_url[] =
3359         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3360          't','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3361     static const WCHAR redirect_url[] =
3362         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3363          't','e','s','t','s','/','r','e','d','i','r','e','c','t',0};
3364     static const WCHAR winetest_url[] =
3365         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3366          't','e','s','t','s','/','d','a','t','a','.','p','h','p',0};
3367     static const WCHAR empty_url[] =
3368         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3369          't','e','s','t','s','/','e','m','p','t','y','.','j','s',0};
3370     static const WCHAR cache_only_url[] =
3371         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3372          't','e','s','t','s','/','c','a','c','h','e','-','o','n','l','y',0};
3373 
3374 
3375     trace("Testing http protocol (not from urlmon)...\n");
3376     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
3377     test_http_protocol_url(winetest_url, HTTP_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3378 
3379     trace("Testing http protocol (from urlmon)...\n");
3380     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3381     test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3382 
3383     trace("Testing http protocol (to file)...\n");
3384     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE;
3385     test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3386 
3387     trace("Testing http protocol (post data)...\n");
3388     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3389     test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST, TYMED_HGLOBAL);
3390 
3391     trace("Testing http protocol (post data stream)...\n");
3392     test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST|TEST_ASYNCREQ, TYMED_ISTREAM);
3393 
3394     trace("Testing http protocol (direct read)...\n");
3395     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3396     test_http_protocol_url(winetest_url, HTTP_TEST, TEST_DIRECT_READ|TEST_USEIURI, TYMED_NULL);
3397 
3398     trace("Testing http protocol (redirected)...\n");
3399     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3400     test_http_protocol_url(redirect_url, HTTP_TEST, TEST_REDIRECT, TYMED_NULL);
3401 
3402     trace("Testing http protocol (redirected, disable auto redirect)...\n");
3403     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3404     test_http_protocol_url(redirect_url, HTTP_TEST, TEST_REDIRECT | TEST_DISABLEAUTOREDIRECT, TYMED_NULL);
3405 
3406     trace("Testing http protocol empty file...\n");
3407     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3408     test_http_protocol_url(empty_url, HTTP_TEST, TEST_EMPTY, TYMED_NULL);
3409 
3410     /* This is a bit ugly. We unconditionally disable this test on Wine. This won't work until we have
3411      * support for reading from cache via HTTP layer in wininet. Until then, Wine will fail badly, affecting
3412      * other, unrelated, tests. Working around it is not worth the trouble, we may simply make sure those
3413      * tests work on Windows and have them around for the future.
3414      */
3415     if(broken(1)) {
3416     trace("Testing http protocol (from cache)...\n");
3417     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3418     test_http_protocol_url(cache_only_url, HTTP_TEST, TEST_FROMCACHE, TYMED_NULL);
3419     }
3420 
3421     trace("Testing http protocol abort...\n");
3422     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3423     test_http_protocol_url(winetest_url, HTTP_TEST, TEST_ABORT, TYMED_NULL);
3424 
3425     test_early_abort(&CLSID_HttpProtocol);
3426     test_early_abort(&CLSID_HttpSProtocol);
3427 }
3428 
3429 static void test_https_protocol(void)
3430 {
3431     static const WCHAR https_winehq_url[] =
3432         {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3433          't','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
3434 
3435     trace("Testing https protocol (from urlmon)...\n");
3436     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3437     test_http_protocol_url(https_winehq_url, HTTPS_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3438 }
3439 
3440 
3441 static void test_ftp_protocol(void)
3442 {
3443     IInternetProtocolInfo *protocol_info;
3444     IClassFactory *factory;
3445     IUnknown *unk;
3446     BYTE buf[4096];
3447     ULONG ref;
3448     DWORD cb;
3449     HRESULT hres;
3450 
3451     static const WCHAR ftp_urlW[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
3452     '/','p','u','b','/','o','t','h','e','r','/',
3453     'w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0};
3454 
3455     trace("Testing ftp protocol...\n");
3456 
3457     init_test(FTP_TEST, 0);
3458 
3459     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3460     state = STATE_STARTDOWNLOADING;
3461     expect_hrResult = E_PENDING;
3462 
3463     hres = CoGetClassObject(&CLSID_FtpProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3464     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3465     if(FAILED(hres))
3466         return;
3467 
3468     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3469     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3470 
3471     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3472     ok(hres == S_OK, "Could not get IClassFactory interface\n");
3473     IUnknown_Release(unk);
3474     if(FAILED(hres))
3475         return;
3476 
3477     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3478                                         (void**)&async_protocol);
3479     IClassFactory_Release(factory);
3480     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3481 
3482     test_priority(async_protocol);
3483 
3484     SET_EXPECT(GetBindInfo);
3485     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
3486     SET_EXPECT(ReportProgress_CONNECTING);
3487     SET_EXPECT(ReportProgress_SENDINGREQUEST);
3488     SET_EXPECT(Switch);
3489 
3490     hres = IInternetProtocol_Start(async_protocol, ftp_urlW, &protocol_sink, &bind_info, 0, 0);
3491     ok(hres == S_OK, "Start failed: %08x\n", hres);
3492     CHECK_CALLED(GetBindInfo);
3493 
3494     SET_EXPECT(ReportResult);
3495 
3496     hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3497     ok((hres == E_PENDING && cb==0) ||
3498        (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3499 
3500     ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3501 
3502     while(1) {
3503         hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3504         if(hres == E_PENDING)
3505         {
3506             DWORD ret = WaitForSingleObject(event_complete, 90000);
3507             ok( ret == WAIT_OBJECT_0, "wait timed out\n" );
3508             if (ret != WAIT_OBJECT_0) break;
3509         }
3510         else
3511             if(cb == 0) break;
3512     }
3513 
3514     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3515     CHECK_CALLED(ReportResult);
3516     CHECK_CALLED(Switch);
3517 
3518     test_protocol_terminate(async_protocol);
3519 
3520     if(pCreateUri) {
3521         IInternetProtocolEx *protocolex;
3522 
3523         hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3524         ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3525         IInternetProtocolEx_Release(protocolex);
3526     }
3527 
3528     ref = IInternetProtocol_Release(async_protocol);
3529     ok(!ref, "ref=%d\n", ref);
3530 
3531     test_early_abort(&CLSID_FtpProtocol);
3532 }
3533 
3534 static void test_gopher_protocol(void)
3535 {
3536     IInternetProtocolInfo *protocol_info;
3537     IClassFactory *factory;
3538     IUnknown *unk;
3539     HRESULT hres;
3540 
3541     trace("Testing gopher protocol...\n");
3542 
3543     hres = CoGetClassObject(&CLSID_GopherProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3544     ok(hres == S_OK ||
3545        broken(hres == REGDB_E_CLASSNOTREG || hres == CLASS_E_CLASSNOTAVAILABLE), /* Gopher protocol has been removed as of Vista */
3546        "CoGetClassObject failed: %08x\n", hres);
3547     if(FAILED(hres))
3548         return;
3549 
3550     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3551     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3552 
3553     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3554     ok(hres == S_OK, "Could not get IClassFactory interface\n");
3555     IUnknown_Release(unk);
3556     if(FAILED(hres))
3557         return;
3558 
3559     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3560                                         (void**)&async_protocol);
3561     IClassFactory_Release(factory);
3562     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3563 
3564     test_priority(async_protocol);
3565 
3566     IInternetProtocol_Release(async_protocol);
3567 
3568     test_early_abort(&CLSID_GopherProtocol);
3569 }
3570 
3571 static void test_mk_protocol(void)
3572 {
3573     IInternetProtocolInfo *protocol_info;
3574     IInternetProtocol *protocol;
3575     IClassFactory *factory;
3576     IUnknown *unk;
3577     HRESULT hres;
3578 
3579     static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
3580                                        ':',':','/','t','e','s','t','.','h','t','m','l',0};
3581     static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
3582 
3583     trace("Testing mk protocol...\n");
3584     init_test(MK_TEST, 0);
3585 
3586     hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
3587             &IID_IUnknown, (void**)&unk);
3588     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3589 
3590     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3591     ok(hres == E_NOINTERFACE,
3592         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
3593         hres);
3594 
3595     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3596     ok(hres == S_OK, "Could not get IClassFactory interface\n");
3597     IUnknown_Release(unk);
3598     if(FAILED(hres))
3599         return;
3600 
3601     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3602                                         (void**)&protocol);
3603     IClassFactory_Release(factory);
3604     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3605 
3606     SET_EXPECT(GetBindInfo);
3607     hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
3608     ok(hres == MK_E_SYNTAX || hres == INET_E_INVALID_URL,
3609        "Start failed: %08x, expected MK_E_SYNTAX or INET_E_INVALID_URL\n", hres);
3610     CLEAR_CALLED(GetBindInfo);
3611 
3612     SET_EXPECT(GetBindInfo);
3613     SET_EXPECT(ReportProgress_DIRECTBIND);
3614     SET_EXPECT(ReportProgress_SENDINGREQUEST);
3615     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
3616     SET_EXPECT(ReportResult);
3617     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
3618 
3619     hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
3620     ok(hres == INET_E_RESOURCE_NOT_FOUND ||
3621        hres == INET_E_INVALID_URL, /* win2k3 */
3622        "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND or INET_E_INVALID_URL\n", hres);
3623 
3624     if (hres == INET_E_RESOURCE_NOT_FOUND) {
3625         CHECK_CALLED(GetBindInfo);
3626         CLEAR_CALLED(ReportProgress_DIRECTBIND);
3627         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
3628         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3629         CHECK_CALLED(ReportResult);
3630     }else {
3631         CLEAR_CALLED(GetBindInfo);
3632         CLEAR_CALLED(ReportProgress_DIRECTBIND);
3633         CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3634         CLEAR_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3635         CLEAR_CALLED(ReportResult);
3636     }
3637 
3638     IInternetProtocol_Release(protocol);
3639 }
3640 
3641 static void test_CreateBinding(void)
3642 {
3643     IInternetProtocol *protocol;
3644     IInternetPriority *priority;
3645     IInternetSession *session;
3646     IWinInetHttpInfo *http_info;
3647     IWinInetInfo *inet_info;
3648     LONG p;
3649     BYTE buf[1000];
3650     DWORD read;
3651     HRESULT hres;
3652 
3653     static const WCHAR test_url[] =
3654         {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
3655     static const WCHAR wsz_test[] = {'t','e','s','t',0};
3656 
3657     trace("Testing CreateBinding...\n");
3658     init_test(BIND_TEST, TEST_BINDING);
3659 
3660     hres = pCoInternetGetSession(0, &session, 0);
3661     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
3662 
3663     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
3664     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
3665 
3666     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3667     binding_protocol = protocol;
3668     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3669     ok(protocol != NULL, "protocol == NULL\n");
3670 
3671     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
3672     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
3673 
3674     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
3675     ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres);
3676 
3677     hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
3678     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3679     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
3680     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3681     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
3682     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3683 
3684     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
3685     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
3686 
3687     p = 0xdeadbeef;
3688     hres = IInternetPriority_GetPriority(priority, &p);
3689     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3690     ok(!p, "p=%d\n", p);
3691 
3692     ex_priority = 100;
3693     hres = IInternetPriority_SetPriority(priority, 100);
3694     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3695 
3696     p = 0xdeadbeef;
3697     hres = IInternetPriority_GetPriority(priority, &p);
3698     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3699     ok(p == 100, "p=%d\n", p);
3700 
3701     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3702     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3703 
3704     SET_EXPECT(QueryService_InternetProtocol);
3705     SET_EXPECT(CreateInstance);
3706     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
3707     SET_EXPECT(SetPriority);
3708     SET_EXPECT(Start);
3709 
3710     expect_hrResult = S_OK;
3711     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
3712     ok(hres == S_OK, "Start failed: %08x\n", hres);
3713 
3714     CHECK_CALLED(QueryService_InternetProtocol);
3715     CHECK_CALLED(CreateInstance);
3716     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
3717     CHECK_CALLED(SetPriority);
3718     CHECK_CALLED(Start);
3719 
3720     SET_EXPECT(QueryInterface_IWinInetInfo);
3721     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3722     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3723     CHECK_CALLED(QueryInterface_IWinInetInfo);
3724 
3725     SET_EXPECT(QueryInterface_IWinInetInfo);
3726     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3727     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3728     CHECK_CALLED(QueryInterface_IWinInetInfo);
3729 
3730     SET_EXPECT(QueryInterface_IWinInetHttpInfo);
3731     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
3732     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3733     CHECK_CALLED(QueryInterface_IWinInetHttpInfo);
3734 
3735     SET_EXPECT(Read);
3736     read = 0xdeadbeef;
3737     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3738     ok(hres == S_OK, "Read failed: %08x\n", hres);
3739     ok(read == 100, "read = %d\n", read);
3740     CHECK_CALLED(Read);
3741 
3742     SET_EXPECT(Read);
3743     read = 0xdeadbeef;
3744     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3745     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3746     ok(!read, "read = %d\n", read);
3747     CHECK_CALLED(Read);
3748 
3749     p = 0xdeadbeef;
3750     hres = IInternetPriority_GetPriority(priority, &p);
3751     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3752     ok(p == 100, "p=%d\n", p);
3753 
3754     hres = IInternetPriority_SetPriority(priority, 101);
3755     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3756 
3757     SET_EXPECT(Terminate);
3758     hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
3759     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3760     CHECK_CALLED(Terminate);
3761 
3762     SET_EXPECT(Continue);
3763     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
3764     ok(hres == S_OK, "Switch failed: %08x\n", hres);
3765     CHECK_CALLED(Continue);
3766 
3767     hres = IInternetProtocolSink_ReportProgress(binding_sink,
3768             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
3769     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
3770 
3771     hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
3772     ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres);
3773 
3774     hres = IInternetProtocolSink_ReportData(binding_sink, 0, 0, 0);
3775     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
3776 
3777     IInternetProtocolSink_Release(binding_sink);
3778     IInternetPriority_Release(priority);
3779     IInternetBindInfo_Release(prot_bind_info);
3780     IInternetProtocol_Release(protocol);
3781 
3782     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3783     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3784     ok(protocol != NULL, "protocol == NULL\n");
3785 
3786     hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3787     ok(hres == S_OK, "Abort failed: %08x\n", hres);
3788 
3789     hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
3790     ok(hres == S_OK, "Abort failed: %08x\n", hres);
3791 
3792     IInternetProtocol_Release(protocol);
3793 
3794     hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, wsz_test);
3795     ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
3796 
3797     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3798     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3799     ok(protocol != NULL, "protocol == NULL\n");
3800 
3801     SET_EXPECT(QueryService_InternetProtocol);
3802     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
3803     ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
3804     CHECK_CALLED(QueryService_InternetProtocol);
3805 
3806     IInternetProtocol_Release(protocol);
3807 
3808     IInternetSession_Release(session);
3809 }
3810 
3811 static void test_binding(int prot, DWORD grf_pi, DWORD test_flags)
3812 {
3813     IInternetProtocolEx *protocolex = NULL;
3814     IInternetProtocol *protocol;
3815     IInternetSession *session;
3816     IUri *uri = NULL;
3817     ULONG ref;
3818     HRESULT hres;
3819 
3820     pi = grf_pi;
3821 
3822     init_test(prot, test_flags|TEST_BINDING);
3823 
3824     hres = pCoInternetGetSession(0, &session, 0);
3825     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
3826 
3827     if(test_flags & TEST_EMULATEPROT) {
3828         hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, protocol_names[prot], 0, NULL, 0);
3829         ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
3830     }
3831 
3832     hres = IInternetSession_CreateBinding(session, NULL, binding_urls[prot], NULL, NULL, &protocol, 0);
3833     binding_protocol = protocol;
3834     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3835     ok(protocol != NULL, "protocol == NULL\n");
3836 
3837     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
3838     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
3839 
3840     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
3841     ok(hres == S_OK, "QueryInterface(IID_IInternetProtocolSink) failed: %08x\n", hres);
3842 
3843     if(test_flags & TEST_USEIURI) {
3844         hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3845         ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3846 
3847         hres = pCreateUri(binding_urls[prot], Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
3848         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
3849     }
3850 
3851     ex_priority = 0;
3852     SET_EXPECT(QueryService_InternetProtocol);
3853     SET_EXPECT(CreateInstance);
3854     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
3855     SET_EXPECT(SetPriority);
3856     if(impl_protex)
3857         SET_EXPECT(StartEx);
3858     else
3859         SET_EXPECT(Start);
3860 
3861     expect_hrResult = S_OK;
3862 
3863     if(protocolex) {
3864         hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, pi, 0);
3865         ok(hres == S_OK, "StartEx failed: %08x\n", hres);
3866     }else {
3867         hres = IInternetProtocol_Start(protocol, binding_urls[prot], &protocol_sink, &bind_info, pi, 0);
3868         ok(hres == S_OK, "Start failed: %08x\n", hres);
3869     }
3870 
3871     CHECK_CALLED(QueryService_InternetProtocol);
3872     CHECK_CALLED(CreateInstance);
3873     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
3874     CLEAR_CALLED(SetPriority); /* IE11 does not call it. */
3875     if(impl_protex)
3876         CHECK_CALLED(StartEx);
3877     else
3878         CHECK_CALLED(Start);
3879 
3880     if(protocolex)
3881         IInternetProtocolEx_Release(protocolex);
3882     if(uri)
3883         IUri_Release(uri);
3884 
3885     if(prot == HTTP_TEST || prot == HTTPS_TEST) {
3886         while(prot_state < 4) {
3887             ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3888             if(mimefilter_test && filtered_protocol) {
3889                 SET_EXPECT(Continue);
3890                 IInternetProtocol_Continue(filtered_protocol, pdata);
3891                 CHECK_CALLED(Continue);
3892             }else {
3893                 SET_EXPECT(Continue);
3894                 IInternetProtocol_Continue(protocol, pdata);
3895                 CHECK_CALLED(Continue);
3896             }
3897             if(test_abort && prot_state == 2) {
3898                 SET_EXPECT(Abort);
3899                 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3900                 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3901                 CHECK_CALLED(Abort);
3902 
3903                 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3904                 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3905                 SetEvent(event_complete2);
3906                 break;
3907             }
3908             SetEvent(event_complete2);
3909         }
3910         if(direct_read)
3911             CHECK_CALLED(ReportData); /* Set in ReportResult */
3912         ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3913     }else {
3914         if(mimefilter_test)
3915             SET_EXPECT(MimeFilter_LockRequest);
3916         else
3917             SET_EXPECT(LockRequest);
3918         hres = IInternetProtocol_LockRequest(protocol, 0);
3919         ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
3920         if(mimefilter_test)
3921             CHECK_CALLED(MimeFilter_LockRequest);
3922         else
3923             CHECK_CALLED(LockRequest);
3924 
3925         if(mimefilter_test)
3926             SET_EXPECT(MimeFilter_UnlockRequest);
3927         else
3928             SET_EXPECT(UnlockRequest);
3929         hres = IInternetProtocol_UnlockRequest(protocol);
3930         ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
3931         if(mimefilter_test)
3932             CHECK_CALLED(MimeFilter_UnlockRequest);
3933         else
3934             CHECK_CALLED(UnlockRequest);
3935     }
3936 
3937     if(mimefilter_test)
3938         SET_EXPECT(MimeFilter_Terminate);
3939     else
3940         SET_EXPECT(Terminate);
3941     hres = IInternetProtocol_Terminate(protocol, 0);
3942     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3943     if(mimefilter_test)
3944         CLEAR_CALLED(MimeFilter_Terminate);
3945     else
3946         CHECK_CALLED(Terminate);
3947 
3948     if(filtered_protocol)
3949         IInternetProtocol_Release(filtered_protocol);
3950     IInternetBindInfo_Release(prot_bind_info);
3951     IInternetProtocolSink_Release(binding_sink);
3952     ref = IInternetProtocol_Release(protocol);
3953     ok(!ref, "ref=%u, expected 0\n", ref);
3954 
3955     if(test_flags & TEST_EMULATEPROT) {
3956         hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, protocol_names[prot]);
3957         ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
3958     }
3959 
3960     IInternetSession_Release(session);
3961 }
3962 
3963 START_TEST(protocol)
3964 {
3965     HMODULE hurlmon;
3966 
3967     hurlmon = GetModuleHandleA("urlmon.dll");
3968     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
3969     pReleaseBindInfo = (void*) GetProcAddress(hurlmon, "ReleaseBindInfo");
3970     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
3971 
3972     if(!GetProcAddress(hurlmon, "CompareSecurityIds")) {
3973         win_skip("Various needed functions not present, too old IE\n");
3974         return;
3975     }
3976 
3977     if(!pCreateUri)
3978         win_skip("CreateUri not supported\n");
3979 
3980     OleInitialize(NULL);
3981 
3982     event_complete = CreateEventW(NULL, FALSE, FALSE, NULL);
3983     event_complete2 = CreateEventW(NULL, FALSE, FALSE, NULL);
3984     event_continue = CreateEventW(NULL, FALSE, FALSE, NULL);
3985     event_continue_done = CreateEventW(NULL, FALSE, FALSE, NULL);
3986     thread_id = GetCurrentThreadId();
3987 
3988     test_file_protocol();
3989     test_http_protocol();
3990     if(pCreateUri)
3991         test_https_protocol();
3992     else
3993         win_skip("Skipping https tests on too old platform\n");
3994     test_ftp_protocol();
3995     test_gopher_protocol();
3996     test_mk_protocol();
3997     test_CreateBinding();
3998 
3999     bindf &= ~BINDF_FROMURLMON;
4000     trace("Testing file binding (mime verification, emulate prot)...\n");
4001     test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
4002     trace("Testing http binding (mime verification, emulate prot)...\n");
4003     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
4004     trace("Testing its binding (mime verification, emulate prot)...\n");
4005     test_binding(ITS_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
4006     trace("Testing http binding (mime verification, emulate prot, short read, direct read)...\n");
4007     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_SHORT_READ|TEST_DIRECT_READ);
4008     trace("Testing http binding (mime verification, redirect, emulate prot)...\n");
4009     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_REDIRECT);
4010     trace("Testing http binding (mime verification, redirect, disable auto redirect, emulate prot)...\n");
4011     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_REDIRECT|TEST_DISABLEAUTOREDIRECT);
4012     trace("Testing file binding (mime verification, emulate prot, mime filter)...\n");
4013     test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
4014     trace("Testing http binding (mime verification, emulate prot, mime filter)...\n");
4015     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
4016     trace("Testing http binding (mime verification, emulate prot, mime filter, no mime)...\n");
4017     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER|TEST_NOMIME);
4018     trace("Testing http binding (mime verification, emulate prot, direct read)...\n");
4019     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_DIRECT_READ);
4020     trace("Testing http binding (mime verification, emulate prot, abort)...\n");
4021     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_ABORT);
4022     if(pCreateUri) {
4023         trace("Testing file binding (use IUri, mime verification, emulate prot)...\n");
4024         test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI);
4025         trace("Testing file binding (use IUri, impl StartEx, mime verification, emulate prot)...\n");
4026         test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI|TEST_IMPLPROTEX);
4027         trace("Testing file binding (impl StartEx, mime verification, emulate prot)...\n");
4028         test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_IMPLPROTEX);
4029     }
4030 
4031     CloseHandle(event_complete);
4032     CloseHandle(event_complete2);
4033     CloseHandle(event_continue);
4034     CloseHandle(event_continue_done);
4035 
4036     OleUninitialize();
4037 }
4038