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