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