d3drm: Implement IDirect3DRMMesh_AddGroup.
[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                     ok(hres == S_OK, "Read failed: %08x\n", hres);
945                     reported_all_data = TRUE;
946                 }else {
947                     if(!emulate_prot)
948                         CHECK_NOT_CALLED(ReportData2);
949                     CHECK_NOT_CALLED(ReportResult);
950                 }
951             }while(hres == S_OK);
952             if(hres == S_FALSE)
953                 wait_for_switch = FALSE;
954         }else {
955             CHECK_EXPECT(ReportData2);
956
957             ok(grfBSCF & BSCF_LASTDATANOTIFICATION, "grfBSCF = %08x\n", grfBSCF);
958
959             read = 0xdeadbeef;
960             if(emulate_prot)
961                 SET_EXPECT(Read2);
962             hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
963             if(emulate_prot)
964                 CHECK_CALLED(Read2);
965             ok(hres == S_FALSE, "Read returned: %08x, expected E_FALSE\n", hres);
966             ok(!read, "read = %d\n", read);
967         }
968     }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST
969             || tested_protocol == FTP_TEST)) {
970         if(empty_file)
971             CHECK_EXPECT2(ReportData);
972         else if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
973             CHECK_EXPECT(ReportData);
974         else if (http_post_test)
975             ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
976
977         if(empty_file) {
978             ok(!ulProgress, "ulProgress = %d\n", ulProgress);
979             ok(!ulProgressMax, "ulProgressMax = %d\n", ulProgressMax);
980         }else {
981             ok(ulProgress, "ulProgress == 0\n");
982         }
983
984         if(empty_file) {
985             ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION),
986                "grcfBSCF = %08x\n", grfBSCF);
987             first_data_notif = FALSE;
988         }else if(first_data_notif) {
989             ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
990                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
991                "grcfBSCF = %08x\n", grfBSCF);
992             first_data_notif = FALSE;
993         } else {
994             ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
995                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
996                || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
997                "grcfBSCF = %08x\n", grfBSCF);
998         }
999
1000         if(!(bindf & BINDF_FROMURLMON) &&
1001            !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
1002             if(state == STATE_CONNECTING) {
1003                 state = STATE_DOWNLOADING;
1004                 if(http_is_first) {
1005                     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1006                     CHECK_CALLED(ReportProgress_CONNECTING);
1007                 }
1008                 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1009                 CHECK_CALLED(OnResponse);
1010                 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
1011             }
1012             SetEvent(event_complete);
1013         }
1014     }else if(!read_report_data) {
1015         BYTE buf[1000];
1016         ULONG read;
1017         HRESULT hres;
1018
1019         CHECK_EXPECT(ReportData);
1020
1021         if(tested_protocol != BIND_TEST) {
1022             do {
1023                 if(mimefilter_test)
1024                     SET_EXPECT(MimeFilter_Read);
1025                 else if(rec_depth > 1)
1026                     SET_EXPECT(Read2);
1027                 else
1028                     SET_EXPECT(Read);
1029                 hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
1030                 if(mimefilter_test)
1031                     CHECK_CALLED(MimeFilter_Read);
1032                 else if(rec_depth > 1)
1033                     CHECK_CALLED(Read2);
1034                 else
1035                     CHECK_CALLED(Read);
1036             }while(hres == S_OK);
1037         }
1038     }
1039
1040     rec_depth--;
1041     return S_OK;
1042 }
1043
1044 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1045         DWORD dwError, LPCWSTR szResult)
1046 {
1047     CHECK_EXPECT(ReportResult);
1048
1049     if(tested_protocol == FTP_TEST)
1050         ok(hrResult == E_PENDING || hrResult == S_OK, "hrResult = %08x, expected E_PENDING or S_OK\n", hrResult);
1051     else
1052         ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
1053            hrResult, expect_hrResult);
1054     if(SUCCEEDED(hrResult) || tested_protocol == FTP_TEST || test_abort)
1055         ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
1056     else
1057         ok(dwError != ERROR_SUCCESS ||
1058            broken(tested_protocol == MK_TEST), /* WinME and NT4 */
1059            "dwError == ERROR_SUCCESS\n");
1060     ok(!szResult, "szResult != NULL\n");
1061
1062     if(direct_read)
1063         SET_EXPECT(ReportData); /* checked after main loop */
1064
1065     return S_OK;
1066 }
1067
1068 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
1069     ProtocolSink_QueryInterface,
1070     ProtocolSink_AddRef,
1071     ProtocolSink_Release,
1072     ProtocolSink_Switch,
1073     ProtocolSink_ReportProgress,
1074     ProtocolSink_ReportData,
1075     ProtocolSink_ReportResult
1076 };
1077
1078 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
1079
1080 static HRESULT WINAPI MimeProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
1081 {
1082     ok(0, "unexpected call\n");
1083     return E_NOTIMPL;
1084 }
1085
1086 static ULONG WINAPI MimeProtocolSink_AddRef(IInternetProtocolSink *iface)
1087 {
1088     return 2;
1089 }
1090
1091 static ULONG WINAPI MimeProtocolSink_Release(IInternetProtocolSink *iface)
1092 {
1093     return 1;
1094 }
1095
1096 static HRESULT WINAPI MimeProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
1097 {
1098     HRESULT hres;
1099
1100     CHECK_EXPECT(MimeFilter_Switch);
1101
1102     SET_EXPECT(Switch);
1103     hres = IInternetProtocolSink_Switch(filtered_sink, pProtocolData);
1104     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1105     CHECK_CALLED(Switch);
1106
1107     return S_OK;
1108 }
1109
1110 static HRESULT WINAPI MimeProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
1111         LPCWSTR szStatusText)
1112 {
1113     switch(ulStatusCode) {
1114     case BINDSTATUS_LOADINGMIMEHANDLER:
1115         /*
1116          * IE9 for some reason (bug?) calls this on mime handler's protocol sink instead of the
1117          * main protocol sink. We check ReportProgress_LOADINGMIMEHANDLER both here and in
1118          * ProtocolSink_ReportProgress to workaround it.
1119          */
1120         CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1121         ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
1122         break;
1123     default:
1124         ok(0, "Unexpected status code %d\n", ulStatusCode);
1125     }
1126
1127     return S_OK;
1128 }
1129
1130 static HRESULT WINAPI MimeProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
1131         ULONG ulProgress, ULONG ulProgressMax)
1132 {
1133     DWORD read = 0;
1134     BYTE buf[8192];
1135     HRESULT hres;
1136     BOOL report_mime = FALSE;
1137
1138     CHECK_EXPECT(MimeFilter_ReportData);
1139
1140     if(!filter_state && !no_mime) {
1141         SET_EXPECT(Read);
1142         hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
1143         if(tested_protocol == HTTP_TEST)
1144             ok(hres == S_OK || hres == E_PENDING || hres == S_FALSE, "Read failed: %08x\n", hres);
1145         else
1146             ok(hres == S_OK, "Read failed: %08x\n", hres);
1147         CHECK_CALLED(Read);
1148
1149         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1150         hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, text_htmlW);
1151         ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1152         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1153
1154         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1155         hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW);
1156         ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1157         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1158
1159         /* FIXME: test BINDSTATUS_CACHEFILENAMEAVAILABLE */
1160     }
1161
1162     if(no_mime && prot_read<200) {
1163         SET_EXPECT(Read);
1164     }else if(no_mime && prot_read<300) {
1165         report_mime = TRUE;
1166         SET_EXPECT(Read);
1167         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1168         SET_EXPECT(ReportData);
1169     }else if(!read_report_data) {
1170         SET_EXPECT(ReportData);
1171     }
1172     hres = IInternetProtocolSink_ReportData(filtered_sink, grfBSCF, ulProgress, ulProgressMax);
1173     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1174     if(no_mime && prot_read<=200) {
1175         CHECK_CALLED(Read);
1176     }else if(report_mime) {
1177         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1178         CHECK_CALLED(ReportData);
1179     }else if(!read_report_data) {
1180         CHECK_CALLED(ReportData);
1181     }
1182
1183     if(!filter_state)
1184         filter_state = 1;
1185
1186     return S_OK;
1187 }
1188
1189 static HRESULT WINAPI MimeProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1190         DWORD dwError, LPCWSTR szResult)
1191 {
1192     HRESULT hres;
1193
1194     CHECK_EXPECT(MimeFilter_ReportResult);
1195
1196     ok(hrResult == S_OK, "hrResult = %08x\n", hrResult);
1197     ok(dwError == ERROR_SUCCESS, "dwError = %u\n", dwError);
1198     ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1199
1200     SET_EXPECT(ReportResult);
1201     hres = IInternetProtocolSink_ReportResult(filtered_sink, hrResult, dwError, szResult);
1202     ok(SUCCEEDED(hres), "ReportResult failed: %08x\n", hres);
1203     CHECK_CALLED(ReportResult);
1204
1205     return S_OK;
1206 }
1207
1208 static IInternetProtocolSinkVtbl mime_protocol_sink_vtbl = {
1209     MimeProtocolSink_QueryInterface,
1210     MimeProtocolSink_AddRef,
1211     MimeProtocolSink_Release,
1212     MimeProtocolSink_Switch,
1213     MimeProtocolSink_ReportProgress,
1214     MimeProtocolSink_ReportData,
1215     MimeProtocolSink_ReportResult
1216 };
1217
1218 static IInternetProtocolSink mime_protocol_sink = { &mime_protocol_sink_vtbl };
1219
1220 static HRESULT QueryInterface(REFIID riid, void **ppv)
1221 {
1222     static const IID IID_undocumented = {0x58DFC7D0,0x5381,0x43E5,{0x9D,0x72,0x4C,0xDD,0xE4,0xCB,0x0F,0x1A}};
1223
1224     *ppv = NULL;
1225
1226     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
1227         *ppv = &protocol_sink;
1228     if(IsEqualGUID(&IID_IServiceProvider, riid))
1229         *ppv = &service_provider;
1230     if(IsEqualGUID(&IID_IUriContainer, riid))
1231         return E_NOINTERFACE; /* TODO */
1232
1233     /* NOTE: IE8 queries for undocumented {58DFC7D0-5381-43E5-9D72-4CDDE4CB0F1A} interface. */
1234     if(IsEqualGUID(&IID_undocumented, riid))
1235         return E_NOINTERFACE;
1236
1237     if(*ppv)
1238         return S_OK;
1239
1240     ok(0, "unexpected call %s\n", debugstr_guid(riid));
1241     return E_NOINTERFACE;
1242 }
1243
1244 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
1245 {
1246     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
1247         *ppv = iface;
1248         return S_OK;
1249     }
1250     return E_NOINTERFACE;
1251 }
1252
1253 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
1254 {
1255     return 2;
1256 }
1257
1258 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
1259 {
1260     return 1;
1261 }
1262
1263 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
1264 {
1265     DWORD cbSize;
1266
1267     CHECK_EXPECT(GetBindInfo);
1268
1269     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
1270     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
1271     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
1272
1273     *grfBINDF = bindf;
1274     if(binding_test)
1275         *grfBINDF |= BINDF_FROMURLMON;
1276     cbSize = pbindinfo->cbSize;
1277     memset(pbindinfo, 0, cbSize);
1278     pbindinfo->cbSize = cbSize;
1279
1280     if(http_post_test)
1281     {
1282         pbindinfo->cbstgmedData = sizeof(post_data)-1;
1283         pbindinfo->dwBindVerb = BINDVERB_POST;
1284         pbindinfo->stgmedData.tymed = http_post_test;
1285
1286         if(http_post_test == TYMED_HGLOBAL) {
1287             HGLOBAL data;
1288
1289             /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly */
1290             data = GlobalAlloc(GPTR, sizeof(post_data));
1291             memcpy(data, post_data, sizeof(post_data));
1292             U(pbindinfo->stgmedData).hGlobal = data;
1293         }else {
1294             IStream *post_stream;
1295             HGLOBAL data;
1296             HRESULT hres;
1297
1298             if(0) {
1299             /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly */
1300             data = GlobalAlloc(GPTR, sizeof(post_data));
1301             memcpy(data, post_data, sizeof(post_data));
1302             U(pbindinfo->stgmedData).hGlobal = data;
1303
1304             hres = CreateStreamOnHGlobal(data, FALSE, &post_stream);
1305             ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
1306
1307             U(pbindinfo->stgmedData).pstm =post_stream;/* &Stream; */
1308             }
1309             U(pbindinfo->stgmedData).pstm = &Stream;
1310         }
1311     }
1312
1313     return S_OK;
1314 }
1315
1316 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
1317         LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1318 {
1319     ok(ppwzStr != NULL, "ppwzStr == NULL\n");
1320     ok(pcElFetched != NULL, "pcElFetched == NULL\n");
1321
1322     switch(ulStringType) {
1323     case BINDSTRING_ACCEPT_MIMES:
1324         CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
1325         ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
1326         if(pcElFetched) {
1327             ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
1328             *pcElFetched = 1;
1329         }
1330         if(ppwzStr) {
1331             *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
1332             memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
1333         }
1334         return S_OK;
1335     case BINDSTRING_USER_AGENT:
1336         CHECK_EXPECT(GetBindString_USER_AGENT);
1337         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1338         if(pcElFetched) {
1339             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
1340             *pcElFetched = 1;
1341         }
1342         if(ppwzStr) {
1343             *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
1344             memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
1345         }
1346         return S_OK;
1347     case BINDSTRING_POST_COOKIE:
1348         CHECK_EXPECT(GetBindString_POST_COOKIE);
1349         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1350         if(pcElFetched)
1351             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
1352         return S_OK;
1353     case BINDSTRING_URL: {
1354         DWORD size;
1355
1356         CHECK_EXPECT(GetBindString_URL);
1357         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1358         ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
1359         *pcElFetched = 1;
1360
1361         size = (lstrlenW(binding_urls[tested_protocol])+1)*sizeof(WCHAR);
1362         *ppwzStr = CoTaskMemAlloc(size);
1363         memcpy(*ppwzStr, binding_urls[tested_protocol], size);
1364         return S_OK;
1365     }
1366     default:
1367         ok(0, "unexpected call\n");
1368     }
1369
1370     return E_NOTIMPL;
1371 }
1372
1373 static IInternetBindInfoVtbl bind_info_vtbl = {
1374     BindInfo_QueryInterface,
1375     BindInfo_AddRef,
1376     BindInfo_Release,
1377     BindInfo_GetBindInfo,
1378     BindInfo_GetBindString
1379 };
1380
1381 static IInternetBindInfo bind_info = { &bind_info_vtbl };
1382
1383 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1384                                                   REFIID riid, void **ppv)
1385 {
1386     ok(0, "unexpected call\n");
1387     return E_NOINTERFACE;
1388 }
1389
1390 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1391 {
1392     return 2;
1393 }
1394
1395 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1396 {
1397     return 1;
1398 }
1399
1400 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1401 {
1402     CHECK_EXPECT(SetPriority);
1403     ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
1404     return S_OK;
1405 }
1406
1407 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1408 {
1409     ok(0, "unexpected call\n");
1410     return E_NOTIMPL;
1411 }
1412
1413
1414 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1415     InternetPriority_QueryInterface,
1416     InternetPriority_AddRef,
1417     InternetPriority_Release,
1418     InternetPriority_SetPriority,
1419     InternetPriority_GetPriority
1420 };
1421
1422 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
1423
1424 static ULONG WINAPI Protocol_AddRef(IInternetProtocolEx *iface)
1425 {
1426     return 2;
1427 }
1428
1429 static ULONG WINAPI Protocol_Release(IInternetProtocolEx *iface)
1430 {
1431     return 1;
1432 }
1433
1434 static HRESULT WINAPI Protocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
1435         DWORD dwOptions)
1436 {
1437     HRESULT hres;
1438
1439     CHECK_EXPECT(Abort);
1440
1441     SET_EXPECT(ReportResult);
1442     hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1443     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1444     CHECK_CALLED(ReportResult);
1445
1446     return S_OK;
1447 }
1448
1449 static HRESULT WINAPI Protocol_Suspend(IInternetProtocolEx *iface)
1450 {
1451     ok(0, "unexpected call\n");
1452     return E_NOTIMPL;
1453 }
1454
1455 static HRESULT WINAPI Protocol_Resume(IInternetProtocolEx *iface)
1456 {
1457     ok(0, "unexpected call\n");
1458     return E_NOTIMPL;
1459 }
1460
1461 static HRESULT WINAPI Protocol_Seek(IInternetProtocolEx *iface,
1462         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1463 {
1464     ok(0, "unexpected call\n");
1465     return E_NOTIMPL;
1466 }
1467
1468 static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
1469 {
1470     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
1471         *ppv = iface;
1472         return S_OK;
1473     }
1474
1475     if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
1476         if(impl_protex) {
1477             *ppv = iface;
1478             return S_OK;
1479         }
1480         *ppv = NULL;
1481         return E_NOINTERFACE;
1482     }
1483
1484     if(IsEqualGUID(&IID_IInternetPriority, riid)) {
1485         *ppv = &InternetPriority;
1486         return S_OK;
1487     }
1488
1489     if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
1490         CHECK_EXPECT(QueryInterface_IWinInetInfo);
1491         *ppv = NULL;
1492         return E_NOINTERFACE;
1493     }
1494
1495     if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
1496         CHECK_EXPECT(QueryInterface_IWinInetHttpInfo);
1497         *ppv = NULL;
1498         return E_NOINTERFACE;
1499     }
1500
1501     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
1502     *ppv = NULL;
1503     return E_NOINTERFACE;
1504 }
1505
1506 static DWORD WINAPI thread_proc(PVOID arg)
1507 {
1508     HRESULT hres;
1509
1510     memset(&protocoldata, -1, sizeof(protocoldata));
1511
1512     prot_state = 0;
1513
1514     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1515     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1516             BINDSTATUS_FINDINGRESOURCE, hostW);
1517     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1518     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1519
1520     SET_EXPECT(ReportProgress_CONNECTING);
1521     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1522             BINDSTATUS_CONNECTING, winehq_ipW);
1523     CHECK_CALLED(ReportProgress_CONNECTING);
1524     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1525
1526     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1527     hres = IInternetProtocolSink_ReportProgress(binding_sink,
1528             BINDSTATUS_SENDINGREQUEST, NULL);
1529     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1530     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1531
1532     prot_state = 1;
1533     SET_EXPECT(Switch);
1534     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1535     CHECK_CALLED(Switch);
1536     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1537
1538     if(!short_read) {
1539         prot_state = 2;
1540         if(mimefilter_test)
1541             SET_EXPECT(MimeFilter_Switch);
1542         else
1543             SET_EXPECT(Switch);
1544         hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1545         ok(hres == S_OK, "Switch failed: %08x\n", hres);
1546         if(mimefilter_test)
1547             CHECK_CALLED(MimeFilter_Switch);
1548         else
1549             CHECK_CALLED(Switch);
1550
1551         if(test_abort) {
1552             SetEvent(event_complete);
1553             return 0;
1554         }
1555
1556         prot_state = 2;
1557         if(mimefilter_test)
1558             SET_EXPECT(MimeFilter_Switch);
1559         else
1560             SET_EXPECT(Switch);
1561         hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1562         ok(hres == S_OK, "Switch failed: %08x\n", hres);
1563         if(mimefilter_test)
1564             CHECK_CALLED(MimeFilter_Switch);
1565         else
1566             CHECK_CALLED(Switch);
1567
1568         prot_state = 3;
1569         if(mimefilter_test)
1570             SET_EXPECT(MimeFilter_Switch);
1571         else
1572             SET_EXPECT(Switch);
1573         hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1574         ok(hres == S_OK, "Switch failed: %08x\n", hres);
1575         if(mimefilter_test)
1576             CHECK_CALLED(MimeFilter_Switch);
1577         else
1578             CHECK_CALLED(Switch);
1579     }
1580
1581     SetEvent(event_complete);
1582
1583     return 0;
1584 }
1585
1586 static void protocol_start(IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD pi)
1587 {
1588     BINDINFO bindinfo, exp_bindinfo;
1589     DWORD cbindf = 0;
1590     HRESULT hres;
1591
1592     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
1593     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
1594     ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
1595     ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
1596     ok(!pi, "pi = %x\n", pi);
1597
1598     if(binding_test)
1599         ok(pOIProtSink == binding_sink, "pOIProtSink != binding_sink\n");
1600
1601     memset(&bindinfo, 0, sizeof(bindinfo));
1602     bindinfo.cbSize = sizeof(bindinfo);
1603     memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
1604     SET_EXPECT(GetBindInfo);
1605     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
1606     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
1607     CHECK_CALLED(GetBindInfo);
1608     ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
1609        cbindf, (bindf|BINDF_FROMURLMON));
1610     ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
1611     pReleaseBindInfo(&bindinfo);
1612
1613     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1614     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
1615     ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
1616     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1617
1618     if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
1619         IServiceProvider *service_provider;
1620         IHttpNegotiate *http_negotiate;
1621         IHttpNegotiate2 *http_negotiate2;
1622         LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
1623         LPWSTR additional_headers = NULL;
1624         BYTE sec_id[100];
1625         DWORD fetched = 0, size = 100;
1626         DWORD tid;
1627
1628         SET_EXPECT(GetBindString_USER_AGENT);
1629         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
1630                                                &ua, 1, &fetched);
1631         CHECK_CALLED(GetBindString_USER_AGENT);
1632         ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
1633         ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
1634         ok(ua != NULL, "ua =  %p\n", ua);
1635         ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", wine_dbgstr_w(ua));
1636         CoTaskMemFree(ua);
1637
1638         fetched = 256;
1639         SET_EXPECT(GetBindString_ACCEPT_MIMES);
1640         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
1641                                                accept_mimes, 256, &fetched);
1642         CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1643
1644         ok(hres == S_OK,
1645            "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
1646         ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
1647         ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", wine_dbgstr_w(accept_mimes[0]));
1648         CoTaskMemFree(accept_mimes[0]);
1649
1650         hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
1651                                                 (void**)&service_provider);
1652         ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
1653
1654         SET_EXPECT(QueryService_HttpNegotiate);
1655         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1656                 &IID_IHttpNegotiate, (void**)&http_negotiate);
1657         CHECK_CALLED(QueryService_HttpNegotiate);
1658         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1659
1660         SET_EXPECT(BeginningTransaction);
1661         hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
1662                                                    NULL, 0, &additional_headers);
1663         CHECK_CALLED(BeginningTransaction);
1664         IHttpNegotiate_Release(http_negotiate);
1665         ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
1666         ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
1667
1668         SET_EXPECT(QueryService_HttpNegotiate);
1669         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
1670                 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
1671         CHECK_CALLED(QueryService_HttpNegotiate);
1672         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1673
1674         size = 512;
1675         SET_EXPECT(GetRootSecurityId);
1676         hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
1677         CHECK_CALLED(GetRootSecurityId);
1678         IHttpNegotiate2_Release(http_negotiate2);
1679         ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
1680         ok(size == 13, "size=%d\n", size);
1681
1682         IServiceProvider_Release(service_provider);
1683
1684         CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
1685         return;
1686     }
1687
1688     SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1689     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
1690             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1691     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1692     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1693
1694     if(mimefilter_test) {
1695         SET_EXPECT(MimeFilter_CreateInstance);
1696         SET_EXPECT(MimeFilter_Start);
1697         SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1698     }
1699     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1700     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
1701             mimefilter_test ? pjpegW : (expect_wsz = text_htmlW));
1702     ok(hres == S_OK,
1703        "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
1704     if(mimefilter_test) {
1705         CHECK_CALLED(MimeFilter_CreateInstance);
1706         CHECK_CALLED(MimeFilter_Start);
1707         CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1708         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1709     }else {
1710         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1711     }
1712
1713     if(mimefilter_test)
1714         SET_EXPECT(MimeFilter_ReportData);
1715     else
1716         SET_EXPECT(ReportData);
1717     hres = IInternetProtocolSink_ReportData(pOIProtSink,
1718             BSCF_FIRSTDATANOTIFICATION | (tested_protocol == ITS_TEST ? BSCF_DATAFULLYAVAILABLE : BSCF_LASTDATANOTIFICATION),
1719             13, 13);
1720     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1721     if(mimefilter_test)
1722         CHECK_CALLED(MimeFilter_ReportData);
1723     else
1724         CHECK_CALLED(ReportData);
1725
1726     if(tested_protocol == ITS_TEST) {
1727         SET_EXPECT(ReportData);
1728         hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
1729         ok(hres == S_OK, "ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres);
1730         CHECK_CALLED(ReportData);
1731     }
1732
1733     if(tested_protocol == BIND_TEST) {
1734         hres = IInternetProtocol_Terminate(binding_protocol, 0);
1735         ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
1736     }
1737
1738     if(mimefilter_test)
1739         SET_EXPECT(MimeFilter_ReportResult);
1740     else
1741         SET_EXPECT(ReportResult);
1742     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
1743     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1744     if(mimefilter_test)
1745         CHECK_CALLED(MimeFilter_ReportResult);
1746     else
1747         CHECK_CALLED(ReportResult);
1748 }
1749
1750 static HRESULT WINAPI ProtocolEmul_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
1751         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1752         DWORD grfPI, HANDLE_PTR dwReserved)
1753 {
1754     CHECK_EXPECT(Start);
1755
1756     ok(!dwReserved, "dwReserved = %lx\n", dwReserved);
1757     protocol_start(pOIProtSink, pOIBindInfo, grfPI);
1758     return S_OK;
1759 }
1760
1761 static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocolEx *iface,
1762         PROTOCOLDATA *pProtocolData)
1763 {
1764     DWORD bscf = 0, pr;
1765     HRESULT hres;
1766
1767     CHECK_EXPECT(Continue);
1768
1769     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
1770     if(!pProtocolData || tested_protocol == BIND_TEST)
1771         return S_OK;
1772     if(binding_test) {
1773         ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
1774         ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
1775            pProtocolData->grfFlags, protocoldata.grfFlags );
1776         ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
1777            pProtocolData->dwState, protocoldata.dwState );
1778         ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
1779            pProtocolData->pData, protocoldata.pData );
1780         ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
1781            pProtocolData->cbData, protocoldata.cbData );
1782     }
1783
1784     switch(prot_state) {
1785     case 1: {
1786         IServiceProvider *service_provider;
1787         IHttpNegotiate *http_negotiate;
1788         static WCHAR header[] = {'?',0};
1789
1790         hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
1791                                                     (void**)&service_provider);
1792         ok(hres == S_OK, "Could not get IServiceProvicder\n");
1793
1794         SET_EXPECT(QueryService_HttpNegotiate);
1795         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1796                                              &IID_IHttpNegotiate, (void**)&http_negotiate);
1797         IServiceProvider_Release(service_provider);
1798         CHECK_CALLED(QueryService_HttpNegotiate);
1799         ok(hres == S_OK, "Could not get IHttpNegotiate\n");
1800
1801         SET_EXPECT(OnResponse);
1802         hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
1803         IHttpNegotiate_Release(http_negotiate);
1804         CHECK_CALLED(OnResponse);
1805         IHttpNegotiate_Release(http_negotiate);
1806         ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
1807
1808         if(mimefilter_test) {
1809             SET_EXPECT(MimeFilter_CreateInstance);
1810             SET_EXPECT(MimeFilter_Start);
1811             SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1812         }else if(!(pi & PI_MIMEVERIFICATION)) {
1813             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1814         }
1815         hres = IInternetProtocolSink_ReportProgress(binding_sink,
1816                 BINDSTATUS_MIMETYPEAVAILABLE, mimefilter_test ? pjpegW : text_htmlW);
1817         if(mimefilter_test) {
1818             CHECK_CALLED(MimeFilter_CreateInstance);
1819             CHECK_CALLED(MimeFilter_Start);
1820             CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1821         }else if(!(pi & PI_MIMEVERIFICATION)) {
1822             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1823         }
1824         ok(hres == S_OK,
1825            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
1826
1827         bscf |= BSCF_FIRSTDATANOTIFICATION;
1828         break;
1829     }
1830     case 2:
1831     case 3:
1832         bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
1833         break;
1834     }
1835
1836     pr = prot_read;
1837     if(mimefilter_test)
1838         SET_EXPECT(MimeFilter_ReportData);
1839     if((!mimefilter_test || no_mime) && (pi & PI_MIMEVERIFICATION)) {
1840         if(pr < 200)
1841             SET_EXPECT(Read); /* checked in ReportData for short_read */
1842         if(pr == 200) {
1843             if(!mimefilter_test)
1844                 SET_EXPECT(Read); /* checked in BINDSTATUS_MIMETYPEAVAILABLE or ReportData */
1845             SET_EXPECT(GetBindInfo);
1846             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1847         }
1848         if(pr >= 200)
1849             SET_EXPECT(ReportData);
1850     }else {
1851         SET_EXPECT(ReportData);
1852     }
1853
1854     hres = IInternetProtocolSink_ReportData(binding_sink, bscf, pr, 400);
1855     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1856
1857     if(mimefilter_test) {
1858         SET_EXPECT(MimeFilter_ReportData);
1859     }else if(pi & PI_MIMEVERIFICATION) {
1860         if(!short_read && pr < 200)
1861             CHECK_CALLED(Read);
1862         if(pr == 200) {
1863             CLEAR_CALLED(GetBindInfo); /* IE9 */
1864             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1865         }
1866     }else {
1867         CHECK_CALLED(ReportData);
1868     }
1869
1870     if(prot_state == 3)
1871         prot_state = 4;
1872
1873     return S_OK;
1874 }
1875
1876 static HRESULT WINAPI ProtocolEmul_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
1877 {
1878     CHECK_EXPECT(Terminate);
1879     ok(!dwOptions, "dwOptions=%d\n", dwOptions);
1880     return S_OK;
1881 }
1882
1883 static HRESULT WINAPI ProtocolEmul_Read(IInternetProtocolEx *iface, void *pv,
1884         ULONG cb, ULONG *pcbRead)
1885 {
1886     if(read_report_data)
1887         CHECK_EXPECT2(Read2);
1888
1889     if(mimefilter_test || short_read) {
1890         if(!read_report_data)
1891             CHECK_EXPECT2(Read);
1892     }else if((pi & PI_MIMEVERIFICATION)) {
1893         if(!read_report_data)
1894             CHECK_EXPECT2(Read);
1895
1896         if(prot_read < 300) {
1897             ok(pv != expect_pv, "pv == expect_pv\n");
1898             if(prot_read < 300)
1899                 ok(cb == 2048-prot_read, "cb=%d\n", cb);
1900             else
1901                 ok(cb == 700, "cb=%d\n", cb);
1902         }else {
1903             ok(expect_pv <= pv && (BYTE*)pv < (BYTE*)expect_pv + cb, "pv != expect_pv\n");
1904         }
1905     }else {
1906         if(!read_report_data)
1907             CHECK_EXPECT(Read);
1908
1909         ok(pv == expect_pv, "pv != expect_pv\n");
1910         ok(cb == 1000, "cb=%d\n", cb);
1911         ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
1912     }
1913     ok(pcbRead != NULL, "pcbRead == NULL\n");
1914
1915     if(prot_state == 3 || (short_read && prot_state != 4)) {
1916         HRESULT hres;
1917
1918         prot_state = 4;
1919         if(short_read) {
1920             SET_EXPECT(Read2); /* checked in BINDSTATUS_MIMETYPEAVAILABLE */
1921             SET_EXPECT(GetBindInfo);
1922             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1923         }
1924         if(mimefilter_test)
1925             SET_EXPECT(MimeFilter_ReportData);
1926         else if(direct_read)
1927             SET_EXPECT(ReportData2);
1928         read_report_data++;
1929         hres = IInternetProtocolSink_ReportData(binding_sink,
1930                 BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION, 0, 0);
1931         read_report_data--;
1932         ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1933         if(short_read) {
1934             CLEAR_CALLED(GetBindInfo); /* IE9 */
1935             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1936         }
1937         if(mimefilter_test)
1938             CHECK_CALLED(MimeFilter_ReportData);
1939         else if(direct_read)
1940             CHECK_CALLED(ReportData2);
1941
1942         if(mimefilter_test)
1943             SET_EXPECT(MimeFilter_ReportResult);
1944         else
1945             SET_EXPECT(ReportResult);
1946         hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1947         ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1948         if(mimefilter_test)
1949             CHECK_CALLED(MimeFilter_ReportResult);
1950         else
1951             CHECK_CALLED(ReportResult);
1952
1953         if(cb > 100)
1954             cb = 100;
1955         memset(pv, 'x', cb);
1956         if(cb>6)
1957             memcpy(pv, "gif87a", 6);
1958         prot_read += *pcbRead = cb;
1959         return S_OK;
1960     }if(prot_state == 4) {
1961         *pcbRead = 0;
1962         return S_FALSE;
1963     }
1964
1965     if((async_read_pending = !async_read_pending)) {
1966         *pcbRead = 0;
1967         return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
1968     }
1969
1970     if(cb > 100)
1971         cb = 100;
1972     memset(pv, 'x', cb);
1973     if(cb>6)
1974         memcpy(pv, "gif87a", 6);
1975     prot_read += *pcbRead = cb;
1976     return S_OK;
1977 }
1978
1979 static HRESULT WINAPI ProtocolEmul_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
1980 {
1981     CHECK_EXPECT(LockRequest);
1982     ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
1983     return S_OK;
1984 }
1985
1986 static HRESULT WINAPI ProtocolEmul_UnlockRequest(IInternetProtocolEx *iface)
1987 {
1988     CHECK_EXPECT(UnlockRequest);
1989     return S_OK;
1990 }
1991
1992 static HRESULT WINAPI ProtocolEmul_StartEx(IInternetProtocolEx *iface, IUri *pUri,
1993         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1994         DWORD grfPI, HANDLE *dwReserved)
1995 {
1996     CHECK_EXPECT(StartEx);
1997     ok(!dwReserved, "dwReserved = %p\n", dwReserved);
1998     protocol_start(pOIProtSink, pOIBindInfo, grfPI);
1999     return S_OK;
2000 }
2001
2002 static const IInternetProtocolExVtbl ProtocolVtbl = {
2003     ProtocolEmul_QueryInterface,
2004     Protocol_AddRef,
2005     Protocol_Release,
2006     ProtocolEmul_Start,
2007     ProtocolEmul_Continue,
2008     Protocol_Abort,
2009     ProtocolEmul_Terminate,
2010     Protocol_Suspend,
2011     Protocol_Resume,
2012     ProtocolEmul_Read,
2013     Protocol_Seek,
2014     ProtocolEmul_LockRequest,
2015     ProtocolEmul_UnlockRequest,
2016     ProtocolEmul_StartEx
2017 };
2018
2019 static IInternetProtocolEx Protocol = { &ProtocolVtbl };
2020
2021 static HRESULT WINAPI MimeProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
2022 {
2023     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
2024         *ppv = iface;
2025         return S_OK;
2026     }
2027
2028     if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
2029         *ppv = &mime_protocol_sink;
2030         return S_OK;
2031     }
2032
2033     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
2034     *ppv = NULL;
2035     return E_NOINTERFACE;
2036 }
2037
2038 static HRESULT WINAPI MimeProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
2039         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2040         DWORD grfPI, HANDLE_PTR dwReserved)
2041 {
2042     PROTOCOLFILTERDATA *data;
2043     LPOLESTR url_str = NULL;
2044     DWORD fetched = 0;
2045     BINDINFO bindinfo;
2046     DWORD cbindf = 0;
2047     HRESULT hres;
2048
2049     CHECK_EXPECT(MimeFilter_Start);
2050
2051     ok(!lstrcmpW(szUrl, pjpegW), "wrong url %s\n", wine_dbgstr_w(szUrl));
2052     ok(grfPI == (PI_FILTER_MODE|PI_FORCE_ASYNC), "grfPI=%x, expected PI_FILTER_MODE|PI_FORCE_ASYNC\n", grfPI);
2053     ok(dwReserved, "dwReserved == 0\n");
2054     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
2055     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
2056
2057     if(binding_test) {
2058         ok(pOIProtSink != binding_sink, "pOIProtSink == protocol_sink\n");
2059         ok(pOIBindInfo == prot_bind_info, "pOIBindInfo != bind_info\n");
2060     }else {
2061         ok(pOIProtSink == &protocol_sink, "pOIProtSink != protocol_sink\n");
2062         ok(pOIBindInfo == &bind_info, "pOIBindInfo != bind_info\n");
2063     }
2064
2065     data = (void*)dwReserved;
2066     ok(data->cbSize == sizeof(*data), "data->cbSize = %d\n", data->cbSize);
2067     ok(!data->pProtocolSink, "data->pProtocolSink != NULL\n");
2068     ok(data->pProtocol != NULL, "data->pProtocol == NULL\n");
2069     ok(!data->pUnk, "data->pUnk != NULL\n");
2070     ok(!data->dwFilterFlags, "data->dwProtocolFlags = %x\n", data->dwFilterFlags);
2071     if(binding_test) {
2072         IInternetProtocolSink *prot_sink;
2073
2074         IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocolSink, (void**)&prot_sink);
2075         ok(prot_sink == pOIProtSink, "QI(data->pProtocol, IID_IInternetProtocolSink) != pOIProtSink\n");
2076         IInternetProtocolSink_Release(prot_sink);
2077
2078         ok(data->pProtocol != binding_protocol, "data->pProtocol == binding_protocol\n");
2079
2080         filtered_protocol = data->pProtocol;
2081         IInternetProtocol_AddRef(filtered_protocol);
2082     }else {
2083         IInternetProtocol *prot;
2084
2085         IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocol, (void**)&prot);
2086         ok(prot == async_protocol, "QI(data->pProtocol, IID_IInternetProtocol) != async_protocol\n");
2087         IInternetProtocol_Release(prot);
2088
2089         ok(data->pProtocol != async_protocol, "data->pProtocol == async_protocol\n");
2090     }
2091
2092     filtered_sink = pOIProtSink;
2093
2094     SET_EXPECT(ReportProgress_DECODING);
2095     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DECODING, pjpegW);
2096     ok(hres == S_OK, "ReportProgress(BINDSTATUS_DECODING) failed: %08x\n", hres);
2097     CHECK_CALLED(ReportProgress_DECODING);
2098
2099     SET_EXPECT(GetBindInfo);
2100     memset(&bindinfo, 0, sizeof(bindinfo));
2101     bindinfo.cbSize = sizeof(bindinfo);
2102     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
2103     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
2104     ok(cbindf == (bindf|BINDF_FROMURLMON), "cbindf = %x, expected %x\n", cbindf, bindf);
2105     CHECK_CALLED(GetBindInfo);
2106
2107     SET_EXPECT(GetBindString_URL);
2108     hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_URL, &url_str, 1, &fetched);
2109     ok(hres == S_OK, "GetBindString(BINDSTRING_URL) failed: %08x\n", hres);
2110     ok(fetched == 1, "fetched = %d\n", fetched);
2111     ok(!lstrcmpW(url_str, binding_urls[tested_protocol]), "wrong url_str %s\n", wine_dbgstr_w(url_str));
2112     CoTaskMemFree(url_str);
2113     CHECK_CALLED(GetBindString_URL);
2114
2115     return S_OK;
2116 }
2117
2118 static HRESULT WINAPI Protocol_Continue(IInternetProtocolEx *iface,
2119         PROTOCOLDATA *pProtocolData)
2120 {
2121     CHECK_EXPECT(MimeFilter_Continue);
2122     return E_NOTIMPL;
2123 }
2124
2125 static HRESULT WINAPI MimeProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2126 {
2127     HRESULT hres;
2128
2129     CHECK_EXPECT(MimeFilter_Terminate);
2130
2131     ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2132
2133     SET_EXPECT(Terminate);
2134     hres = IInternetProtocol_Terminate(filtered_protocol, dwOptions);
2135     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2136     CHECK_CALLED(Terminate);
2137
2138     return S_OK;
2139 }
2140
2141 static HRESULT WINAPI MimeProtocol_Read(IInternetProtocolEx *iface, void *pv,
2142         ULONG cb, ULONG *pcbRead)
2143 {
2144     BYTE buf[2096];
2145     DWORD read = 0;
2146     HRESULT hres;
2147
2148     CHECK_EXPECT(MimeFilter_Read);
2149
2150     ok(pv != NULL, "pv == NULL\n");
2151     ok(cb != 0, "cb == 0\n");
2152     ok(pcbRead != NULL, "pcbRead == NULL\n");
2153
2154     if(read_report_data)
2155         SET_EXPECT(Read2);
2156     else
2157         SET_EXPECT(Read);
2158     hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
2159     ok(hres == S_OK || hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
2160     if(read_report_data)
2161         CHECK_CALLED(Read2);
2162     else
2163         CHECK_CALLED(Read);
2164
2165     if(pcbRead) {
2166         ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
2167         *pcbRead = read;
2168     }
2169
2170     memset(pv, 'x', read);
2171     return hres;
2172 }
2173
2174 static HRESULT WINAPI MimeProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2175 {
2176     HRESULT hres;
2177
2178     CHECK_EXPECT(MimeFilter_LockRequest);
2179
2180     ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2181
2182     SET_EXPECT(LockRequest);
2183     hres = IInternetProtocol_LockRequest(filtered_protocol, dwOptions);
2184     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2185     CHECK_CALLED(LockRequest);
2186
2187     return S_OK;
2188 }
2189
2190 static HRESULT WINAPI MimeProtocol_UnlockRequest(IInternetProtocolEx *iface)
2191 {
2192     HRESULT hres;
2193
2194     CHECK_EXPECT(MimeFilter_UnlockRequest);
2195
2196     SET_EXPECT(UnlockRequest);
2197     hres = IInternetProtocol_UnlockRequest(filtered_protocol);
2198     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2199     CHECK_CALLED(UnlockRequest);
2200
2201     return S_OK;
2202 }
2203
2204 static const IInternetProtocolExVtbl MimeProtocolVtbl = {
2205     MimeProtocol_QueryInterface,
2206     Protocol_AddRef,
2207     Protocol_Release,
2208     MimeProtocol_Start,
2209     Protocol_Continue,
2210     Protocol_Abort,
2211     MimeProtocol_Terminate,
2212     Protocol_Suspend,
2213     Protocol_Resume,
2214     MimeProtocol_Read,
2215     Protocol_Seek,
2216     MimeProtocol_LockRequest,
2217     MimeProtocol_UnlockRequest
2218 };
2219
2220 static IInternetProtocolEx MimeProtocol = { &MimeProtocolVtbl };
2221
2222 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2223 {
2224     ok(0, "unexpected call\n");
2225     return E_NOINTERFACE;
2226 }
2227
2228 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
2229 {
2230     return 2;
2231 }
2232
2233 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
2234 {
2235     return 1;
2236 }
2237
2238 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
2239                                         REFIID riid, void **ppv)
2240 {
2241     CHECK_EXPECT(CreateInstance);
2242
2243     ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
2244     ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
2245     ok(ppv != NULL, "ppv == NULL\n");
2246
2247     *ppv = &Protocol;
2248     return S_OK;
2249 }
2250
2251 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
2252 {
2253     ok(0, "unexpected call\n");
2254     return S_OK;
2255 }
2256
2257 static const IClassFactoryVtbl ClassFactoryVtbl = {
2258     ClassFactory_QueryInterface,
2259     ClassFactory_AddRef,
2260     ClassFactory_Release,
2261     ClassFactory_CreateInstance,
2262     ClassFactory_LockServer
2263 };
2264
2265 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
2266
2267 static HRESULT WINAPI MimeFilter_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
2268 {
2269     CHECK_EXPECT(MimeFilter_CreateInstance);
2270
2271     ok(!outer, "outer = %p\n", outer);
2272     ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", debugstr_guid(riid));
2273
2274     *ppv = &MimeProtocol;
2275     return S_OK;
2276 }
2277
2278 static const IClassFactoryVtbl MimeFilterCFVtbl = {
2279     ClassFactory_QueryInterface,
2280     ClassFactory_AddRef,
2281     ClassFactory_Release,
2282     MimeFilter_CreateInstance,
2283     ClassFactory_LockServer
2284 };
2285
2286 static IClassFactory mimefilter_cf = { &MimeFilterCFVtbl };
2287
2288 #define TEST_BINDING     0x0001
2289 #define TEST_FILTER      0x0002
2290 #define TEST_FIRST_HTTP  0x0004
2291 #define TEST_DIRECT_READ 0x0008
2292 #define TEST_POST        0x0010
2293 #define TEST_EMULATEPROT 0x0020
2294 #define TEST_SHORT_READ  0x0040
2295 #define TEST_REDIRECT    0x0080
2296 #define TEST_ABORT       0x0100
2297 #define TEST_ASYNCREQ    0x0200
2298 #define TEST_USEIURI     0x0400
2299 #define TEST_IMPLPROTEX  0x0800
2300 #define TEST_EMPTY       0x1000
2301 #define TEST_NOMIME      0x2000
2302
2303 static void register_filter(BOOL do_register)
2304 {
2305     IInternetSession *session;
2306     HRESULT hres;
2307
2308     hres = pCoInternetGetSession(0, &session, 0);
2309     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2310
2311     if(do_register) {
2312         hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, pjpegW);
2313         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2314         hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, gifW);
2315         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2316     }else {
2317         hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, pjpegW);
2318         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2319         hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, gifW);
2320         ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2321     }
2322
2323     IInternetSession_Release(session);
2324 }
2325
2326 static void init_test(int prot, DWORD flags)
2327 {
2328     tested_protocol = prot;
2329     binding_test = (flags & TEST_BINDING) != 0;
2330     first_data_notif = TRUE;
2331     prot_read = 0;
2332     prot_state = 0;
2333     async_read_pending = TRUE;
2334     mimefilter_test = (flags & TEST_FILTER) != 0;
2335     no_mime = (flags & TEST_NOMIME) != 0;
2336     filter_state = 0;
2337     post_stream_read = 0;
2338     ResetEvent(event_complete);
2339     ResetEvent(event_complete2);
2340     ResetEvent(event_continue);
2341     ResetEvent(event_continue_done);
2342     async_protocol = binding_protocol = filtered_protocol = NULL;
2343     filtered_sink = NULL;
2344     http_is_first = (flags & TEST_FIRST_HTTP) != 0;
2345     first_data_notif = TRUE;
2346     state = STATE_CONNECTING;
2347     test_async_req = (flags & TEST_ASYNCREQ) != 0;
2348     direct_read = (flags & TEST_DIRECT_READ) != 0;
2349     emulate_prot = (flags & TEST_EMULATEPROT) != 0;
2350     wait_for_switch = TRUE;
2351     short_read = (flags & TEST_SHORT_READ) != 0;
2352     http_post_test = TYMED_NULL;
2353     test_redirect = (flags & TEST_REDIRECT) != 0;
2354     test_abort = (flags & TEST_ABORT) != 0;
2355     impl_protex = (flags & TEST_IMPLPROTEX) != 0;
2356     empty_file = (flags & TEST_EMPTY) != 0;
2357
2358     register_filter(mimefilter_test);
2359 }
2360
2361 static void test_priority(IInternetProtocol *protocol)
2362 {
2363     IInternetPriority *priority;
2364     LONG pr;
2365     HRESULT hres;
2366
2367     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
2368                                             (void**)&priority);
2369     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
2370     if(FAILED(hres))
2371         return;
2372
2373     hres = IInternetPriority_GetPriority(priority, &pr);
2374     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2375     ok(pr == 0, "pr=%d, expected 0\n", pr);
2376
2377     hres = IInternetPriority_SetPriority(priority, 1);
2378     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2379
2380     hres = IInternetPriority_GetPriority(priority, &pr);
2381     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2382     ok(pr == 1, "pr=%d, expected 1\n", pr);
2383
2384     IInternetPriority_Release(priority);
2385 }
2386
2387 static void test_early_abort(const CLSID *clsid)
2388 {
2389     IInternetProtocol *protocol;
2390     HRESULT hres;
2391
2392     hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2393             &IID_IInternetProtocol, (void**)&protocol);
2394     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2395
2396     hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
2397     ok(hres == S_OK, "Abort failed: %08x\n", hres);
2398
2399     hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
2400     ok(hres == S_OK, "Abort failed: %08x\n", hres);
2401
2402     IInternetProtocol_Release(protocol);
2403 }
2404
2405 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url,
2406         IInternetProtocolEx *protocolex, IUri *uri, BOOL is_first)
2407 {
2408     HRESULT hres;
2409
2410     SET_EXPECT(GetBindInfo);
2411     if(!(bindf & BINDF_FROMURLMON))
2412        SET_EXPECT(ReportProgress_DIRECTBIND);
2413     if(is_first) {
2414         SET_EXPECT(ReportProgress_SENDINGREQUEST);
2415         SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
2416         if(bindf & BINDF_FROMURLMON)
2417             SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2418         else
2419             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2420     }
2421     SET_EXPECT(ReportData);
2422     if(is_first)
2423         SET_EXPECT(ReportResult);
2424
2425     expect_hrResult = S_OK;
2426
2427     if(protocolex) {
2428         hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
2429         ok(hres == S_OK, "StartEx failed: %08x\n", hres);
2430     }else {
2431         hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
2432         if(hres == INET_E_RESOURCE_NOT_FOUND) {
2433             win_skip("Start failed\n");
2434             return FALSE;
2435         }
2436         ok(hres == S_OK, "Start failed: %08x\n", hres);
2437     }
2438
2439     CHECK_CALLED(GetBindInfo);
2440     if(!(bindf & BINDF_FROMURLMON))
2441        CHECK_CALLED(ReportProgress_DIRECTBIND);
2442     if(is_first) {
2443         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2444         CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
2445         if(bindf & BINDF_FROMURLMON)
2446             CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2447         else
2448             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2449     }
2450     CHECK_CALLED(ReportData);
2451     if(is_first)
2452         CHECK_CALLED(ReportResult);
2453
2454     return TRUE;
2455 }
2456
2457 static void test_file_protocol_url(LPCWSTR url)
2458 {
2459     IInternetProtocolInfo *protocol_info;
2460     IUnknown *unk;
2461     IClassFactory *factory;
2462     IInternetProtocol *protocol;
2463     BYTE buf[512];
2464     ULONG cb;
2465     HRESULT hres;
2466
2467     hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
2468             &IID_IUnknown, (void**)&unk);
2469     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2470     if(FAILED(hres))
2471         return;
2472
2473     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2474     ok(hres == E_NOINTERFACE,
2475             "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
2476
2477     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2478     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2479     IUnknown_Release(unk);
2480     if(FAILED(hres))
2481         return;
2482
2483     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2484     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2485
2486     if(SUCCEEDED(hres)) {
2487         if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2488             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2489             ok(hres == S_OK, "Read failed: %08x\n", hres);
2490             ok(cb == 2, "cb=%u expected 2\n", cb);
2491             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2492             ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2493             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2494             ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
2495             ok(cb == 0, "cb=%u expected 0\n", cb);
2496             hres = IInternetProtocol_UnlockRequest(protocol);
2497             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2498         }
2499
2500         if(file_protocol_start(protocol, url, NULL, NULL, FALSE)) {
2501             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2502             ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2503             hres = IInternetProtocol_LockRequest(protocol, 0);
2504             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2505             hres = IInternetProtocol_UnlockRequest(protocol);
2506             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2507         }
2508
2509         IInternetProtocol_Release(protocol);
2510     }
2511
2512     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2513     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2514     if(SUCCEEDED(hres)) {
2515         if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2516             hres = IInternetProtocol_LockRequest(protocol, 0);
2517             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2518             hres = IInternetProtocol_Terminate(protocol, 0);
2519             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2520             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2521             ok(hres == S_OK, "Read failed: %08x\n\n", hres);
2522             hres = IInternetProtocol_UnlockRequest(protocol);
2523             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2524             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2525             ok(hres == S_OK, "Read failed: %08x\n", hres);
2526             hres = IInternetProtocol_Terminate(protocol, 0);
2527             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2528         }
2529
2530         IInternetProtocol_Release(protocol);
2531     }
2532
2533     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2534     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2535     if(SUCCEEDED(hres)) {
2536         if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2537             hres = IInternetProtocol_Terminate(protocol, 0);
2538             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2539             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2540             ok(hres == S_OK, "Read failed: %08x\n", hres);
2541             ok(cb == 2, "cb=%u expected 2\n", cb);
2542         }
2543
2544         IInternetProtocol_Release(protocol);
2545     }
2546
2547     if(pCreateUri) {
2548         IInternetProtocolEx *protocolex;
2549         IUri *uri;
2550
2551         hres = pCreateUri(url, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
2552         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2553
2554         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2555         ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2556
2557         if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2558             hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2559             ok(hres == S_OK, "Read failed: %08x\n", hres);
2560             hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2561             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2562             hres = IInternetProtocolEx_UnlockRequest(protocolex);
2563             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2564         }
2565
2566         IUri_Release(uri);
2567         IInternetProtocolEx_Release(protocolex);
2568
2569         hres = pCreateUri(url, 0, 0, &uri);
2570         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2571
2572         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2573         ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2574
2575         if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2576             hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2577             ok(hres == S_OK, "Read failed: %08x\n", hres);
2578             hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2579             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2580             hres = IInternetProtocolEx_UnlockRequest(protocolex);
2581             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2582         }
2583
2584         IUri_Release(uri);
2585         IInternetProtocolEx_Release(protocolex);
2586     }else {
2587         win_skip("Skipping file protocol StartEx tests\n");
2588     }
2589
2590     IClassFactory_Release(factory);
2591 }
2592
2593 static void test_file_protocol_fail(void)
2594 {
2595     IInternetProtocol *protocol;
2596     HRESULT hres;
2597
2598     static const WCHAR index_url2[] =
2599         {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
2600
2601     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2602             &IID_IInternetProtocol, (void**)&protocol);
2603     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2604     if(FAILED(hres))
2605         return;
2606
2607     SET_EXPECT(GetBindInfo);
2608     expect_hrResult = MK_E_SYNTAX;
2609     hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
2610     ok(hres == MK_E_SYNTAX ||
2611        hres == E_INVALIDARG,
2612        "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres);
2613     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2614
2615     SET_EXPECT(GetBindInfo);
2616     if(!(bindf & BINDF_FROMURLMON))
2617         SET_EXPECT(ReportProgress_DIRECTBIND);
2618     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2619     SET_EXPECT(ReportResult);
2620     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2621     hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
2622     ok(hres == INET_E_RESOURCE_NOT_FOUND,
2623             "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
2624     CHECK_CALLED(GetBindInfo);
2625     if(!(bindf & BINDF_FROMURLMON))
2626         CHECK_CALLED(ReportProgress_DIRECTBIND);
2627     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2628     CHECK_CALLED(ReportResult);
2629
2630     IInternetProtocol_Release(protocol);
2631
2632     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2633             &IID_IInternetProtocol, (void**)&protocol);
2634     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2635     if(FAILED(hres))
2636         return;
2637
2638     SET_EXPECT(GetBindInfo);
2639     if(!(bindf & BINDF_FROMURLMON))
2640         SET_EXPECT(ReportProgress_DIRECTBIND);
2641     SET_EXPECT(ReportProgress_SENDINGREQUEST);
2642     SET_EXPECT(ReportResult);
2643     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2644
2645     hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
2646     ok(hres == INET_E_RESOURCE_NOT_FOUND,
2647             "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
2648     CHECK_CALLED(GetBindInfo);
2649     if(!(bindf & BINDF_FROMURLMON))
2650         CHECK_CALLED(ReportProgress_DIRECTBIND);
2651     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2652     CHECK_CALLED(ReportResult);
2653
2654     SET_EXPECT(GetBindInfo);
2655     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
2656     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2657     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2658
2659     SET_EXPECT(GetBindInfo);
2660     hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0);
2661     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2662     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2663
2664     IInternetProtocol_Release(protocol);
2665 }
2666
2667 static void test_file_protocol(void) {
2668     WCHAR buf[INTERNET_MAX_URL_LENGTH], file_name_buf[MAX_PATH];
2669     DWORD size;
2670     ULONG len;
2671     HANDLE file;
2672
2673     static const WCHAR wszFile[] = {'f','i','l','e',':',0};
2674     static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
2675     static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
2676     static const WCHAR wszFile4[] = {'f','i','l','e',':','\\','\\',0};
2677     static const char html_doc[] = "<HTML></HTML>";
2678
2679     trace("Testing file protocol...\n");
2680     init_test(FILE_TEST, 0);
2681
2682     SetLastError(0xdeadbeef);
2683     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2684             FILE_ATTRIBUTE_NORMAL, NULL);
2685     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
2686     if(file == INVALID_HANDLE_VALUE)
2687         return;
2688     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
2689     CloseHandle(file);
2690
2691     file_name = wszIndexHtml;
2692     bindf = 0;
2693     test_file_protocol_url(index_url);
2694     bindf = BINDF_FROMURLMON;
2695     test_file_protocol_url(index_url);
2696     bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
2697     test_file_protocol_url(index_url);
2698
2699     memcpy(buf, wszFile, sizeof(wszFile));
2700     len = sizeof(wszFile)/sizeof(WCHAR)-1;
2701     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2702     buf[len++] = '\\';
2703     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2704
2705     file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
2706     bindf = 0;
2707     test_file_protocol_url(buf);
2708     bindf = BINDF_FROMURLMON;
2709     test_file_protocol_url(buf);
2710
2711     memcpy(buf, wszFile2, sizeof(wszFile2));
2712     len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
2713     file_name_buf[len++] = '\\';
2714     memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2715     lstrcpyW(buf+sizeof(wszFile2)/sizeof(WCHAR)-1, file_name_buf);
2716     file_name = file_name_buf;
2717     bindf = 0;
2718     test_file_protocol_url(buf);
2719     bindf = BINDF_FROMURLMON;
2720     test_file_protocol_url(buf);
2721
2722     buf[sizeof(wszFile2)/sizeof(WCHAR)] = '|';
2723     test_file_protocol_url(buf);
2724
2725     memcpy(buf, wszFile3, sizeof(wszFile3));
2726     len = sizeof(wszFile3)/sizeof(WCHAR)-1;
2727     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2728     buf[len++] = '\\';
2729     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2730
2731     file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
2732     bindf = 0;
2733     test_file_protocol_url(buf);
2734     bindf = BINDF_FROMURLMON;
2735     test_file_protocol_url(buf);
2736
2737     memcpy(buf, wszFile4, sizeof(wszFile4));
2738     len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
2739     file_name_buf[len++] = '\\';
2740     memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2741     lstrcpyW(buf+sizeof(wszFile4)/sizeof(WCHAR)-1, file_name_buf);
2742     file_name = file_name_buf;
2743     bindf = 0;
2744     test_file_protocol_url(buf);
2745     bindf = BINDF_FROMURLMON;
2746     test_file_protocol_url(buf);
2747
2748     buf[sizeof(wszFile4)/sizeof(WCHAR)] = '|';
2749     test_file_protocol_url(buf);
2750
2751     DeleteFileW(wszIndexHtml);
2752
2753     bindf = 0;
2754     test_file_protocol_fail();
2755     bindf = BINDF_FROMURLMON;
2756     test_file_protocol_fail();
2757 }
2758
2759 static BOOL http_protocol_start(LPCWSTR url, BOOL use_iuri)
2760 {
2761     static BOOL got_user_agent = FALSE;
2762     IUri *uri = NULL;
2763     HRESULT hres;
2764
2765     if(use_iuri && pCreateUri) {
2766         hres = pCreateUri(url, 0, 0, &uri);
2767         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2768     }
2769
2770     SET_EXPECT(GetBindInfo);
2771     if (!(bindf & BINDF_FROMURLMON))
2772         SET_EXPECT(ReportProgress_DIRECTBIND);
2773     if(!got_user_agent)
2774         SET_EXPECT(GetBindString_USER_AGENT);
2775     SET_EXPECT(GetBindString_ACCEPT_MIMES);
2776     SET_EXPECT(QueryService_HttpNegotiate);
2777     SET_EXPECT(BeginningTransaction);
2778     SET_EXPECT(GetRootSecurityId);
2779     if(http_post_test) {
2780         SET_EXPECT(GetBindString_POST_COOKIE);
2781         if(http_post_test == TYMED_ISTREAM)
2782             SET_EXPECT(Stream_Seek);
2783     }
2784
2785     if(uri) {
2786         IInternetProtocolEx *protocolex;
2787
2788         hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
2789         ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
2790
2791         hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
2792         ok(hres == S_OK, "Start failed: %08x\n", hres);
2793
2794         IInternetProtocolEx_Release(protocolex);
2795         IUri_Release(uri);
2796     }else {
2797         hres = IInternetProtocol_Start(async_protocol, url, &protocol_sink, &bind_info, 0, 0);
2798         ok(hres == S_OK, "Start failed: %08x\n", hres);
2799     }
2800     if(FAILED(hres))
2801         return FALSE;
2802
2803     CHECK_CALLED(GetBindInfo);
2804     if (!(bindf & BINDF_FROMURLMON))
2805         CHECK_CALLED(ReportProgress_DIRECTBIND);
2806     if (!got_user_agent)
2807     {
2808         CHECK_CALLED(GetBindString_USER_AGENT);
2809         got_user_agent = TRUE;
2810     }
2811     CHECK_CALLED(GetBindString_ACCEPT_MIMES);
2812     CHECK_CALLED(QueryService_HttpNegotiate);
2813     CHECK_CALLED(BeginningTransaction);
2814     /* GetRootSecurityId called on WinXP but not on Win98 */
2815     CLEAR_CALLED(GetRootSecurityId);
2816     if(http_post_test) {
2817         CHECK_CALLED(GetBindString_POST_COOKIE);
2818         if(http_post_test == TYMED_ISTREAM)
2819             CHECK_CALLED(Stream_Seek);
2820     }
2821
2822     return TRUE;
2823 }
2824
2825 static void test_protocol_terminate(IInternetProtocol *protocol)
2826 {
2827     BYTE buf[3600];
2828     DWORD cb;
2829     HRESULT hres;
2830
2831     hres = IInternetProtocol_LockRequest(protocol, 0);
2832     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2833
2834     hres = IInternetProtocol_Read(protocol, buf, 1, &cb);
2835     ok(hres == test_abort ? S_OK : S_FALSE, "Read failed: %08x\n", hres);
2836
2837     hres = IInternetProtocol_Terminate(protocol, 0);
2838     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2839
2840     /* This wait is to give the internet handles being freed in Terminate
2841      * enough time to actually terminate in all cases. Internet handles
2842      * terminate asynchronously and native reuses the main InternetOpen
2843      * handle. The only case in which this seems to be necessary is on
2844      * wine with native wininet and urlmon, resulting in the next time
2845      * test_http_protocol_url being called the first data notification actually
2846      * being an extra last data notification from the previous connection
2847      * about once out of every ten times. */
2848     Sleep(100);
2849
2850     hres = IInternetProtocol_UnlockRequest(protocol);
2851     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2852 }
2853
2854 static void test_http_info(IInternetProtocol *protocol)
2855 {
2856     IWinInetHttpInfo *info;
2857     HRESULT hres;
2858
2859     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&info);
2860     ok(hres == S_OK, "Could not get IWinInterHttpInfo iface: %08x\n", hres);
2861
2862     /* TODO */
2863
2864     IWinInetHttpInfo_Release(info);
2865 }
2866
2867 /* is_first refers to whether this is the first call to this function
2868  * _for this url_ */
2869 static void test_http_protocol_url(LPCWSTR url, int prot, DWORD flags, DWORD tymed)
2870 {
2871     IInternetProtocolInfo *protocol_info;
2872     IClassFactory *factory;
2873     IUnknown *unk;
2874     HRESULT hres;
2875
2876     init_test(prot, flags);
2877     http_url = url;
2878     http_post_test = tymed;
2879
2880     hres = CoGetClassObject(prot == HTTPS_TEST ? &CLSID_HttpSProtocol : &CLSID_HttpProtocol,
2881             CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
2882     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2883     if(FAILED(hres))
2884         return;
2885
2886     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2887     ok(hres == E_NOINTERFACE,
2888         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
2889         hres);
2890
2891     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2892     ok(hres == S_OK, "Could not get IClassFactory interface\n");
2893     IUnknown_Release(unk);
2894     if(FAILED(hres))
2895         return;
2896
2897     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
2898                                         (void**)&async_protocol);
2899     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2900     if(SUCCEEDED(hres)) {
2901         BYTE buf[3600];
2902         DWORD cb;
2903         ULONG ref;
2904
2905         test_priority(async_protocol);
2906         test_http_info(async_protocol);
2907
2908         SET_EXPECT(ReportProgress_COOKIE_SENT);
2909         if(http_is_first) {
2910             SET_EXPECT(ReportProgress_FINDINGRESOURCE);
2911             SET_EXPECT(ReportProgress_CONNECTING);
2912         }
2913         SET_EXPECT(ReportProgress_SENDINGREQUEST);
2914         if(test_redirect)
2915             SET_EXPECT(ReportProgress_REDIRECTING);
2916         SET_EXPECT(ReportProgress_PROXYDETECTING);
2917         if(prot == HTTP_TEST)
2918             SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
2919         else
2920             SET_EXPECT(QueryService_HttpSecurity);
2921         if(!(bindf & BINDF_FROMURLMON)) {
2922             SET_EXPECT(OnResponse);
2923             SET_EXPECT(ReportProgress_RAWMIMETYPE);
2924             SET_EXPECT(ReportData);
2925         } else {
2926             SET_EXPECT(Switch);
2927         }
2928
2929         if(!http_protocol_start(url, (flags & TEST_USEIURI) != 0))
2930             return;
2931
2932         if(!direct_read && !test_abort)
2933             SET_EXPECT(ReportResult);
2934         expect_hrResult = test_abort ? E_ABORT : S_OK;
2935
2936         if(direct_read) {
2937             SET_EXPECT(Switch);
2938             while(wait_for_switch) {
2939                 WaitForSingleObject(event_continue, INFINITE);
2940                 CHECK_CALLED(Switch); /* Set in ReportData */
2941                 call_continue(&continue_protdata);
2942                 SetEvent(event_continue_done);
2943             }
2944         }else {
2945             hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
2946             ok((hres == E_PENDING && cb==0) ||
2947                (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
2948
2949             WaitForSingleObject(event_complete, INFINITE);
2950             if(bindf & BINDF_FROMURLMON)
2951                 CHECK_CALLED(Switch);
2952             else
2953                 CHECK_CALLED(ReportData);
2954             if(prot == HTTPS_TEST)
2955                 CLEAR_CALLED(QueryService_HttpSecurity);
2956
2957             while(1) {
2958                 if(bindf & BINDF_FROMURLMON)
2959                     SET_EXPECT(Switch);
2960                 else
2961                     SET_EXPECT(ReportData);
2962                 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
2963                 if(hres == E_PENDING) {
2964                     hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
2965                     ok((hres == E_PENDING && cb==0) ||
2966                        (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
2967                     WaitForSingleObject(event_complete, INFINITE);
2968                     if(bindf & BINDF_FROMURLMON)
2969                         CHECK_CALLED(Switch);
2970                     else
2971                         CHECK_CALLED(ReportData);
2972
2973                     if(test_abort) {
2974                         HRESULT hres;
2975
2976                         SET_EXPECT(ReportResult);
2977                         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
2978                         ok(hres == S_OK, "Abort failed: %08x\n", hres);
2979                         CHECK_CALLED(ReportResult);
2980
2981                         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
2982                         ok(hres == INET_E_RESULT_DISPATCHED, "Abort failed: %08x\n", hres);
2983                         break;
2984                     }
2985                 }else {
2986                     if(bindf & BINDF_FROMURLMON)
2987                         CHECK_NOT_CALLED(Switch);
2988                     else
2989                         CHECK_NOT_CALLED(ReportData);
2990                     if(cb == 0) break;
2991                 }
2992             }
2993             if(!test_abort) {
2994                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2995                 CHECK_CALLED(ReportResult);
2996             }
2997         }
2998         if(prot == HTTPS_TEST)
2999             CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3000
3001         if (prot == HTTP_TEST || prot == HTTPS_TEST)
3002             CLEAR_CALLED(ReportProgress_COOKIE_SENT);
3003
3004         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3005         ok(hres == INET_E_RESULT_DISPATCHED, "Abort failed: %08x\n", hres);
3006
3007         test_protocol_terminate(async_protocol);
3008
3009         hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3010         ok(hres == S_OK, "Abort failed: %08x\n", hres);
3011
3012         ref = IInternetProtocol_Release(async_protocol);
3013         ok(!ref, "ref=%x\n", ref);
3014     }
3015
3016     IClassFactory_Release(factory);
3017 }
3018
3019 static void test_http_protocol(void)
3020 {
3021     static const WCHAR posttest_url[] =
3022         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3023          't','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3024     static const WCHAR redirect_url[] =
3025         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3026          't','e','s','t','s','/','r','e','d','i','r','e','c','t',0};
3027     static const WCHAR winetest_url[] =
3028         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3029          't','e','s','t','s','/','d','a','t','a','.','p','h','p',0};
3030     static const WCHAR empty_url[] =
3031         {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3032          't','e','s','t','s','/','e','m','p','t','y','.','j','s',0};
3033
3034     trace("Testing http protocol (not from urlmon)...\n");
3035     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
3036     test_http_protocol_url(winetest_url, HTTP_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3037
3038     trace("Testing http protocol (from urlmon)...\n");
3039     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3040     test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3041
3042     trace("Testing http protocol (to file)...\n");
3043     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE;
3044     test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3045
3046     trace("Testing http protocol (post data)...\n");
3047     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3048     test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST, TYMED_HGLOBAL);
3049
3050     trace("Testing http protocol (post data stream)...\n");
3051     test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST|TEST_ASYNCREQ, TYMED_ISTREAM);
3052
3053     trace("Testing http protocol (direct read)...\n");
3054     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3055     test_http_protocol_url(winetest_url, HTTP_TEST, TEST_DIRECT_READ|TEST_USEIURI, TYMED_NULL);
3056
3057     trace("Testing http protocol (redirected)...\n");
3058     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3059     test_http_protocol_url(redirect_url, HTTP_TEST, TEST_REDIRECT, TYMED_NULL);
3060
3061     trace("Testing http protocol empty file...\n");
3062     test_http_protocol_url(empty_url, HTTP_TEST, TEST_EMPTY, TYMED_NULL);
3063
3064     trace("Testing http protocol abort...\n");
3065     test_http_protocol_url(winetest_url, HTTP_TEST, TEST_ABORT, TYMED_NULL);
3066
3067     test_early_abort(&CLSID_HttpProtocol);
3068     test_early_abort(&CLSID_HttpSProtocol);
3069 }
3070
3071 static void test_https_protocol(void)
3072 {
3073     static const WCHAR codeweavers_url[] =
3074         {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
3075          '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0};
3076
3077     trace("Testing https protocol (from urlmon)...\n");
3078     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3079     test_http_protocol_url(codeweavers_url, HTTPS_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3080 }
3081
3082
3083 static void test_ftp_protocol(void)
3084 {
3085     IInternetProtocolInfo *protocol_info;
3086     IClassFactory *factory;
3087     IUnknown *unk;
3088     BYTE buf[4096];
3089     ULONG ref;
3090     DWORD cb;
3091     HRESULT hres;
3092
3093     static const WCHAR ftp_urlW[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
3094     '/','p','u','b','/','o','t','h','e','r','/',
3095     'w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0};
3096
3097     trace("Testing ftp protocol...\n");
3098
3099     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3100     state = STATE_STARTDOWNLOADING;
3101     tested_protocol = FTP_TEST;
3102     first_data_notif = TRUE;
3103     expect_hrResult = E_PENDING;
3104
3105     hres = CoGetClassObject(&CLSID_FtpProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3106     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3107     if(FAILED(hres))
3108         return;
3109
3110     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3111     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3112
3113     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3114     ok(hres == S_OK, "Could not get IClassFactory interface\n");
3115     IUnknown_Release(unk);
3116     if(FAILED(hres))
3117         return;
3118
3119     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3120                                         (void**)&async_protocol);
3121     IClassFactory_Release(factory);
3122     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3123
3124     test_priority(async_protocol);
3125     test_http_info(async_protocol);
3126
3127     SET_EXPECT(GetBindInfo);
3128     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
3129     SET_EXPECT(ReportProgress_CONNECTING);
3130     SET_EXPECT(ReportProgress_SENDINGREQUEST);
3131     SET_EXPECT(Switch);
3132
3133     hres = IInternetProtocol_Start(async_protocol, ftp_urlW, &protocol_sink, &bind_info, 0, 0);
3134     ok(hres == S_OK, "Start failed: %08x\n", hres);
3135     CHECK_CALLED(GetBindInfo);
3136
3137     SET_EXPECT(ReportResult);
3138
3139     hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3140     ok((hres == E_PENDING && cb==0) ||
3141        (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3142
3143     WaitForSingleObject(event_complete, INFINITE);
3144
3145     while(1) {
3146         hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3147         if(hres == E_PENDING)
3148             WaitForSingleObject(event_complete, INFINITE);
3149         else
3150             if(cb == 0) break;
3151     }
3152
3153     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3154     CHECK_CALLED(ReportResult);
3155     CHECK_CALLED(Switch);
3156
3157     test_protocol_terminate(async_protocol);
3158
3159     if(pCreateUri) {
3160         IInternetProtocolEx *protocolex;
3161
3162         hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3163         ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3164         IInternetProtocolEx_Release(protocolex);
3165     }
3166
3167     ref = IInternetProtocol_Release(async_protocol);
3168     ok(!ref, "ref=%d\n", ref);
3169
3170     test_early_abort(&CLSID_FtpProtocol);
3171 }
3172
3173 static void test_gopher_protocol(void)
3174 {
3175     IInternetProtocolInfo *protocol_info;
3176     IClassFactory *factory;
3177     IUnknown *unk;
3178     HRESULT hres;
3179
3180     trace("Testing gopher protocol...\n");
3181
3182     hres = CoGetClassObject(&CLSID_GopherProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3183     ok(hres == S_OK ||
3184        hres == REGDB_E_CLASSNOTREG, /* Gopher protocol has been removed as of Vista */
3185        "CoGetClassObject failed: %08x\n", hres);
3186     if(FAILED(hres))
3187         return;
3188
3189     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3190     ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3191
3192     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3193     ok(hres == S_OK, "Could not get IClassFactory interface\n");
3194     IUnknown_Release(unk);
3195     if(FAILED(hres))
3196         return;
3197
3198     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3199                                         (void**)&async_protocol);
3200     IClassFactory_Release(factory);
3201     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3202
3203     test_priority(async_protocol);
3204
3205     IInternetProtocol_Release(async_protocol);
3206
3207     test_early_abort(&CLSID_GopherProtocol);
3208 }
3209
3210 static void test_mk_protocol(void)
3211 {
3212     IInternetProtocolInfo *protocol_info;
3213     IInternetProtocol *protocol;
3214     IClassFactory *factory;
3215     IUnknown *unk;
3216     HRESULT hres;
3217
3218     static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
3219                                        ':',':','/','t','e','s','t','.','h','t','m','l',0};
3220     static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
3221
3222     trace("Testing mk protocol...\n");
3223     init_test(MK_TEST, 0);
3224
3225     hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
3226             &IID_IUnknown, (void**)&unk);
3227     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3228
3229     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3230     ok(hres == E_NOINTERFACE,
3231         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
3232         hres);
3233
3234     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3235     ok(hres == S_OK, "Could not get IClassFactory interface\n");
3236     IUnknown_Release(unk);
3237     if(FAILED(hres))
3238         return;
3239
3240     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3241                                         (void**)&protocol);
3242     IClassFactory_Release(factory);
3243     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3244
3245     SET_EXPECT(GetBindInfo);
3246     hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
3247     ok(hres == MK_E_SYNTAX || hres == INET_E_INVALID_URL,
3248        "Start failed: %08x, expected MK_E_SYNTAX or INET_E_INVALID_URL\n", hres);
3249     CLEAR_CALLED(GetBindInfo);
3250
3251     SET_EXPECT(GetBindInfo);
3252     SET_EXPECT(ReportProgress_DIRECTBIND);
3253     SET_EXPECT(ReportProgress_SENDINGREQUEST);
3254     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
3255     SET_EXPECT(ReportResult);
3256     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
3257
3258     hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
3259     ok(hres == INET_E_RESOURCE_NOT_FOUND ||
3260        hres == INET_E_INVALID_URL, /* win2k3 */
3261        "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND or INET_E_INVALID_URL\n", hres);
3262
3263     if (hres == INET_E_RESOURCE_NOT_FOUND) {
3264         CHECK_CALLED(GetBindInfo);
3265         CLEAR_CALLED(ReportProgress_DIRECTBIND);
3266         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
3267         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3268         CHECK_CALLED(ReportResult);
3269     }else {
3270         CLEAR_CALLED(GetBindInfo);
3271         CLEAR_CALLED(ReportProgress_DIRECTBIND);
3272         CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3273         CLEAR_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3274         CLEAR_CALLED(ReportResult);
3275     }
3276
3277     IInternetProtocol_Release(protocol);
3278 }
3279
3280 static void test_CreateBinding(void)
3281 {
3282     IInternetProtocol *protocol;
3283     IInternetPriority *priority;
3284     IInternetSession *session;
3285     IWinInetHttpInfo *http_info;
3286     IWinInetInfo *inet_info;
3287     LONG p;
3288     BYTE buf[1000];
3289     DWORD read;
3290     HRESULT hres;
3291
3292     static const WCHAR test_url[] =
3293         {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
3294     static const WCHAR wsz_test[] = {'t','e','s','t',0};
3295
3296     trace("Testing CreateBinding...\n");
3297     init_test(BIND_TEST, TEST_BINDING);
3298
3299     hres = pCoInternetGetSession(0, &session, 0);
3300     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
3301
3302     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
3303     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
3304
3305     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3306     binding_protocol = protocol;
3307     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3308     ok(protocol != NULL, "protocol == NULL\n");
3309
3310     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
3311     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
3312
3313     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
3314     ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres);
3315
3316     hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
3317     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3318     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
3319     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3320     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
3321     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3322
3323     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
3324     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
3325
3326     p = 0xdeadbeef;
3327     hres = IInternetPriority_GetPriority(priority, &p);
3328     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3329     ok(!p, "p=%d\n", p);
3330
3331     ex_priority = 100;
3332     hres = IInternetPriority_SetPriority(priority, 100);
3333     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3334
3335     p = 0xdeadbeef;
3336     hres = IInternetPriority_GetPriority(priority, &p);
3337     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3338     ok(p == 100, "p=%d\n", p);
3339
3340     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3341     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3342
3343     SET_EXPECT(QueryService_InternetProtocol);
3344     SET_EXPECT(CreateInstance);
3345     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
3346     SET_EXPECT(SetPriority);
3347     SET_EXPECT(Start);
3348
3349     expect_hrResult = S_OK;
3350     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
3351     ok(hres == S_OK, "Start failed: %08x\n", hres);
3352
3353     CHECK_CALLED(QueryService_InternetProtocol);
3354     CHECK_CALLED(CreateInstance);
3355     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
3356     CHECK_CALLED(SetPriority);
3357     CHECK_CALLED(Start);
3358
3359     SET_EXPECT(QueryInterface_IWinInetInfo);
3360     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3361     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3362     CHECK_CALLED(QueryInterface_IWinInetInfo);
3363
3364     SET_EXPECT(QueryInterface_IWinInetInfo);
3365     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3366     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3367     CHECK_CALLED(QueryInterface_IWinInetInfo);
3368
3369     SET_EXPECT(QueryInterface_IWinInetHttpInfo);
3370     hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
3371     ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3372     CHECK_CALLED(QueryInterface_IWinInetHttpInfo);
3373
3374     SET_EXPECT(Read);
3375     read = 0xdeadbeef;
3376     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3377     ok(hres == S_OK, "Read failed: %08x\n", hres);
3378     ok(read == 100, "read = %d\n", read);
3379     CHECK_CALLED(Read);
3380
3381     SET_EXPECT(Read);
3382     read = 0xdeadbeef;
3383     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3384     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3385     ok(!read, "read = %d\n", read);
3386     CHECK_CALLED(Read);
3387
3388     p = 0xdeadbeef;
3389     hres = IInternetPriority_GetPriority(priority, &p);
3390     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3391     ok(p == 100, "p=%d\n", p);
3392
3393     hres = IInternetPriority_SetPriority(priority, 101);
3394     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3395
3396     SET_EXPECT(Terminate);
3397     hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
3398     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3399     CHECK_CALLED(Terminate);
3400
3401     SET_EXPECT(Continue);
3402     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
3403     ok(hres == S_OK, "Switch failed: %08x\n", hres);
3404     CHECK_CALLED(Continue);
3405
3406     hres = IInternetProtocolSink_ReportProgress(binding_sink,
3407             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
3408     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
3409
3410     hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
3411     ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres);
3412
3413     hres = IInternetProtocolSink_ReportData(binding_sink, 0, 0, 0);
3414     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
3415
3416     IInternetProtocolSink_Release(binding_sink);
3417     IInternetPriority_Release(priority);
3418     IInternetBindInfo_Release(prot_bind_info);
3419     IInternetProtocol_Release(protocol);
3420
3421     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3422     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3423     ok(protocol != NULL, "protocol == NULL\n");
3424
3425     hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3426     ok(hres == S_OK, "Abort failed: %08x\n", hres);
3427
3428     hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
3429     ok(hres == S_OK, "Abort failed: %08x\n", hres);
3430
3431     IInternetProtocol_Release(protocol);
3432
3433     hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, wsz_test);
3434     ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
3435
3436     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3437     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3438     ok(protocol != NULL, "protocol == NULL\n");
3439
3440     SET_EXPECT(QueryService_InternetProtocol);
3441     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
3442     ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
3443     CHECK_CALLED(QueryService_InternetProtocol);
3444
3445     IInternetProtocol_Release(protocol);
3446
3447     IInternetSession_Release(session);
3448 }
3449
3450 static void test_binding(int prot, DWORD grf_pi, DWORD test_flags)
3451 {
3452     IInternetProtocolEx *protocolex = NULL;
3453     IInternetProtocol *protocol;
3454     IInternetSession *session;
3455     IUri *uri = NULL;
3456     ULONG ref;
3457     HRESULT hres;
3458
3459     pi = grf_pi;
3460
3461     init_test(prot, test_flags|TEST_BINDING);
3462
3463     hres = pCoInternetGetSession(0, &session, 0);
3464     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
3465
3466     if(test_flags & TEST_EMULATEPROT) {
3467         hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, protocol_names[prot], 0, NULL, 0);
3468         ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
3469     }
3470
3471     hres = IInternetSession_CreateBinding(session, NULL, binding_urls[prot], NULL, NULL, &protocol, 0);
3472     binding_protocol = protocol;
3473     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3474     ok(protocol != NULL, "protocol == NULL\n");
3475
3476     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
3477     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
3478
3479     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
3480     ok(hres == S_OK, "QueryInterface(IID_IInternetProtocolSink) failed: %08x\n", hres);
3481
3482     if(test_flags & TEST_USEIURI) {
3483         hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3484         ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3485
3486         hres = pCreateUri(binding_urls[prot], Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
3487         ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
3488     }
3489
3490     ex_priority = 0;
3491     SET_EXPECT(QueryService_InternetProtocol);
3492     SET_EXPECT(CreateInstance);
3493     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
3494     SET_EXPECT(SetPriority);
3495     if(impl_protex)
3496         SET_EXPECT(StartEx);
3497     else
3498         SET_EXPECT(Start);
3499
3500     expect_hrResult = S_OK;
3501
3502     if(protocolex) {
3503         hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, pi, 0);
3504         ok(hres == S_OK, "StartEx failed: %08x\n", hres);
3505     }else {
3506         hres = IInternetProtocol_Start(protocol, binding_urls[prot], &protocol_sink, &bind_info, pi, 0);
3507         ok(hres == S_OK, "Start failed: %08x\n", hres);
3508     }
3509
3510     CHECK_CALLED(QueryService_InternetProtocol);
3511     CHECK_CALLED(CreateInstance);
3512     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
3513     CHECK_CALLED(SetPriority);
3514     if(impl_protex)
3515         CHECK_CALLED(StartEx);
3516     else
3517         CHECK_CALLED(Start);
3518
3519     if(protocolex)
3520         IInternetProtocolEx_Release(protocolex);
3521     if(uri)
3522         IUri_Release(uri);
3523
3524     if(prot == HTTP_TEST || prot == HTTPS_TEST) {
3525         while(prot_state < 4) {
3526             WaitForSingleObject(event_complete, INFINITE);
3527             if(mimefilter_test && filtered_protocol) {
3528                 SET_EXPECT(Continue);
3529                 IInternetProtocol_Continue(filtered_protocol, pdata);
3530                 CHECK_CALLED(Continue);
3531             }else {
3532                 SET_EXPECT(Continue);
3533                 IInternetProtocol_Continue(protocol, pdata);
3534                 CHECK_CALLED(Continue);
3535             }
3536             if(test_abort && prot_state == 2) {
3537                 SET_EXPECT(Abort);
3538                 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3539                 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3540                 CHECK_CALLED(Abort);
3541
3542                 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3543                 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3544                 SetEvent(event_complete2);
3545                 break;
3546             }
3547             SetEvent(event_complete2);
3548         }
3549         if(direct_read)
3550             CHECK_CALLED(ReportData); /* Set in ReportResult */
3551         WaitForSingleObject(event_complete, INFINITE);
3552     }else {
3553         if(mimefilter_test)
3554             SET_EXPECT(MimeFilter_LockRequest);
3555         else
3556             SET_EXPECT(LockRequest);
3557         hres = IInternetProtocol_LockRequest(protocol, 0);
3558         ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
3559         if(mimefilter_test)
3560             CHECK_CALLED(MimeFilter_LockRequest);
3561         else
3562             CHECK_CALLED(LockRequest);
3563
3564         if(mimefilter_test)
3565             SET_EXPECT(MimeFilter_UnlockRequest);
3566         else
3567             SET_EXPECT(UnlockRequest);
3568         hres = IInternetProtocol_UnlockRequest(protocol);
3569         ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
3570         if(mimefilter_test)
3571             CHECK_CALLED(MimeFilter_UnlockRequest);
3572         else
3573             CHECK_CALLED(UnlockRequest);
3574     }
3575
3576     if(mimefilter_test)
3577         SET_EXPECT(MimeFilter_Terminate);
3578     else
3579         SET_EXPECT(Terminate);
3580     hres = IInternetProtocol_Terminate(protocol, 0);
3581     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3582     if(mimefilter_test)
3583         CLEAR_CALLED(MimeFilter_Terminate);
3584     else
3585         CHECK_CALLED(Terminate);
3586
3587     if(filtered_protocol)
3588         IInternetProtocol_Release(filtered_protocol);
3589     IInternetBindInfo_Release(prot_bind_info);
3590     IInternetProtocolSink_Release(binding_sink);
3591     ref = IInternetProtocol_Release(protocol);
3592     ok(!ref, "ref=%u, expected 0\n", ref);
3593
3594     if(test_flags & TEST_EMULATEPROT) {
3595         hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, protocol_names[prot]);
3596         ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
3597     }
3598
3599     IInternetSession_Release(session);
3600 }
3601
3602 START_TEST(protocol)
3603 {
3604     HMODULE hurlmon;
3605
3606     hurlmon = GetModuleHandle("urlmon.dll");
3607     pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
3608     pReleaseBindInfo = (void*) GetProcAddress(hurlmon, "ReleaseBindInfo");
3609     pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
3610
3611     if(!GetProcAddress(hurlmon, "CompareSecurityIds")) {
3612         win_skip("Various needed functions not present, too old IE\n");
3613         return;
3614     }
3615
3616     if(!pCreateUri)
3617         win_skip("CreateUri not supported\n");
3618
3619     OleInitialize(NULL);
3620
3621     event_complete = CreateEvent(NULL, FALSE, FALSE, NULL);
3622     event_complete2 = CreateEvent(NULL, FALSE, FALSE, NULL);
3623     event_continue = CreateEvent(NULL, FALSE, FALSE, NULL);
3624     event_continue_done = CreateEvent(NULL, FALSE, FALSE, NULL);
3625     thread_id = GetCurrentThreadId();
3626
3627     test_file_protocol();
3628     test_http_protocol();
3629     test_https_protocol();
3630     test_ftp_protocol();
3631     test_gopher_protocol();
3632     test_mk_protocol();
3633     test_CreateBinding();
3634
3635     bindf &= ~BINDF_FROMURLMON;
3636     trace("Testing file binding (mime verification, emulate prot)...\n");
3637     test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
3638     trace("Testing http binding (mime verification, emulate prot)...\n");
3639     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
3640     trace("Testing its binding (mime verification, emulate prot)...\n");
3641     test_binding(ITS_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
3642     trace("Testing http binding (mime verification, emulate prot, short read, direct read)...\n");
3643     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_SHORT_READ|TEST_DIRECT_READ);
3644     trace("Testing file binding (mime verification, emulate prot, mime filter)...\n");
3645     test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
3646     trace("Testing http binding (mime verification, emulate prot, mime filter)...\n");
3647     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
3648     trace("Testing http binding (mime verification, emulate prot, mime filter, no mime)...\n");
3649     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER|TEST_NOMIME);
3650     trace("Testing http binding (mime verification, emulate prot, direct read)...\n");
3651     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_DIRECT_READ);
3652     trace("Testing http binding (mime verification, emulate prot, abort)...\n");
3653     test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_ABORT);
3654     if(pCreateUri) {
3655         trace("Testing file binding (use IUri, mime verification, emulate prot)...\n");
3656         test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI);
3657         trace("Testing file binding (use IUri, impl StartEx, mime verification, emulate prot)...\n");
3658         test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI|TEST_IMPLPROTEX);
3659         trace("Testing file binding (impl StartEx, mime verification, emulate prot)...\n");
3660         test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_IMPLPROTEX);
3661     }
3662
3663     CloseHandle(event_complete);
3664     CloseHandle(event_complete2);
3665     CloseHandle(event_continue);
3666     CloseHandle(event_continue_done);
3667
3668     OleUninitialize();
3669 }