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