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