winejoystick.drv: Use CP_UNIXCP instead of CP_ACP when converting a string that comes...
[wine] / dlls / urlmon / tests / protocol.c
1 /*
2  * Copyright 2005-2007 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(ReportData);
81 DEFINE_EXPECT(ReportResult);
82 DEFINE_EXPECT(GetBindString_ACCEPT_MIMES);
83 DEFINE_EXPECT(GetBindString_USER_AGENT);
84 DEFINE_EXPECT(GetBindString_POST_COOKIE);
85 DEFINE_EXPECT(QueryService_HttpNegotiate);
86 DEFINE_EXPECT(QueryService_InternetProtocol);
87 DEFINE_EXPECT(BeginningTransaction);
88 DEFINE_EXPECT(GetRootSecurityId);
89 DEFINE_EXPECT(OnResponse);
90 DEFINE_EXPECT(Switch);
91 DEFINE_EXPECT(Continue);
92 DEFINE_EXPECT(CreateInstance);
93 DEFINE_EXPECT(Start);
94 DEFINE_EXPECT(Terminate);
95 DEFINE_EXPECT(Read);
96 DEFINE_EXPECT(SetPriority);
97 DEFINE_EXPECT(LockRequest);
98 DEFINE_EXPECT(UnlockRequest);
99
100 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
101 static const WCHAR index_url[] =
102     {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
103
104 static const WCHAR acc_mimeW[] = {'*','/','*',0};
105 static const WCHAR user_agentW[] = {'W','i','n','e',0};
106 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
107 static const WCHAR hostW[] = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
108 static const WCHAR winehq_ipW[] = {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
109 static const WCHAR emptyW[] = {0};
110
111 static HRESULT expect_hrResult;
112 static LPCWSTR file_name, http_url, expect_wsz;
113 static IInternetProtocol *http_protocol = NULL;
114 static BOOL first_data_notif = FALSE, http_is_first = FALSE,
115     http_post_test = FALSE;
116 static int state = 0, prot_state;
117 static DWORD bindf = 0, ex_priority = 0;
118 static IInternetProtocol *binding_protocol;
119 static IInternetBindInfo *prot_bind_info;
120 static IInternetProtocolSink *binding_sink;
121 static void *expect_pv;
122 static HANDLE event_complete, event_complete2;
123 static BOOL binding_test;
124 static PROTOCOLDATA protocoldata, *pdata;
125 static DWORD prot_read;
126
127 static enum {
128     FILE_TEST,
129     HTTP_TEST,
130     HTTPS_TEST,
131     MK_TEST,
132     BIND_TEST
133 } tested_protocol;
134
135 static const WCHAR protocol_names[][10] = {
136     {'f','i','l','e',0},
137     {'h','t','t','p',0},
138     {'m','k',0},
139     {'t','e','s','t',0}
140 };
141
142 static const WCHAR binding_urls[][30] = {
143     {'f','i','l','e',':','t','e','s','t','.','h','t','m','l',0},
144     {'h','t','t','p',':','/','/','t','e','s','t','/','t','e','s','t','.','h','t','m','l',0},
145     {'m','k',':','t','e','s','t',0},
146     {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0}
147 };
148
149 static const char *debugstr_w(LPCWSTR str)
150 {
151     static char buf[512];
152     if(!str)
153         return "(null)";
154     WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
155     return buf;
156 }
157
158 static const char *debugstr_guid(REFIID riid)
159 {
160     static char buf[50];
161
162     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
163             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
164             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
165             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
166
167     return buf;
168 }
169
170 static int strcmp_wa(LPCWSTR strw, const char *stra)
171 {
172     WCHAR buf[512];
173     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
174     return lstrcmpW(strw, buf);
175 }
176
177 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
178 {
179     if(IsEqualGUID(&IID_IUnknown, riid)
180             || IsEqualGUID(&IID_IHttpNegotiate, riid)
181             || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
182         *ppv = iface;
183         return S_OK;
184     }
185
186     ok(0, "unexpected call\n");
187     return E_NOINTERFACE;
188 }
189
190 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
191 {
192     return 2;
193 }
194
195 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
196 {
197     return 1;
198 }
199
200 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
201         LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
202 {
203     LPWSTR addl_headers;
204
205     static const WCHAR wszHeaders[] =
206         {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
207          'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
208          'd','e','d','\r','\n',0};
209
210     CHECK_EXPECT(BeginningTransaction);
211
212     if(binding_test)
213         ok(!lstrcmpW(szURL, binding_urls[tested_protocol]), "szURL != http_url\n");
214     else
215         ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
216     ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
217     ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
218     if(pszAdditionalHeaders)
219     {
220         ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
221         if (http_post_test)
222         {
223             addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
224             if (!addl_headers)
225             {
226                 http_post_test = FALSE;
227                 skip("Out of memory\n");
228                 return E_OUTOFMEMORY;
229             }
230             lstrcpyW(addl_headers, wszHeaders);
231             *pszAdditionalHeaders = addl_headers;
232         }
233     }
234
235     return S_OK;
236 }
237
238 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
239         LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
240 {
241     CHECK_EXPECT(OnResponse);
242
243     ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
244     ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
245     ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
246     ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
247
248     return S_OK;
249 }
250
251 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
252         BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
253 {
254     static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
255     
256     CHECK_EXPECT(GetRootSecurityId);
257
258     ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
259     ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
260     ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
261
262     if(pcbSecurityId) {
263         ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
264         *pcbSecurityId = sizeof(sec_id);
265     }
266
267     if(pbSecurityId)
268         memcpy(pbSecurityId, sec_id, sizeof(sec_id));
269
270     return E_FAIL;
271 }
272
273 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
274     HttpNegotiate_QueryInterface,
275     HttpNegotiate_AddRef,
276     HttpNegotiate_Release,
277     HttpNegotiate_BeginningTransaction,
278     HttpNegotiate_OnResponse,
279     HttpNegotiate_GetRootSecurityId
280 };
281
282 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
283
284 static HRESULT QueryInterface(REFIID,void**);
285
286 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
287 {
288     return QueryInterface(riid, ppv);
289 }
290
291 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
292 {
293     return 2;
294 }
295
296 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
297 {
298     return 1;
299 }
300
301 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
302         REFIID riid, void **ppv)
303 {
304     if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
305         CHECK_EXPECT2(QueryService_HttpNegotiate);
306         return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
307     }
308
309     if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
310         ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
311         CHECK_EXPECT(QueryService_InternetProtocol);
312         return E_NOINTERFACE;
313     }
314
315     ok(0, "unexpected service %s\n", debugstr_guid(guidService));
316     return E_FAIL;
317 }
318
319 static const IServiceProviderVtbl ServiceProviderVtbl = {
320     ServiceProvider_QueryInterface,
321     ServiceProvider_AddRef,
322     ServiceProvider_Release,
323     ServiceProvider_QueryService
324 };
325
326 static IServiceProvider service_provider = { &ServiceProviderVtbl };
327
328 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
329 {
330     return QueryInterface(riid, ppv);
331 }
332
333 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
334 {
335     return 2;
336 }
337
338 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
339 {
340     return 1;
341 }
342
343 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
344 {
345     HRESULT hres;
346
347     CHECK_EXPECT(Switch);
348     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
349
350     pdata = pProtocolData;
351
352     if(binding_test) {
353         SetEvent(event_complete);
354         WaitForSingleObject(event_complete2, INFINITE);
355         return S_OK;
356     }
357
358     if (!state) {
359         if (http_is_first) {
360             CLEAR_CALLED(ReportProgress_FINDINGRESOURCE);
361             CLEAR_CALLED(ReportProgress_CONNECTING);
362             CLEAR_CALLED(ReportProgress_PROXYDETECTING);
363         } else todo_wine {
364             CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
365             /* IE7 does call this */
366             CLEAR_CALLED(ReportProgress_CONNECTING);
367         }
368         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
369         SET_EXPECT(OnResponse);
370         if(tested_protocol == HTTPS_TEST)
371             SET_EXPECT(ReportProgress_ACCEPTRANGES);
372         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
373         if(bindf & BINDF_NEEDFILE)
374             SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
375     }
376
377     SET_EXPECT(ReportData);
378     hres = IInternetProtocol_Continue(http_protocol, pProtocolData);
379     ok(hres == S_OK, "Continue failed: %08x\n", hres);
380     CHECK_CALLED(ReportData);
381
382     if (!state) {
383         state = 1;
384         CHECK_CALLED(OnResponse);
385         if(tested_protocol == HTTPS_TEST)
386             CHECK_CALLED(ReportProgress_ACCEPTRANGES);
387         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
388         if(bindf & BINDF_NEEDFILE)
389             CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
390     }
391
392     SetEvent(event_complete);
393
394     return S_OK;
395 }
396
397 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
398         LPCWSTR szStatusText)
399 {
400     static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
401         '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
402     static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
403
404     switch(ulStatusCode) {
405     case BINDSTATUS_MIMETYPEAVAILABLE:
406         CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
407         ok(szStatusText != NULL, "szStatusText == NULL\n");
408         if(szStatusText) {
409             if(tested_protocol == BIND_TEST)
410                 ok(szStatusText == expect_wsz, "unexpected szStatusText\n");
411             else if (http_post_test)
412                 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
413                    !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
414                    "szStatusText != text/plain\n");
415             else
416                 ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) &&
417                    !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
418                    "szStatusText != text/html\n");
419         }
420         break;
421     case BINDSTATUS_DIRECTBIND:
422         CHECK_EXPECT2(ReportProgress_DIRECTBIND);
423         ok(szStatusText == NULL, "szStatusText != NULL\n");
424         break;
425     case BINDSTATUS_RAWMIMETYPE:
426         CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
427         ok(szStatusText != NULL, "szStatusText == NULL\n");
428         if(szStatusText)
429             ok(lstrlenW(szStatusText) < lstrlenW(text_htmlW) ||
430                !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
431                "szStatusText != text/html\n");
432         break;
433     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
434         CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
435         ok(szStatusText != NULL, "szStatusText == NULL\n");
436         if(szStatusText) {
437             if(binding_test)
438                 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText\n");
439             else if(tested_protocol == FILE_TEST)
440                 ok(!lstrcmpW(szStatusText, file_name), "szStatusText = \"%s\"\n", debugstr_w(szStatusText));
441             else
442                 ok(szStatusText != NULL, "szStatusText == NULL\n");
443         }
444         break;
445     case BINDSTATUS_FINDINGRESOURCE:
446         CHECK_EXPECT(ReportProgress_FINDINGRESOURCE);
447         ok(szStatusText != NULL, "szStatusText == NULL\n");
448         break;
449     case BINDSTATUS_CONNECTING:
450         CHECK_EXPECT(ReportProgress_CONNECTING);
451         ok(szStatusText != NULL, "szStatusText == NULL\n");
452         break;
453     case BINDSTATUS_SENDINGREQUEST:
454         CHECK_EXPECT(ReportProgress_SENDINGREQUEST);
455         if(tested_protocol == FILE_TEST) {
456             ok(szStatusText != NULL, "szStatusText == NULL\n");
457             if(szStatusText)
458                 ok(!*szStatusText, "wrong szStatusText\n");
459         }
460         break;
461     case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
462         CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
463         ok(szStatusText != NULL, "szStatusText == NULL\n");
464         if(szStatusText)
465             ok(!lstrcmpW(szStatusText, text_htmlW), "szStatusText != text/html\n");
466         break;
467     case BINDSTATUS_PROTOCOLCLASSID:
468         CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
469         ok(szStatusText != NULL, "szStatusText == NULL\n");
470         ok(!lstrcmpW(szStatusText, null_guid), "unexpected szStatusText\n");
471         break;
472     case BINDSTATUS_COOKIE_SENT:
473         CHECK_EXPECT(ReportProgress_COOKIE_SENT);
474         ok(szStatusText == NULL, "szStatusText != NULL\n");
475         break;
476     case BINDSTATUS_REDIRECTING:
477         CHECK_EXPECT(ReportProgress_REDIRECTING);
478         ok(szStatusText == NULL, "szStatusText = %s\n", debugstr_w(szStatusText));
479         break;
480     case BINDSTATUS_ENCODING:
481         CHECK_EXPECT(ReportProgress_ENCODING);
482         ok(!strcmp_wa(szStatusText, "gzip"), "szStatusText = %s\n", debugstr_w(szStatusText));
483         break;
484     case BINDSTATUS_ACCEPTRANGES:
485         CHECK_EXPECT(ReportProgress_ACCEPTRANGES);
486         ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText));
487         break;
488     case BINDSTATUS_PROXYDETECTING:
489         CHECK_EXPECT(ReportProgress_PROXYDETECTING);
490         SET_EXPECT(ReportProgress_CONNECTING);
491         ok(!szStatusText, "szStatusText = %s\n", debugstr_w(szStatusText));
492         break;
493     default:
494         ok(0, "Unexpected status %d\n", ulStatusCode);
495     };
496
497     return S_OK;
498 }
499
500 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
501         ULONG ulProgress, ULONG ulProgressMax)
502 {
503     if(tested_protocol == FILE_TEST) {
504         CHECK_EXPECT2(ReportData);
505
506         ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
507            ulProgress, ulProgressMax);
508         ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
509         ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION),
510                 "grcfBSCF = %08x\n", grfBSCF);
511     }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST)) {
512         if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
513             CHECK_EXPECT(ReportData);
514         else if (http_post_test)
515             ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
516
517         ok(ulProgress, "ulProgress == 0\n");
518
519         if(first_data_notif) {
520             ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
521                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
522                "grcfBSCF = %08x\n", grfBSCF);
523             first_data_notif = FALSE;
524         } else {
525             ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
526                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
527                || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
528                "grcfBSCF = %08x\n", grfBSCF);
529         }
530
531         if(!(bindf & BINDF_FROMURLMON) &&
532            !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
533             if(!state) {
534                 state = 1;
535                 if(http_is_first) {
536                     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
537                     CHECK_CALLED(ReportProgress_CONNECTING);
538                 } else todo_wine {
539                     CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
540                     CHECK_NOT_CALLED(ReportProgress_CONNECTING);
541                 }
542                 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
543                 CHECK_CALLED(OnResponse);
544                 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
545             }
546             SetEvent(event_complete);
547         }
548     }else {
549         BYTE buf[1000];
550         ULONG read;
551         HRESULT hres;
552
553         CHECK_EXPECT(ReportData);
554
555         if(tested_protocol == BIND_TEST)
556             return S_OK;
557
558         do {
559             SET_EXPECT(Read);
560             hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
561             CHECK_CALLED(Read);
562         }while(hres == S_OK);
563     }
564
565     return S_OK;
566 }
567
568 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
569         DWORD dwError, LPCWSTR szResult)
570 {
571     CHECK_EXPECT(ReportResult);
572
573     ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
574             hrResult, expect_hrResult);
575     if(SUCCEEDED(hrResult))
576         ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
577     else
578         ok(dwError != ERROR_SUCCESS, "dwError == ERROR_SUCCESS\n");
579     ok(!szResult, "szResult != NULL\n");
580
581     return S_OK;
582 }
583
584 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
585     ProtocolSink_QueryInterface,
586     ProtocolSink_AddRef,
587     ProtocolSink_Release,
588     ProtocolSink_Switch,
589     ProtocolSink_ReportProgress,
590     ProtocolSink_ReportData,
591     ProtocolSink_ReportResult
592 };
593
594 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
595
596 static HRESULT QueryInterface(REFIID riid, void **ppv)
597 {
598     *ppv = NULL;
599
600     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
601         *ppv = &protocol_sink;
602     if(IsEqualGUID(&IID_IServiceProvider, riid))
603         *ppv = &service_provider;
604
605     if(*ppv)
606         return S_OK;
607
608     return E_NOINTERFACE;
609 }
610
611 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
612 {
613     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
614         *ppv = iface;
615         return S_OK;
616     }
617     return E_NOINTERFACE;
618 }
619
620 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
621 {
622     return 2;
623 }
624
625 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
626 {
627     return 1;
628 }
629
630 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
631 {
632     DWORD cbSize;
633
634     static const CHAR szPostData[] = "mode=Test";
635
636     CHECK_EXPECT(GetBindInfo);
637
638     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
639     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
640     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
641
642     *grfBINDF = bindf;
643     if(binding_test)
644         *grfBINDF |= BINDF_FROMURLMON;
645     cbSize = pbindinfo->cbSize;
646     memset(pbindinfo, 0, cbSize);
647     pbindinfo->cbSize = cbSize;
648
649     if (http_post_test)
650     {
651         /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly
652          * with urlmon on native (Win98 and WinXP) */
653         U(pbindinfo->stgmedData).hGlobal = GlobalAlloc(GPTR, sizeof(szPostData));
654         if (!U(pbindinfo->stgmedData).hGlobal)
655         {
656             http_post_test = FALSE;
657             skip("Out of memory\n");
658             return E_OUTOFMEMORY;
659         }
660         lstrcpy((LPSTR)U(pbindinfo->stgmedData).hGlobal, szPostData);
661         pbindinfo->cbstgmedData = sizeof(szPostData)-1;
662         pbindinfo->dwBindVerb = BINDVERB_POST;
663         pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
664     }
665
666     return S_OK;
667 }
668
669 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
670         LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
671 {
672     ok(ppwzStr != NULL, "ppwzStr == NULL\n");
673     ok(pcElFetched != NULL, "pcElFetched == NULL\n");
674
675     switch(ulStringType) {
676     case BINDSTRING_ACCEPT_MIMES:
677         CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
678         ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
679         if(pcElFetched) {
680             ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
681             *pcElFetched = 1;
682         }
683         if(ppwzStr) {
684             *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
685             memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
686         }
687         return S_OK;
688     case BINDSTRING_USER_AGENT:
689         CHECK_EXPECT(GetBindString_USER_AGENT);
690         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
691         if(pcElFetched) {
692             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
693             *pcElFetched = 1;
694         }
695         if(ppwzStr) {
696             *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
697             memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
698         }
699         return S_OK;
700     case BINDSTRING_POST_COOKIE:
701         CHECK_EXPECT(GetBindString_POST_COOKIE);
702         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
703         if(pcElFetched)
704             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
705         return S_OK;
706     default:
707         ok(0, "unexpected call\n");
708     }
709
710     return E_NOTIMPL;
711 }
712
713 static IInternetBindInfoVtbl bind_info_vtbl = {
714     BindInfo_QueryInterface,
715     BindInfo_AddRef,
716     BindInfo_Release,
717     BindInfo_GetBindInfo,
718     BindInfo_GetBindString
719 };
720
721 static IInternetBindInfo bind_info = { &bind_info_vtbl };
722
723 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
724                                                   REFIID riid, void **ppv)
725 {
726     ok(0, "unexpected call\n");
727     return E_NOINTERFACE;
728 }
729
730 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
731 {
732     return 2;
733 }
734
735 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
736 {
737     return 1;
738 }
739
740 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
741 {
742     CHECK_EXPECT(SetPriority);
743     ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
744     return S_OK;
745 }
746
747 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
748 {
749     ok(0, "unexpected call\n");
750     return E_NOTIMPL;
751 }
752
753
754 static const IInternetPriorityVtbl InternetPriorityVtbl = {
755     InternetPriority_QueryInterface,
756     InternetPriority_AddRef,
757     InternetPriority_Release,
758     InternetPriority_SetPriority,
759     InternetPriority_GetPriority
760 };
761
762 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
763
764 static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
765 {
766     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
767         *ppv = iface;
768         return S_OK;
769     }
770
771     if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
772         trace("IID_IInternetProtocolEx not supported\n");
773         *ppv = NULL;
774         return E_NOINTERFACE;
775     }
776
777     if(IsEqualGUID(&IID_IInternetPriority, riid)) {
778         *ppv = &InternetPriority;
779         return S_OK;
780     }
781
782     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
783     *ppv = NULL;
784     return E_NOINTERFACE;
785 }
786
787 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
788 {
789     return 2;
790 }
791
792 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
793 {
794     return 1;
795 }
796
797 static DWORD WINAPI thread_proc(PVOID arg)
798 {
799     HRESULT hres;
800
801     memset(&protocoldata, -1, sizeof(protocoldata));
802
803     prot_state = 0;
804
805     SET_EXPECT(ReportProgress_FINDINGRESOURCE);
806     hres = IInternetProtocolSink_ReportProgress(binding_sink,
807             BINDSTATUS_FINDINGRESOURCE, hostW);
808     CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
809     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
810
811     SET_EXPECT(ReportProgress_CONNECTING);
812     hres = IInternetProtocolSink_ReportProgress(binding_sink,
813             BINDSTATUS_CONNECTING, winehq_ipW);
814     CHECK_CALLED(ReportProgress_CONNECTING);
815     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
816
817     SET_EXPECT(ReportProgress_SENDINGREQUEST);
818     hres = IInternetProtocolSink_ReportProgress(binding_sink,
819             BINDSTATUS_SENDINGREQUEST, NULL);
820     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
821     ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
822
823     prot_state = 1;
824     SET_EXPECT(Switch);
825     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
826     CHECK_CALLED(Switch);
827     ok(hres == S_OK, "Switch failed: %08x\n", hres);
828
829     prot_state = 2;
830     SET_EXPECT(Switch);
831     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
832     CHECK_CALLED(Switch);
833     ok(hres == S_OK, "Switch failed: %08x\n", hres);
834
835     prot_state = 2;
836     SET_EXPECT(Switch);
837     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
838     CHECK_CALLED(Switch);
839     ok(hres == S_OK, "Switch failed: %08x\n", hres);
840
841     prot_state = 3;
842     SET_EXPECT(Switch);
843     hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
844     CHECK_CALLED(Switch);
845     ok(hres == S_OK, "Switch failed: %08x\n", hres);
846
847     SetEvent(event_complete);
848
849     return 0;
850 }
851
852 static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
853         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
854         DWORD grfPI, DWORD dwReserved)
855 {
856     BINDINFO bindinfo, exp_bindinfo;
857     DWORD cbindf = 0;
858     HRESULT hres;
859
860     CHECK_EXPECT(Start);
861
862     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
863     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
864     ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
865     ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
866     ok(!grfPI, "grfPI = %x\n", grfPI);
867     ok(!dwReserved, "dwReserved = %d\n", dwReserved);
868
869     memset(&bindinfo, 0, sizeof(bindinfo));
870     bindinfo.cbSize = sizeof(bindinfo);
871     memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
872     SET_EXPECT(GetBindInfo);
873     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
874     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
875     CHECK_CALLED(GetBindInfo);
876     ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
877        cbindf, (bindf|BINDF_FROMURLMON));
878     ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
879     ReleaseBindInfo(&bindinfo);
880
881     SET_EXPECT(ReportProgress_SENDINGREQUEST);
882     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
883     ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
884     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
885
886     if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
887         IServiceProvider *service_provider;
888         IHttpNegotiate *http_negotiate;
889         IHttpNegotiate2 *http_negotiate2;
890         LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
891         LPWSTR additional_headers = NULL;
892         BYTE sec_id[100];
893         DWORD fetched = 0, size = 100;
894         DWORD tid;
895
896         SET_EXPECT(GetBindString_USER_AGENT);
897         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
898                                                &ua, 1, &fetched);
899         CHECK_CALLED(GetBindString_USER_AGENT);
900         ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
901         ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
902         ok(ua != NULL, "ua =  %p\n", ua);
903         ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", debugstr_w(ua));
904         CoTaskMemFree(ua);
905
906         fetched = 256;
907         SET_EXPECT(GetBindString_ACCEPT_MIMES);
908         hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
909                                                accept_mimes, 256, &fetched);
910         CHECK_CALLED(GetBindString_ACCEPT_MIMES);
911
912         ok(hres == S_OK,
913            "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
914         ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
915         ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", debugstr_w(accept_mimes[0]));
916
917         hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
918                                                 (void**)&service_provider);
919         ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
920
921         SET_EXPECT(QueryService_HttpNegotiate);
922         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
923                 &IID_IHttpNegotiate, (void**)&http_negotiate);
924         CHECK_CALLED(QueryService_HttpNegotiate);
925         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
926
927         SET_EXPECT(BeginningTransaction);
928         hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
929                                                    NULL, 0, &additional_headers);
930         CHECK_CALLED(BeginningTransaction);
931         IHttpNegotiate_Release(http_negotiate);
932         ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
933         ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
934
935         SET_EXPECT(QueryService_HttpNegotiate);
936         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
937                 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
938         CHECK_CALLED(QueryService_HttpNegotiate);
939         ok(hres == S_OK, "QueryService failed: %08x\n", hres);
940
941         size = 512;
942         SET_EXPECT(GetRootSecurityId);
943         hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
944         CHECK_CALLED(GetRootSecurityId);
945         IHttpNegotiate2_Release(http_negotiate2);
946         ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
947         ok(size == 13, "size=%d\n", size);
948
949         IServiceProvider_Release(service_provider);
950
951         CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
952
953         return S_OK;
954     }
955
956     SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
957     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
958             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
959     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
960     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
961
962     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
963     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
964                                                 expect_wsz = text_htmlW);
965     ok(hres == S_OK,
966        "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
967     CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
968
969     SET_EXPECT(ReportData);
970     hres = IInternetProtocolSink_ReportData(pOIProtSink,
971             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, 13, 13);
972     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
973     CHECK_CALLED(ReportData);
974
975     if(tested_protocol == BIND_TEST) {
976         hres = IInternetProtocol_Terminate(binding_protocol, 0);
977         ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
978     }
979
980     SET_EXPECT(ReportResult);
981     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
982     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
983     CHECK_CALLED(ReportResult);
984
985     return S_OK;
986 }
987
988 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
989         PROTOCOLDATA *pProtocolData)
990 {
991     DWORD bscf = 0;
992     HRESULT hres;
993
994     CHECK_EXPECT(Continue);
995
996     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
997     if(!pProtocolData || tested_protocol == BIND_TEST)
998         return S_OK;
999
1000     switch(prot_state) {
1001     case 1: {
1002         IServiceProvider *service_provider;
1003         IHttpNegotiate *http_negotiate;
1004         static WCHAR header[] = {'?',0};
1005
1006         hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
1007                                                     (void**)&service_provider);
1008         ok(hres == S_OK, "Could not get IServiceProvicder\n");
1009
1010         SET_EXPECT(QueryService_HttpNegotiate);
1011         hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1012                                              &IID_IHttpNegotiate, (void**)&http_negotiate);
1013         IServiceProvider_Release(service_provider);
1014         CHECK_CALLED(QueryService_HttpNegotiate);
1015         ok(hres == S_OK, "Could not get IHttpNegotiate\n");
1016
1017         SET_EXPECT(OnResponse);
1018         hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
1019         IHttpNegotiate_Release(http_negotiate);
1020         CHECK_CALLED(OnResponse);
1021         IHttpNegotiate_Release(http_negotiate);
1022         ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
1023
1024         SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1025         hres = IInternetProtocolSink_ReportProgress(binding_sink,
1026                 BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW);
1027         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1028         ok(hres == S_OK,
1029            "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
1030
1031         bscf |= BSCF_FIRSTDATANOTIFICATION;
1032         break;
1033     }
1034     case 2:
1035     case 3:
1036         bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
1037         break;
1038     }
1039
1040     SET_EXPECT(ReportData);
1041     hres = IInternetProtocolSink_ReportData(binding_sink, bscf, 100, 400);
1042     CHECK_CALLED(ReportData);
1043     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1044
1045     if(prot_state == 3)
1046         prot_state = 4;
1047
1048     return S_OK;
1049 }
1050
1051 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
1052         DWORD dwOptions)
1053 {
1054     ok(0, "unexpected call\n");
1055     return E_NOTIMPL;
1056 }
1057
1058 static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
1059 {
1060     CHECK_EXPECT(Terminate);
1061     ok(!dwOptions, "dwOptions=%d\n", dwOptions);
1062     return S_OK;
1063 }
1064
1065 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
1066 {
1067     ok(0, "unexpected call\n");
1068     return E_NOTIMPL;
1069 }
1070
1071 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
1072 {
1073     ok(0, "unexpected call\n");
1074     return E_NOTIMPL;
1075 }
1076
1077 static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv,
1078         ULONG cb, ULONG *pcbRead)
1079 {
1080     static BOOL b = TRUE;
1081
1082     CHECK_EXPECT(Read);
1083
1084     ok(pv == expect_pv, "pv != expect_pv\n");
1085     ok(cb == 1000, "cb=%d\n", cb);
1086     ok(pcbRead != NULL, "pcbRead == NULL\n");
1087     ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
1088
1089     if(prot_state == 3) {
1090         HRESULT hres;
1091
1092         SET_EXPECT(ReportResult);
1093         hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1094         CHECK_CALLED(ReportResult);
1095
1096         return S_FALSE;
1097     }
1098
1099     if((b = !b))
1100         return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
1101
1102     memset(pv, 'x', 100);
1103     prot_read += *pcbRead = 100;
1104     return S_OK;
1105 }
1106
1107 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
1108         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1109 {
1110     ok(0, "unexpected call\n");
1111     return E_NOTIMPL;
1112 }
1113
1114 static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
1115 {
1116     CHECK_EXPECT(LockRequest);
1117     ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
1118     return S_OK;
1119 }
1120
1121 static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface)
1122 {
1123     CHECK_EXPECT(UnlockRequest);
1124     return S_OK;
1125 }
1126
1127 static const IInternetProtocolVtbl ProtocolVtbl = {
1128     Protocol_QueryInterface,
1129     Protocol_AddRef,
1130     Protocol_Release,
1131     Protocol_Start,
1132     Protocol_Continue,
1133     Protocol_Abort,
1134     Protocol_Terminate,
1135     Protocol_Suspend,
1136     Protocol_Resume,
1137     Protocol_Read,
1138     Protocol_Seek,
1139     Protocol_LockRequest,
1140     Protocol_UnlockRequest
1141 };
1142
1143 static IInternetProtocol Protocol = { &ProtocolVtbl };
1144
1145 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
1146 {
1147     ok(0, "unexpected call\n");
1148     return E_NOINTERFACE;
1149 }
1150
1151 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
1152 {
1153     return 2;
1154 }
1155
1156 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
1157 {
1158     return 1;
1159 }
1160
1161 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
1162                                         REFIID riid, void **ppv)
1163 {
1164     CHECK_EXPECT(CreateInstance);
1165
1166     ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
1167     ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
1168     ok(ppv != NULL, "ppv == NULL\n");
1169
1170     *ppv = &Protocol;
1171     return S_OK;
1172 }
1173
1174 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
1175 {
1176     ok(0, "unexpected call\n");
1177     return S_OK;
1178 }
1179
1180 static const IClassFactoryVtbl ClassFactoryVtbl = {
1181     ClassFactory_QueryInterface,
1182     ClassFactory_AddRef,
1183     ClassFactory_Release,
1184     ClassFactory_CreateInstance,
1185     ClassFactory_LockServer
1186 };
1187
1188 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
1189
1190 static void test_priority(IInternetProtocol *protocol)
1191 {
1192     IInternetPriority *priority;
1193     LONG pr;
1194     HRESULT hres;
1195
1196     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
1197                                             (void**)&priority);
1198     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
1199     if(FAILED(hres))
1200         return;
1201
1202     hres = IInternetPriority_GetPriority(priority, &pr);
1203     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1204     ok(pr == 0, "pr=%d, expected 0\n", pr);
1205
1206     hres = IInternetPriority_SetPriority(priority, 1);
1207     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1208
1209     hres = IInternetPriority_GetPriority(priority, &pr);
1210     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1211     ok(pr == 1, "pr=%d, expected 1\n", pr);
1212
1213     IInternetPriority_Release(priority);
1214 }
1215
1216 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url, BOOL is_first)
1217 {
1218     HRESULT hres;
1219
1220     SET_EXPECT(GetBindInfo);
1221     if(!(bindf & BINDF_FROMURLMON))
1222        SET_EXPECT(ReportProgress_DIRECTBIND);
1223     if(is_first) {
1224         SET_EXPECT(ReportProgress_SENDINGREQUEST);
1225         SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1226         if(bindf & BINDF_FROMURLMON)
1227             SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
1228         else
1229             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1230     }
1231     SET_EXPECT(ReportData);
1232     if(is_first)
1233         SET_EXPECT(ReportResult);
1234
1235     expect_hrResult = S_OK;
1236
1237     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
1238     if(hres == INET_E_RESOURCE_NOT_FOUND) {
1239         win_skip("Start failed\n");
1240         return FALSE;
1241     }
1242     ok(hres == S_OK, "Start failed: %08x\n", hres);
1243
1244     CHECK_CALLED(GetBindInfo);
1245     if(!(bindf & BINDF_FROMURLMON))
1246        CHECK_CALLED(ReportProgress_DIRECTBIND);
1247     if(is_first) {
1248         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1249         CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1250         if(bindf & BINDF_FROMURLMON)
1251             CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
1252         else
1253             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1254     }
1255     CHECK_CALLED(ReportData);
1256     if(is_first)
1257         CHECK_CALLED(ReportResult);
1258
1259     return TRUE;
1260 }
1261
1262 static void test_file_protocol_url(LPCWSTR url)
1263 {
1264     IInternetProtocolInfo *protocol_info;
1265     IUnknown *unk;
1266     IClassFactory *factory;
1267     HRESULT hres;
1268
1269     hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
1270             &IID_IUnknown, (void**)&unk);
1271     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1272     if(FAILED(hres))
1273         return;
1274
1275     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1276     ok(hres == E_NOINTERFACE,
1277             "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
1278
1279     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1280     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1281     if(SUCCEEDED(hres)) {
1282         IInternetProtocol *protocol;
1283         BYTE buf[512];
1284         ULONG cb;
1285         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1286         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1287
1288         if(SUCCEEDED(hres)) {
1289             if(file_protocol_start(protocol, url, TRUE)) {
1290                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1291                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1292                 ok(cb == 2, "cb=%u expected 2\n", cb);
1293                 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
1294                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1295                 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
1296                 ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
1297                 ok(cb == 0, "cb=%u expected 0\n", cb);
1298                 hres = IInternetProtocol_UnlockRequest(protocol);
1299                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1300             }
1301
1302             if(file_protocol_start(protocol, url, FALSE)) {
1303                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1304                 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1305                 hres = IInternetProtocol_LockRequest(protocol, 0);
1306                 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1307                 hres = IInternetProtocol_UnlockRequest(protocol);
1308                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1309             }
1310
1311             IInternetProtocol_Release(protocol);
1312         }
1313
1314         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1315         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1316
1317         if(SUCCEEDED(hres)) {
1318             if(file_protocol_start(protocol, url, TRUE)) {
1319                 hres = IInternetProtocol_LockRequest(protocol, 0);
1320                 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1321                 hres = IInternetProtocol_Terminate(protocol, 0);
1322                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1323                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1324                 ok(hres == S_OK, "Read failed: %08x\n\n", hres);
1325                 hres = IInternetProtocol_UnlockRequest(protocol);
1326                 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1327                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1328                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1329                 hres = IInternetProtocol_Terminate(protocol, 0);
1330                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1331             }
1332
1333             IInternetProtocol_Release(protocol);
1334         }
1335
1336         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1337         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1338
1339         if(SUCCEEDED(hres)) {
1340             if(file_protocol_start(protocol, url, TRUE)) {
1341                 hres = IInternetProtocol_Terminate(protocol, 0);
1342                 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1343                 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1344                 ok(hres == S_OK, "Read failed: %08x\n", hres);
1345                 ok(cb == 2, "cb=%u expected 2\n", cb);
1346             }
1347
1348             IInternetProtocol_Release(protocol);
1349         }
1350
1351         IClassFactory_Release(factory);
1352     }
1353
1354     IUnknown_Release(unk);
1355 }
1356
1357 static void test_file_protocol_fail(void)
1358 {
1359     IInternetProtocol *protocol;
1360     HRESULT hres;
1361
1362     static const WCHAR index_url2[] =
1363         {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
1364
1365     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1366             &IID_IInternetProtocol, (void**)&protocol);
1367     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1368     if(FAILED(hres))
1369         return;
1370
1371     SET_EXPECT(GetBindInfo);
1372     expect_hrResult = MK_E_SYNTAX;
1373     hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
1374     ok(hres == MK_E_SYNTAX ||
1375        hres == E_INVALIDARG,
1376        "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres);
1377     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
1378
1379     SET_EXPECT(GetBindInfo);
1380     if(!(bindf & BINDF_FROMURLMON))
1381         SET_EXPECT(ReportProgress_DIRECTBIND);
1382     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1383     SET_EXPECT(ReportResult);
1384     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1385     hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
1386     ok(hres == INET_E_RESOURCE_NOT_FOUND,
1387             "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1388     CHECK_CALLED(GetBindInfo);
1389     if(!(bindf & BINDF_FROMURLMON))
1390         CHECK_CALLED(ReportProgress_DIRECTBIND);
1391     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1392     CHECK_CALLED(ReportResult);
1393
1394     IInternetProtocol_Release(protocol);
1395
1396     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1397             &IID_IInternetProtocol, (void**)&protocol);
1398     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1399     if(FAILED(hres))
1400         return;
1401
1402     SET_EXPECT(GetBindInfo);
1403     if(!(bindf & BINDF_FROMURLMON))
1404         SET_EXPECT(ReportProgress_DIRECTBIND);
1405     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1406     SET_EXPECT(ReportResult);
1407     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1408
1409     hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
1410     ok(hres == INET_E_RESOURCE_NOT_FOUND,
1411             "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1412     CHECK_CALLED(GetBindInfo);
1413     if(!(bindf & BINDF_FROMURLMON))
1414         CHECK_CALLED(ReportProgress_DIRECTBIND);
1415     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1416     CHECK_CALLED(ReportResult);
1417
1418     SET_EXPECT(GetBindInfo);
1419     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
1420     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1421     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
1422
1423     SET_EXPECT(GetBindInfo);
1424     hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0);
1425     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1426     CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
1427
1428     IInternetProtocol_Release(protocol);
1429 }
1430
1431 static void test_file_protocol(void) {
1432     WCHAR buf[INTERNET_MAX_URL_LENGTH], file_name_buf[MAX_PATH];
1433     DWORD size;
1434     ULONG len;
1435     HANDLE file;
1436
1437     static const WCHAR wszFile[] = {'f','i','l','e',':',0};
1438     static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
1439     static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
1440     static const char html_doc[] = "<HTML></HTML>";
1441
1442     trace("Testing file protocol...\n");
1443     tested_protocol = FILE_TEST;
1444
1445     SetLastError(0xdeadbeef);
1446     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1447             FILE_ATTRIBUTE_NORMAL, NULL);
1448     if(!file && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1449     {
1450         win_skip("Detected Win9x or WinMe\n");
1451         return;
1452     }
1453     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1454     if(file == INVALID_HANDLE_VALUE)
1455         return;
1456     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
1457     CloseHandle(file);
1458
1459     file_name = wszIndexHtml;
1460     bindf = 0;
1461     test_file_protocol_url(index_url);
1462     bindf = BINDF_FROMURLMON;
1463     test_file_protocol_url(index_url);
1464     bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
1465     test_file_protocol_url(index_url);
1466
1467     memcpy(buf, wszFile, sizeof(wszFile));
1468     len = sizeof(wszFile)/sizeof(WCHAR)-1;
1469     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1470     buf[len++] = '\\';
1471     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1472
1473     file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
1474     bindf = 0;
1475     test_file_protocol_url(buf);
1476     bindf = BINDF_FROMURLMON;
1477     test_file_protocol_url(buf);
1478
1479     memcpy(buf, wszFile2, sizeof(wszFile2));
1480     len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
1481     file_name_buf[len++] = '\\';
1482     memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1483     lstrcpyW(buf+sizeof(wszFile2)/sizeof(WCHAR)-1, file_name_buf);
1484     file_name = file_name_buf;
1485     bindf = 0;
1486     test_file_protocol_url(buf);
1487     bindf = BINDF_FROMURLMON;
1488     test_file_protocol_url(buf);
1489
1490     buf[sizeof(wszFile2)/sizeof(WCHAR)] = '|';
1491     test_file_protocol_url(buf);
1492
1493     memcpy(buf, wszFile3, sizeof(wszFile3));
1494     len = sizeof(wszFile3)/sizeof(WCHAR)-1;
1495     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1496     buf[len++] = '\\';
1497     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1498
1499     file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
1500     bindf = 0;
1501     test_file_protocol_url(buf);
1502     bindf = BINDF_FROMURLMON;
1503     test_file_protocol_url(buf);
1504
1505     DeleteFileW(wszIndexHtml);
1506
1507     bindf = 0;
1508     test_file_protocol_fail();
1509     bindf = BINDF_FROMURLMON;
1510     test_file_protocol_fail();
1511 }
1512
1513 static BOOL http_protocol_start(LPCWSTR url, BOOL is_first)
1514 {
1515     static BOOL got_user_agent = FALSE;
1516     HRESULT hres;
1517
1518     first_data_notif = TRUE;
1519     state = 0;
1520
1521     SET_EXPECT(GetBindInfo);
1522     if (!(bindf & BINDF_FROMURLMON))
1523         SET_EXPECT(ReportProgress_DIRECTBIND);
1524     SET_EXPECT(GetBindString_USER_AGENT);
1525     SET_EXPECT(GetBindString_ACCEPT_MIMES);
1526     SET_EXPECT(QueryService_HttpNegotiate);
1527     SET_EXPECT(BeginningTransaction);
1528     SET_EXPECT(GetRootSecurityId);
1529     if (http_post_test)
1530         SET_EXPECT(GetBindString_POST_COOKIE);
1531
1532     hres = IInternetProtocol_Start(http_protocol, url, &protocol_sink, &bind_info, 0, 0);
1533     ok(hres == S_OK, "Start failed: %08x\n", hres);
1534     if(FAILED(hres))
1535         return FALSE;
1536
1537     CHECK_CALLED(GetBindInfo);
1538     if (!(bindf & BINDF_FROMURLMON))
1539         CHECK_CALLED(ReportProgress_DIRECTBIND);
1540     if (!got_user_agent)
1541     {
1542         CHECK_CALLED(GetBindString_USER_AGENT);
1543         got_user_agent = TRUE;
1544     }
1545     else todo_wine
1546     {
1547         /* user agent only retrieved once, even with different URLs */
1548         CHECK_NOT_CALLED(GetBindString_USER_AGENT);
1549     }
1550     CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1551     CHECK_CALLED(QueryService_HttpNegotiate);
1552     CHECK_CALLED(BeginningTransaction);
1553     /* GetRootSecurityId called on WinXP but not on Win98 */
1554     CLEAR_CALLED(GetRootSecurityId);
1555     if (http_post_test)
1556         CHECK_CALLED(GetBindString_POST_COOKIE);
1557
1558     return TRUE;
1559 }
1560
1561 /* is_first refers to whether this is the first call to this function
1562  * _for this url_ */
1563 static void test_http_protocol_url(LPCWSTR url, BOOL is_https, BOOL is_first)
1564 {
1565     IInternetProtocolInfo *protocol_info;
1566     IClassFactory *factory;
1567     IUnknown *unk;
1568     HRESULT hres;
1569
1570     http_url = url;
1571     http_is_first = is_first;
1572
1573     hres = CoGetClassObject(is_https ? &CLSID_HttpSProtocol : &CLSID_HttpProtocol,
1574             CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
1575     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1576     if(FAILED(hres))
1577         return;
1578
1579     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1580     ok(hres == E_NOINTERFACE,
1581         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1582         hres);
1583
1584     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1585     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1586     IUnknown_Release(unk);
1587     if(FAILED(hres))
1588         return;
1589
1590     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1591                                         (void**)&http_protocol);
1592     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1593     if(SUCCEEDED(hres)) {
1594         BYTE buf[3600];
1595         DWORD cb;
1596
1597         test_priority(http_protocol);
1598
1599         SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1600         SET_EXPECT(ReportProgress_CONNECTING);
1601         SET_EXPECT(ReportProgress_SENDINGREQUEST);
1602         SET_EXPECT(ReportProgress_PROXYDETECTING);
1603         if(! is_https)
1604             SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1605         if(!(bindf & BINDF_FROMURLMON)) {
1606             SET_EXPECT(OnResponse);
1607             SET_EXPECT(ReportProgress_RAWMIMETYPE);
1608             SET_EXPECT(ReportData);
1609         } else {
1610             SET_EXPECT(Switch);
1611         }
1612
1613         if(!http_protocol_start(url, is_first))
1614             return;
1615
1616         SET_EXPECT(ReportResult);
1617         expect_hrResult = S_OK;
1618
1619         hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb);
1620         ok((hres == E_PENDING && cb==0) ||
1621            (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
1622
1623         WaitForSingleObject(event_complete, INFINITE);
1624         if(bindf & BINDF_FROMURLMON)
1625             CHECK_CALLED(Switch);
1626         else
1627             CHECK_CALLED(ReportData);
1628
1629         while(1) {
1630             if(bindf & BINDF_FROMURLMON)
1631                 SET_EXPECT(Switch);
1632             else
1633                 SET_EXPECT(ReportData);
1634             hres = IInternetProtocol_Read(http_protocol, buf, sizeof(buf), &cb);
1635             if(hres == E_PENDING) {
1636                 hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb);
1637                 ok((hres == E_PENDING && cb==0) ||
1638                    (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
1639                 WaitForSingleObject(event_complete, INFINITE);
1640                 if(bindf & BINDF_FROMURLMON)
1641                     CHECK_CALLED(Switch);
1642                 else
1643                     CHECK_CALLED(ReportData);
1644             } else {
1645                 if(bindf & BINDF_FROMURLMON)
1646                     CHECK_NOT_CALLED(Switch);
1647                 else
1648                     CHECK_NOT_CALLED(ReportData);
1649                 if(cb == 0) break;
1650             }
1651         }
1652         ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1653         CHECK_CALLED(ReportResult);
1654
1655         hres = IInternetProtocol_LockRequest(http_protocol, 0);
1656         ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1657
1658         hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb);
1659         ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1660
1661         hres = IInternetProtocol_Terminate(http_protocol, 0);
1662         ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1663
1664         /* This wait is to give the internet handles being freed in Terminate
1665          * enough time to actually terminate in all cases. Internet handles
1666          * terminate asynchronously and native reuses the main InternetOpen
1667          * handle. The only case in which this seems to be necessary is on
1668          * wine with native wininet and urlmon, resulting in the next time
1669          * test_http_protocol_url being called the first data notification actually
1670          * being an extra last data notification from the previous connection
1671          * about once out of every ten times. */
1672         Sleep(100);
1673
1674         hres = IInternetProtocol_UnlockRequest(http_protocol);
1675         ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1676
1677         IInternetProtocol_Release(http_protocol);
1678     }
1679
1680     IClassFactory_Release(factory);
1681 }
1682
1683 static void test_http_protocol(void)
1684 {
1685     static const WCHAR winehq_url[] =
1686         {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
1687             'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
1688     static const WCHAR posttest_url[] =
1689         {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.',
1690          'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/',
1691          'p','o','s','t','t','e','s','t','.','p','h','p',0};
1692
1693     trace("Testing http protocol (not from urlmon)...\n");
1694     tested_protocol = HTTP_TEST;
1695     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
1696     test_http_protocol_url(winehq_url, FALSE, TRUE);
1697
1698     trace("Testing http protocol (from urlmon)...\n");
1699     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
1700     test_http_protocol_url(winehq_url, FALSE, FALSE);
1701
1702     trace("Testing http protocol (to file)...\n");
1703     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE;
1704     test_http_protocol_url(winehq_url, FALSE, FALSE);
1705
1706     trace("Testing http protocol (post data)...\n");
1707     http_post_test = TRUE;
1708     /* Without this flag we get a ReportProgress_CACHEFILENAMEAVAILABLE
1709      * notification with BINDVERB_POST */
1710     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
1711     test_http_protocol_url(posttest_url, FALSE, TRUE);
1712     http_post_test = FALSE;
1713 }
1714
1715 static void test_https_protocol(void)
1716 {
1717     static const WCHAR codeweavers_url[] =
1718         {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
1719          '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0};
1720
1721     trace("Testing https protocol (from urlmon)...\n");
1722     tested_protocol = HTTPS_TEST;
1723     bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
1724     test_http_protocol_url(codeweavers_url, TRUE, TRUE);
1725 }
1726
1727 static void test_mk_protocol(void)
1728 {
1729     IInternetProtocolInfo *protocol_info;
1730     IInternetProtocol *protocol;
1731     IClassFactory *factory;
1732     IUnknown *unk;
1733     HRESULT hres;
1734
1735     static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
1736                                        ':',':','/','t','e','s','t','.','h','t','m','l',0};
1737     static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
1738
1739     trace("Testing mk protocol...\n");
1740     tested_protocol = MK_TEST;
1741
1742     hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
1743             &IID_IUnknown, (void**)&unk);
1744     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1745
1746     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1747     ok(hres == E_NOINTERFACE,
1748         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1749         hres);
1750
1751     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1752     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1753     IUnknown_Release(unk);
1754     if(FAILED(hres))
1755         return;
1756
1757     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1758                                         (void**)&protocol);
1759     IClassFactory_Release(factory);
1760     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1761
1762     SET_EXPECT(GetBindInfo);
1763     hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
1764     ok(hres == MK_E_SYNTAX || hres == INET_E_INVALID_URL,
1765        "Start failed: %08x, expected MK_E_SYNTAX or INET_E_INVALID_URL\n", hres);
1766     CLEAR_CALLED(GetBindInfo);
1767
1768     SET_EXPECT(GetBindInfo);
1769     SET_EXPECT(ReportProgress_DIRECTBIND);
1770     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1771     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1772     SET_EXPECT(ReportResult);
1773     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1774
1775     hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
1776     ok(hres == INET_E_RESOURCE_NOT_FOUND ||
1777        hres == INET_E_INVALID_URL, /* win2k3 */
1778        "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND or INET_E_INVALID_URL\n", hres);
1779
1780     if (hres == INET_E_RESOURCE_NOT_FOUND) {
1781         CHECK_CALLED(GetBindInfo);
1782         CLEAR_CALLED(ReportProgress_DIRECTBIND);
1783         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1784         CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1785         CHECK_CALLED(ReportResult);
1786     }else {
1787         CLEAR_CALLED(GetBindInfo);
1788         CLEAR_CALLED(ReportProgress_DIRECTBIND);
1789         CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
1790         CLEAR_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1791         CLEAR_CALLED(ReportResult);
1792     }
1793
1794     IInternetProtocol_Release(protocol);
1795 }
1796
1797 static void test_CreateBinding(void)
1798 {
1799     IInternetProtocolSink *sink;
1800     IInternetProtocol *protocol;
1801     IInternetPriority *priority;
1802     IInternetSession *session;
1803     LONG p;
1804     BYTE buf[1000];
1805     DWORD read;
1806     HRESULT hres;
1807
1808     static const WCHAR test_url[] =
1809         {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
1810     static const WCHAR wsz_test[] = {'t','e','s','t',0};
1811
1812     trace("Testing CreateBinding...\n");
1813     tested_protocol = BIND_TEST;
1814     binding_test = TRUE;
1815
1816     hres = CoInternetGetSession(0, &session, 0);
1817     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
1818
1819     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
1820     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
1821
1822     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
1823     binding_protocol = protocol;
1824     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
1825     ok(protocol != NULL, "protocol == NULL\n");
1826
1827     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
1828     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
1829
1830     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&sink);
1831     ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres);
1832
1833     hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
1834     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1835     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
1836     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1837     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
1838     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1839
1840     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
1841     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
1842
1843     p = 0xdeadbeef;
1844     hres = IInternetPriority_GetPriority(priority, &p);
1845     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1846     ok(!p, "p=%d\n", p);
1847
1848     ex_priority = 100;
1849     hres = IInternetPriority_SetPriority(priority, 100);
1850     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1851
1852     p = 0xdeadbeef;
1853     hres = IInternetPriority_GetPriority(priority, &p);
1854     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1855     ok(p == 100, "p=%d\n", p);
1856
1857     SET_EXPECT(QueryService_InternetProtocol);
1858     SET_EXPECT(CreateInstance);
1859     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
1860     SET_EXPECT(SetPriority);
1861     SET_EXPECT(Start);
1862
1863     expect_hrResult = S_OK;
1864     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
1865     ok(hres == S_OK, "Start failed: %08x\n", hres);
1866
1867     CHECK_CALLED(QueryService_InternetProtocol);
1868     CHECK_CALLED(CreateInstance);
1869     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
1870     CHECK_CALLED(SetPriority);
1871     CHECK_CALLED(Start);
1872
1873     SET_EXPECT(Read);
1874     read = 0xdeadbeef;
1875     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
1876     ok(hres == S_OK, "Read failed: %08x\n", hres);
1877     ok(read == 100, "read = %d\n", read);
1878     CHECK_CALLED(Read);
1879
1880     SET_EXPECT(Read);
1881     read = 0xdeadbeef;
1882     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
1883     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1884     ok(!read, "read = %d\n", read);
1885     CHECK_CALLED(Read);
1886
1887     p = 0xdeadbeef;
1888     hres = IInternetPriority_GetPriority(priority, &p);
1889     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1890     ok(p == 100, "p=%d\n", p);
1891
1892     hres = IInternetPriority_SetPriority(priority, 101);
1893     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1894
1895     SET_EXPECT(Terminate);
1896     hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
1897     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1898     CHECK_CALLED(Terminate);
1899
1900     SET_EXPECT(Continue);
1901     hres = IInternetProtocolSink_Switch(sink, &protocoldata);
1902     ok(hres == S_OK, "Switch failed: %08x\n", hres);
1903     CHECK_CALLED(Continue);
1904
1905     hres = IInternetProtocolSink_ReportProgress(sink,
1906             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1907     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1908
1909     hres = IInternetProtocolSink_ReportResult(sink, S_OK, ERROR_SUCCESS, NULL);
1910     ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres);
1911
1912     hres = IInternetProtocolSink_ReportData(sink, 0, 0, 0);
1913     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1914
1915     IInternetProtocolSink_Release(sink);
1916     IInternetPriority_Release(priority);
1917     IInternetBindInfo_Release(prot_bind_info);
1918     IInternetProtocol_Release(protocol);
1919     IInternetSession_Release(session);
1920 }
1921
1922 static void test_binding(int prot)
1923 {
1924     IInternetProtocol *protocol;
1925     IInternetSession *session;
1926     ULONG ref;
1927     HRESULT hres;
1928
1929     trace("Testing %s binding...\n", debugstr_w(protocol_names[prot]));
1930
1931     tested_protocol = prot;
1932     binding_test = TRUE;
1933     first_data_notif = TRUE;
1934     prot_read = 0;
1935
1936     hres = CoInternetGetSession(0, &session, 0);
1937     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
1938
1939     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, protocol_names[prot], 0, NULL, 0);
1940     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
1941
1942     hres = IInternetSession_CreateBinding(session, NULL, binding_urls[prot], NULL, NULL, &protocol, 0);
1943     binding_protocol = protocol;
1944     IInternetSession_Release(session);
1945     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
1946     ok(protocol != NULL, "protocol == NULL\n");
1947
1948     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
1949     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
1950
1951     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
1952     ok(hres == S_OK, "QueryInterface(IID_IInternetProtocolSink) failed: %08x\n", hres);
1953
1954     ex_priority = 0;
1955     SET_EXPECT(QueryService_InternetProtocol);
1956     SET_EXPECT(CreateInstance);
1957     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
1958     SET_EXPECT(SetPriority);
1959     SET_EXPECT(Start);
1960
1961     expect_hrResult = S_OK;
1962     hres = IInternetProtocol_Start(protocol, binding_urls[prot], &protocol_sink, &bind_info, 0, 0);
1963     ok(hres == S_OK, "Start failed: %08x\n", hres);
1964
1965     CHECK_CALLED(QueryService_InternetProtocol);
1966     CHECK_CALLED(CreateInstance);
1967     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
1968     CHECK_CALLED(SetPriority);
1969     CHECK_CALLED(Start);
1970
1971     if(prot == HTTP_TEST || prot == HTTPS_TEST) {
1972         while(prot_state < 4) {
1973             WaitForSingleObject(event_complete, INFINITE);
1974             SET_EXPECT(Continue);
1975             IInternetProtocol_Continue(protocol, pdata);
1976             CHECK_CALLED(Continue);
1977             SetEvent(event_complete2);
1978         }
1979
1980         WaitForSingleObject(event_complete, INFINITE);
1981     }else {
1982         SET_EXPECT(LockRequest);
1983         hres = IInternetProtocol_LockRequest(protocol, 0);
1984         ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1985         CHECK_CALLED(LockRequest);
1986
1987         SET_EXPECT(UnlockRequest);
1988         hres = IInternetProtocol_UnlockRequest(protocol);
1989         ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1990         CHECK_CALLED(UnlockRequest);
1991     }
1992
1993     SET_EXPECT(Terminate);
1994     hres = IInternetProtocol_Terminate(protocol, 0);
1995     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1996     CHECK_CALLED(Terminate);
1997
1998     IInternetBindInfo_Release(prot_bind_info);
1999     IInternetProtocolSink_Release(binding_sink);
2000     ref = IInternetProtocol_Release(protocol);
2001     ok(!ref, "ref=%u, expected 0\n", ref);
2002 }
2003
2004 START_TEST(protocol)
2005 {
2006     OleInitialize(NULL);
2007
2008     event_complete = CreateEvent(NULL, FALSE, FALSE, NULL);
2009     event_complete2 = CreateEvent(NULL, FALSE, FALSE, NULL);
2010
2011     test_file_protocol();
2012     test_http_protocol();
2013     test_https_protocol();
2014     test_mk_protocol();
2015     test_CreateBinding();
2016     test_binding(FILE_TEST);
2017     test_binding(HTTP_TEST);
2018
2019     CloseHandle(event_complete);
2020     CloseHandle(event_complete2);
2021
2022     OleUninitialize();
2023 }