mcicda: Exclude unused headers.
[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
25 #include "windef.h"
26 #include "winbase.h"
27 #include "ole2.h"
28 #include "urlmon.h"
29
30 #include "initguid.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_EXPECT(func) \
39     do { \
40         ok(expect_ ##func, "unexpected call " #func "\n"); \
41         expect_ ## func = FALSE; \
42         called_ ## func = TRUE; \
43     }while(0)
44
45 #define CHECK_EXPECT2(func) \
46     do { \
47         ok(expect_ ##func, "unexpected call " #func  "\n"); \
48         called_ ## func = TRUE; \
49     }while(0)
50
51 #define CHECK_CALLED(func) \
52     do { \
53         ok(called_ ## func, "expected " #func "\n"); \
54         expect_ ## func = called_ ## func = FALSE; \
55     }while(0)
56
57 DEFINE_EXPECT(GetBindInfo);
58 DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
59 DEFINE_EXPECT(ReportProgress_DIRECTBIND);
60 DEFINE_EXPECT(ReportProgress_FINDINGRESOURCE);
61 DEFINE_EXPECT(ReportProgress_CONNECTING);
62 DEFINE_EXPECT(ReportProgress_SENDINGREQUEST);
63 DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
64 DEFINE_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
65 DEFINE_EXPECT(ReportProgress_PROTOCOLCLASSID);
66 DEFINE_EXPECT(ReportData);
67 DEFINE_EXPECT(ReportResult);
68 DEFINE_EXPECT(GetBindString_ACCEPT_MIMES);
69 DEFINE_EXPECT(GetBindString_USER_AGENT);
70 DEFINE_EXPECT(QueryService_HttpNegotiate);
71 DEFINE_EXPECT(QueryService_InternetProtocol);
72 DEFINE_EXPECT(BeginningTransaction);
73 DEFINE_EXPECT(GetRootSecurityId);
74 DEFINE_EXPECT(OnResponse);
75 DEFINE_EXPECT(Switch);
76 DEFINE_EXPECT(CreateInstance);
77 DEFINE_EXPECT(Start);
78 DEFINE_EXPECT(Terminate);
79 DEFINE_EXPECT(Read);
80 DEFINE_EXPECT(SetPriority);
81
82 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
83 static const WCHAR index_url[] =
84     {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
85
86 static HRESULT expect_hrResult;
87 static LPCWSTR file_name, http_url, expect_wsz;
88 static IInternetProtocol *http_protocol = NULL;
89 static BOOL first_data_notif = FALSE;
90 static HWND protocol_hwnd;
91 static int state = 0;
92 static DWORD bindf = 0;
93 static IInternetBindInfo *prot_bind_info;
94 static void *expect_pv;
95
96 static enum {
97     FILE_TEST,
98     HTTP_TEST,
99     MK_TEST,
100     BIND_TEST
101 } tested_protocol;
102
103 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
104 {
105     if(IsEqualGUID(&IID_IUnknown, riid)
106             || IsEqualGUID(&IID_IHttpNegotiate, riid)
107             || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
108         *ppv = iface;
109         return S_OK;
110     }
111
112     ok(0, "unexpected call\n");
113     return E_NOINTERFACE;
114 }
115
116 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
117 {
118     return 2;
119 }
120
121 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
122 {
123     return 1;
124 }
125
126 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
127         LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
128 {
129     CHECK_EXPECT(BeginningTransaction);
130
131     ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
132     ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
133     ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
134     if(pszAdditionalHeaders)
135         ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
136
137     return S_OK;
138 }
139
140 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
141         LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
142 {
143     CHECK_EXPECT(OnResponse);
144
145     ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
146     ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
147     ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
148     ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
149
150     return S_OK;
151 }
152
153 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
154         BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
155 {
156     static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
157     
158     CHECK_EXPECT(GetRootSecurityId);
159
160     ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
161     ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
162     ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
163
164     if(pcbSecurityId) {
165         ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
166         *pcbSecurityId = sizeof(sec_id);
167     }
168
169     if(pbSecurityId)
170         memcpy(pbSecurityId, sec_id, sizeof(sec_id));
171
172     return E_FAIL;
173 }
174
175 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
176     HttpNegotiate_QueryInterface,
177     HttpNegotiate_AddRef,
178     HttpNegotiate_Release,
179     HttpNegotiate_BeginningTransaction,
180     HttpNegotiate_OnResponse,
181     HttpNegotiate_GetRootSecurityId
182 };
183
184 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
185
186 static HRESULT QueryInterface(REFIID,void**);
187
188 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
189 {
190     return QueryInterface(riid, ppv);
191 }
192
193 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
194 {
195     return 2;
196 }
197
198 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
199 {
200     return 1;
201 }
202
203 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
204         REFIID riid, void **ppv)
205 {
206     if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
207         CHECK_EXPECT2(QueryService_HttpNegotiate);
208         return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
209     }
210
211     if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
212         ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
213         CHECK_EXPECT(QueryService_InternetProtocol);
214         return E_NOINTERFACE;
215     }
216
217     ok(0, "unexpected call\n");
218     return E_FAIL;
219 }
220
221 static const IServiceProviderVtbl ServiceProviderVtbl = {
222     ServiceProvider_QueryInterface,
223     ServiceProvider_AddRef,
224     ServiceProvider_Release,
225     ServiceProvider_QueryService
226 };
227
228 static IServiceProvider service_provider = { &ServiceProviderVtbl };
229
230 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
231 {
232     return QueryInterface(riid, ppv);
233 }
234
235 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
236 {
237     return 2;
238 }
239
240 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
241 {
242     return 1;
243 }
244
245 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
246 {
247     CHECK_EXPECT2(Switch);
248     ok(pProtocolData != NULL, "pProtocolData == NULL\n");
249     SendMessageW(protocol_hwnd, WM_USER, 0, (LPARAM)pProtocolData);
250     return S_OK;
251 }
252
253 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
254         LPCWSTR szStatusText)
255 {
256     static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
257         '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
258     static const WCHAR text_html[] = {'t','e','x','t','/','h','t','m','l',0};
259     static const WCHAR host[] =
260         {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
261     static const WCHAR wszWineHQIP[] =
262         {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
263     /* I'm not sure if it's a good idea to hardcode here the IP address... */
264
265     switch(ulStatusCode) {
266     case BINDSTATUS_MIMETYPEAVAILABLE:
267         CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
268         ok(szStatusText != NULL, "szStatusText == NULL\n");
269         if(szStatusText) {
270             if(tested_protocol == BIND_TEST)
271                 ok(szStatusText == expect_wsz, "unexpected szStatusText\n");
272             else
273                 ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
274         }
275         break;
276     case BINDSTATUS_DIRECTBIND:
277         CHECK_EXPECT2(ReportProgress_DIRECTBIND);
278         ok(szStatusText == NULL, "szStatusText != NULL\n");
279         break;
280     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
281         CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
282         ok(szStatusText != NULL, "szStatusText == NULL\n");
283         if(szStatusText) {
284             if(tested_protocol == BIND_TEST)
285                 ok(szStatusText == expect_wsz, "unexpected szStatusText\n");
286             else
287                 ok(!lstrcmpW(szStatusText, file_name), "szStatusText != file_name\n");
288         }
289         break;
290     case BINDSTATUS_FINDINGRESOURCE:
291         CHECK_EXPECT(ReportProgress_FINDINGRESOURCE);
292         ok(szStatusText != NULL, "szStatusText == NULL\n");
293         if(szStatusText)
294             ok(!lstrcmpW(szStatusText, host), "szStatustext != \"www.winehq.org\"\n");
295         break;
296     case BINDSTATUS_CONNECTING:
297         CHECK_EXPECT(ReportProgress_CONNECTING);
298         ok(szStatusText != NULL, "szStatusText == NULL\n");
299         if(szStatusText)
300             ok(!lstrcmpW(szStatusText, wszWineHQIP), "Unexpected szStatusText\n");
301         break;
302     case BINDSTATUS_SENDINGREQUEST:
303         CHECK_EXPECT(ReportProgress_SENDINGREQUEST);
304         if(tested_protocol == FILE_TEST) {
305             ok(szStatusText != NULL, "szStatusText == NULL\n");
306             if(szStatusText)
307                 ok(!*szStatusText, "wrong szStatusText\n");
308         }else {
309             ok(szStatusText == NULL, "szStatusText != NULL\n");
310         }
311         break;
312     case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
313         CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
314         ok(szStatusText != NULL, "szStatusText == NULL\n");
315         if(szStatusText)
316             ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
317         break;
318     case BINDSTATUS_PROTOCOLCLASSID:
319         CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
320         ok(szStatusText != NULL, "szStatusText == NULL\n");
321         ok(!lstrcmpW(szStatusText, null_guid), "unexpected szStatusText\n");
322         break;
323     default:
324         ok(0, "Unexpected call %d\n", ulStatusCode);
325     };
326
327     return S_OK;
328 }
329
330 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
331         ULONG ulProgress, ULONG ulProgressMax)
332 {
333     if(tested_protocol == FILE_TEST) {
334         CHECK_EXPECT2(ReportData);
335
336         ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
337            ulProgress, ulProgressMax);
338         ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
339         ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION),
340                 "grcfBSCF = %08x\n", grfBSCF);
341     }else if(tested_protocol == HTTP_TEST) {
342         if(!(grfBSCF & BSCF_LASTDATANOTIFICATION))
343             CHECK_EXPECT(ReportData);
344
345         ok(ulProgress, "ulProgress == 0\n");
346
347         if(first_data_notif) {
348             ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
349             first_data_notif = FALSE;
350         } else {
351             ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
352                || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION),
353                "grcfBSCF = %08x\n", grfBSCF);
354         }
355     }
356     return S_OK;
357 }
358
359 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
360         DWORD dwError, LPCWSTR szResult)
361 {
362     CHECK_EXPECT(ReportResult);
363
364     ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
365             hrResult, expect_hrResult);
366     if(SUCCEEDED(hrResult))
367         ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
368     else
369         ok(dwError != ERROR_SUCCESS, "dwError == ERROR_SUCCESS\n");
370     ok(!szResult, "szResult != NULL\n");
371
372     return S_OK;
373 }
374
375 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
376     ProtocolSink_QueryInterface,
377     ProtocolSink_AddRef,
378     ProtocolSink_Release,
379     ProtocolSink_Switch,
380     ProtocolSink_ReportProgress,
381     ProtocolSink_ReportData,
382     ProtocolSink_ReportResult
383 };
384
385 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
386
387 static HRESULT QueryInterface(REFIID riid, void **ppv)
388 {
389     *ppv = NULL;
390
391     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
392         *ppv = &protocol_sink;
393     if(IsEqualGUID(&IID_IServiceProvider, riid))
394         *ppv = &service_provider;
395
396     if(*ppv)
397         return S_OK;
398
399     return E_NOINTERFACE;
400 }
401
402 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
403 {
404     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
405         *ppv = iface;
406         return S_OK;
407     }
408     return E_NOINTERFACE;
409 }
410
411 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
412 {
413     return 2;
414 }
415
416 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
417 {
418     return 1;
419 }
420
421 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
422 {
423     DWORD cbSize;
424
425     CHECK_EXPECT(GetBindInfo);
426
427     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
428     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
429     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
430
431     *grfBINDF = bindf;
432     cbSize = pbindinfo->cbSize;
433     memset(pbindinfo, 0, cbSize);
434     pbindinfo->cbSize = cbSize;
435
436     return S_OK;
437 }
438
439 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
440         LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
441 {
442     static const WCHAR acc_mime[] = {'*','/','*',0};
443     static const WCHAR user_agent[] = {'W','i','n','e',0};
444
445     ok(ppwzStr != NULL, "ppwzStr == NULL\n");
446     ok(pcElFetched != NULL, "pcElFetched == NULL\n");
447
448     switch(ulStringType) {
449     case BINDSTRING_ACCEPT_MIMES:
450         CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
451         ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
452         if(pcElFetched) {
453             ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
454             *pcElFetched = 1;
455         }
456         if(ppwzStr) {
457             *ppwzStr = CoTaskMemAlloc(sizeof(acc_mime));
458             memcpy(*ppwzStr, acc_mime, sizeof(acc_mime));
459         }
460         return S_OK;
461     case BINDSTRING_USER_AGENT:
462         CHECK_EXPECT(GetBindString_USER_AGENT);
463         ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
464         if(pcElFetched) {
465             ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
466             *pcElFetched = 1;
467         }
468         if(ppwzStr) {
469             *ppwzStr = CoTaskMemAlloc(sizeof(user_agent));
470             memcpy(*ppwzStr, user_agent, sizeof(user_agent));
471         }
472         return S_OK;
473     default:
474         ok(0, "unexpected call\n");
475     }
476
477     return E_NOTIMPL;
478 }
479
480 static IInternetBindInfoVtbl bind_info_vtbl = {
481     BindInfo_QueryInterface,
482     BindInfo_AddRef,
483     BindInfo_Release,
484     BindInfo_GetBindInfo,
485     BindInfo_GetBindString
486 };
487
488 static IInternetBindInfo bind_info = { &bind_info_vtbl };
489
490 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
491                                                   REFIID riid, void **ppv)
492 {
493     ok(0, "unexpected call\n");
494     return E_NOINTERFACE;
495 }
496
497 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
498 {
499     return 2;
500 }
501
502 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
503 {
504     return 1;
505 }
506
507 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
508 {
509     CHECK_EXPECT(SetPriority);
510     ok(nPriority == 100, "nPriority=%d\n", nPriority);
511     return S_OK;
512 }
513
514 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
515 {
516     ok(0, "unexpected call\n");
517     return E_NOTIMPL;
518 }
519
520
521 static const IInternetPriorityVtbl InternetPriorityVtbl = {
522     InternetPriority_QueryInterface,
523     InternetPriority_AddRef,
524     InternetPriority_Release,
525     InternetPriority_SetPriority,
526     InternetPriority_GetPriority
527 };
528
529 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
530
531 static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
532 {
533     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
534         *ppv = iface;
535         return S_OK;
536     }
537
538     if(IsEqualGUID(&IID_IInternetPriority, riid)) {
539         *ppv = &InternetPriority;
540         return S_OK;
541     }
542
543     ok(0, "unexpected call\n");
544     *ppv = NULL;
545     return E_NOINTERFACE;
546 }
547
548 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
549 {
550     return 2;
551 }
552
553 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
554 {
555     return 1;
556 }
557
558 static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
559         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
560         DWORD grfPI, DWORD dwReserved)
561 {
562     BINDINFO bindinfo, exp_bindinfo;
563     DWORD cbindf = 0;
564     HRESULT hres;
565
566     static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
567     static const WCHAR empty_str[] = {0};
568
569     CHECK_EXPECT(Start);
570
571     ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
572     ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
573     ok(!grfPI, "grfPI = %x\n", grfPI);
574     ok(!dwReserved, "dwReserved = %d\n", dwReserved);
575
576     memset(&bindinfo, 0, sizeof(bindinfo));
577     bindinfo.cbSize = sizeof(bindinfo);
578     memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
579     SET_EXPECT(GetBindInfo);
580     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
581     ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
582     CHECK_CALLED(GetBindInfo);
583     ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
584        cbindf, (bindf|BINDF_FROMURLMON));
585     ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
586
587     SET_EXPECT(ReportProgress_SENDINGREQUEST);
588     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
589             BINDSTATUS_SENDINGREQUEST, empty_str);
590     ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
591     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
592
593     SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
594     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
595             BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = empty_str);
596     ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
597     CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
598
599     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
600     hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
601             BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, expect_wsz = wszTextHtml);
602     ok(hres == S_OK,
603        "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
604     CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
605
606     hres = IInternetProtocolSink_ReportData(pOIProtSink,
607             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, 13, 13);
608     ok(hres == S_OK, "ReportData failed: %08x\n", hres);
609
610     SET_EXPECT(ReportResult);
611     hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
612     ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
613     CHECK_CALLED(ReportResult);
614
615     return S_OK;
616 }
617
618 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
619         PROTOCOLDATA *pProtocolData)
620 {
621     ok(0, "unexpected call\n");
622     return E_NOTIMPL;
623 }
624
625 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
626         DWORD dwOptions)
627 {
628     ok(0, "unexpected call\n");
629     return E_NOTIMPL;
630 }
631
632 static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
633 {
634     CHECK_EXPECT(Terminate);
635     ok(!dwOptions, "dwOptions=%d\n", dwOptions);
636     return S_OK;
637 }
638
639 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
640 {
641     ok(0, "unexpected call\n");
642     return E_NOTIMPL;
643 }
644
645 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
646 {
647     ok(0, "unexpected call\n");
648     return E_NOTIMPL;
649 }
650
651 static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv,
652         ULONG cb, ULONG *pcbRead)
653 {
654     static DWORD read;
655
656     CHECK_EXPECT(Read);
657
658     ok(pv == expect_pv, "pv != expect_pv\n");
659     ok(cb == 1000, "cb=%d\n", cb);
660     ok(pcbRead != NULL, "pcbRead == NULL\n");
661     ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
662
663     if(read)
664         return S_FALSE;
665
666     memset(pv, 'x', 100);
667     *pcbRead = read = 100;
668     return S_OK;
669 }
670
671 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
672         LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
673 {
674     ok(0, "unexpected call\n");
675     return E_NOTIMPL;
676 }
677
678 static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
679 {
680     ok(0, "unexpected call\n");
681     return S_OK;
682 }
683
684 static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface)
685 {
686     ok(0, "unexpected call\n");
687     return S_OK;
688 }
689
690 static const IInternetProtocolVtbl ProtocolVtbl = {
691     Protocol_QueryInterface,
692     Protocol_AddRef,
693     Protocol_Release,
694     Protocol_Start,
695     Protocol_Continue,
696     Protocol_Abort,
697     Protocol_Terminate,
698     Protocol_Suspend,
699     Protocol_Resume,
700     Protocol_Read,
701     Protocol_Seek,
702     Protocol_LockRequest,
703     Protocol_UnlockRequest
704 };
705
706 static IInternetProtocol Protocol = { &ProtocolVtbl };
707
708 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
709 {
710     ok(0, "unexpected call\n");
711     return E_NOINTERFACE;
712 }
713
714 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
715 {
716     return 2;
717 }
718
719 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
720 {
721     return 1;
722 }
723
724 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
725                                         REFIID riid, void **ppv)
726 {
727     CHECK_EXPECT(CreateInstance);
728
729     ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
730     ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid\n");
731     ok(ppv != NULL, "ppv == NULL\n");
732
733     *ppv = &Protocol;
734     return S_OK;
735 }
736
737 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
738 {
739     ok(0, "unexpected call\n");
740     return S_OK;
741 }
742
743 static const IClassFactoryVtbl ClassFactoryVtbl = {
744     ClassFactory_QueryInterface,
745     ClassFactory_AddRef,
746     ClassFactory_Release,
747     ClassFactory_CreateInstance,
748     ClassFactory_LockServer
749 };
750
751 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
752
753 static void test_priority(IInternetProtocol *protocol)
754 {
755     IInternetPriority *priority;
756     LONG pr;
757     HRESULT hres;
758
759     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
760                                             (void**)&priority);
761     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
762     if(FAILED(hres))
763         return;
764
765     hres = IInternetPriority_GetPriority(priority, &pr);
766     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
767     ok(pr == 0, "pr=%d, expected 0\n", pr);
768
769     hres = IInternetPriority_SetPriority(priority, 1);
770     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
771
772     hres = IInternetPriority_GetPriority(priority, &pr);
773     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
774     ok(pr == 1, "pr=%d, expected 1\n", pr);
775
776     IInternetPriority_Release(priority);
777 }
778
779 static void file_protocol_start(IInternetProtocol *protocol, LPCWSTR url, BOOL is_first)
780 {
781     HRESULT hres;
782
783     SET_EXPECT(GetBindInfo);
784     if(!(bindf & BINDF_FROMURLMON))
785        SET_EXPECT(ReportProgress_DIRECTBIND);
786     if(is_first) {
787         SET_EXPECT(ReportProgress_SENDINGREQUEST);
788         SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
789         if(bindf & BINDF_FROMURLMON)
790             SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
791         else
792             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
793     }
794     SET_EXPECT(ReportData);
795     if(is_first)
796         SET_EXPECT(ReportResult);
797
798     expect_hrResult = S_OK;
799
800     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
801     ok(hres == S_OK, "Start failed: %08x\n", hres);
802
803     CHECK_CALLED(GetBindInfo);
804     if(!(bindf & BINDF_FROMURLMON))
805        CHECK_CALLED(ReportProgress_DIRECTBIND);
806     if(is_first) {
807         CHECK_CALLED(ReportProgress_SENDINGREQUEST);
808         CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
809         if(bindf & BINDF_FROMURLMON)
810             CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
811         else
812             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
813     }
814     CHECK_CALLED(ReportData);
815     if(is_first)
816         CHECK_CALLED(ReportResult);
817 }
818
819 static void test_file_protocol_url(LPCWSTR url)
820 {
821     IInternetProtocolInfo *protocol_info;
822     IUnknown *unk;
823     IClassFactory *factory;
824     HRESULT hres;
825
826     hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
827             &IID_IUnknown, (void**)&unk);
828     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
829     if(!SUCCEEDED(hres))
830         return;
831
832     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
833     ok(hres == E_NOINTERFACE,
834             "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
835
836     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
837     ok(hres == S_OK, "Could not get IClassFactory interface\n");
838     if(SUCCEEDED(hres)) {
839         IInternetProtocol *protocol;
840         BYTE buf[512];
841         ULONG cb;
842         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
843         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
844
845         if(SUCCEEDED(hres)) {
846             file_protocol_start(protocol, url, TRUE);
847             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
848             ok(hres == S_OK, "Read failed: %08x\n", hres);
849             ok(cb == 2, "cb=%u expected 2\n", cb);
850             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
851             ok(hres == S_FALSE, "Read failed: %08x\n", hres);
852             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
853             ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
854             ok(cb == 0, "cb=%u expected 0\n", cb);
855             hres = IInternetProtocol_UnlockRequest(protocol);
856             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
857
858             file_protocol_start(protocol, url, FALSE);
859             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
860             ok(hres == S_FALSE, "Read failed: %08x\n", hres);
861             hres = IInternetProtocol_LockRequest(protocol, 0);
862             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
863             hres = IInternetProtocol_UnlockRequest(protocol);
864             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
865
866             IInternetProtocol_Release(protocol);
867         }
868
869         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
870         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
871
872         if(SUCCEEDED(hres)) {
873             file_protocol_start(protocol, url, TRUE);
874             hres = IInternetProtocol_LockRequest(protocol, 0);
875             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
876             hres = IInternetProtocol_Terminate(protocol, 0);
877             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
878             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
879             ok(hres == S_OK, "Read failed: %08x\n\n", hres);
880             hres = IInternetProtocol_UnlockRequest(protocol);
881             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
882             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
883             ok(hres == S_OK, "Read failed: %08x\n", hres);
884             hres = IInternetProtocol_Terminate(protocol, 0);
885             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
886
887             IInternetProtocol_Release(protocol);
888         }
889
890         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
891         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
892
893         if(SUCCEEDED(hres)) {
894             file_protocol_start(protocol, url, TRUE);
895             hres = IInternetProtocol_Terminate(protocol, 0);
896             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
897             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
898             ok(hres == S_OK, "Read failed: %08x\n", hres);
899             ok(cb == 2, "cb=%u expected 2\n", cb);
900
901             IInternetProtocol_Release(protocol);
902         }
903
904         IClassFactory_Release(factory);
905     }
906
907     IUnknown_Release(unk);
908 }
909
910 static void test_file_protocol_fail(void)
911 {
912     IInternetProtocol *protocol;
913     HRESULT hres;
914
915     static const WCHAR index_url2[] =
916         {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
917
918     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
919             &IID_IInternetProtocol, (void**)&protocol);
920     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
921     if(FAILED(hres))
922         return;
923
924     SET_EXPECT(GetBindInfo);
925     expect_hrResult = MK_E_SYNTAX;
926     hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
927     ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
928     CHECK_CALLED(GetBindInfo);
929
930     SET_EXPECT(GetBindInfo);
931     if(!(bindf & BINDF_FROMURLMON))
932         SET_EXPECT(ReportProgress_DIRECTBIND);
933     SET_EXPECT(ReportProgress_SENDINGREQUEST);
934     SET_EXPECT(ReportResult);
935     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
936     hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
937     ok(hres == INET_E_RESOURCE_NOT_FOUND,
938             "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
939     CHECK_CALLED(GetBindInfo);
940     if(!(bindf & BINDF_FROMURLMON))
941         CHECK_CALLED(ReportProgress_DIRECTBIND);
942     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
943     CHECK_CALLED(ReportResult);
944
945     IInternetProtocol_Release(protocol);
946
947     hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
948             &IID_IInternetProtocol, (void**)&protocol);
949     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
950     if(FAILED(hres))
951         return;
952
953     SET_EXPECT(GetBindInfo);
954     if(!(bindf & BINDF_FROMURLMON))
955         SET_EXPECT(ReportProgress_DIRECTBIND);
956     SET_EXPECT(ReportProgress_SENDINGREQUEST);
957     SET_EXPECT(ReportResult);
958     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
959
960     hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
961     ok(hres == INET_E_RESOURCE_NOT_FOUND,
962             "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
963     CHECK_CALLED(GetBindInfo);
964     if(!(bindf & BINDF_FROMURLMON))
965         CHECK_CALLED(ReportProgress_DIRECTBIND);
966     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
967     CHECK_CALLED(ReportResult);
968
969     IInternetProtocol_Release(protocol);
970 }
971
972 static void test_file_protocol(void) {
973     WCHAR buf[MAX_PATH];
974     DWORD size;
975     ULONG len;
976     HANDLE file;
977
978     static const WCHAR wszFile[] = {'f','i','l','e',':',0};
979     static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
980     static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
981     static const char html_doc[] = "<HTML></HTML>";
982
983     trace("Testing file protocol...\n");
984     tested_protocol = FILE_TEST;
985
986     file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
987             FILE_ATTRIBUTE_NORMAL, NULL);
988     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
989     if(file == INVALID_HANDLE_VALUE)
990         return;
991     WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
992     CloseHandle(file);
993
994     file_name = wszIndexHtml;
995     bindf = 0;
996     test_file_protocol_url(index_url);
997     bindf = BINDF_FROMURLMON;
998     test_file_protocol_url(index_url);
999
1000     memcpy(buf, wszFile, sizeof(wszFile));
1001     len = sizeof(wszFile)/sizeof(WCHAR)-1;
1002     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1003     buf[len++] = '\\';
1004     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1005
1006     file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
1007     bindf = 0;
1008     test_file_protocol_url(buf);
1009     bindf = BINDF_FROMURLMON;
1010     test_file_protocol_url(buf);
1011
1012     memcpy(buf, wszFile2, sizeof(wszFile2));
1013     len = sizeof(wszFile2)/sizeof(WCHAR)-1;
1014     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1015     buf[len++] = '\\';
1016     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1017
1018     file_name = buf + sizeof(wszFile2)/sizeof(WCHAR)-1;
1019     bindf = 0;
1020     test_file_protocol_url(buf);
1021     bindf = BINDF_FROMURLMON;
1022     test_file_protocol_url(buf);
1023
1024     memcpy(buf, wszFile3, sizeof(wszFile3));
1025     len = sizeof(wszFile3)/sizeof(WCHAR)-1;
1026     len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1027     buf[len++] = '\\';
1028     memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1029
1030     file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
1031     bindf = 0;
1032     test_file_protocol_url(buf);
1033     bindf = BINDF_FROMURLMON;
1034     test_file_protocol_url(buf);
1035
1036     DeleteFileW(wszIndexHtml);
1037
1038     bindf = 0;
1039     test_file_protocol_fail();
1040     bindf = BINDF_FROMURLMON;
1041     test_file_protocol_fail();
1042 }
1043
1044 static BOOL http_protocol_start(LPCWSTR url, BOOL is_first)
1045 {
1046     HRESULT hres;
1047
1048     first_data_notif = TRUE;
1049
1050     SET_EXPECT(GetBindInfo);
1051     SET_EXPECT(GetBindString_USER_AGENT);
1052     SET_EXPECT(GetBindString_ACCEPT_MIMES);
1053     SET_EXPECT(QueryService_HttpNegotiate);
1054     SET_EXPECT(BeginningTransaction);
1055     SET_EXPECT(GetRootSecurityId);
1056
1057     hres = IInternetProtocol_Start(http_protocol, url, &protocol_sink, &bind_info, 0, 0);
1058     todo_wine {
1059         ok(hres == S_OK, "Start failed: %08x\n", hres);
1060     }
1061     if(FAILED(hres))
1062         return FALSE;
1063
1064     CHECK_CALLED(GetBindInfo);
1065     CHECK_CALLED(GetBindString_USER_AGENT);
1066     CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1067     CHECK_CALLED(QueryService_HttpNegotiate);
1068     CHECK_CALLED(BeginningTransaction);
1069     CHECK_CALLED(GetRootSecurityId);
1070
1071     return TRUE;
1072 }
1073
1074 static void test_http_protocol_url(LPCWSTR url)
1075 {
1076     IInternetProtocolInfo *protocol_info;
1077     IClassFactory *factory;
1078     IUnknown *unk;
1079     HRESULT hres;
1080
1081     trace("Testing http protocol...\n");
1082     http_url = url;
1083
1084     hres = CoGetClassObject(&CLSID_HttpProtocol, CLSCTX_INPROC_SERVER, NULL,
1085             &IID_IUnknown, (void**)&unk);
1086     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1087     if(!SUCCEEDED(hres))
1088         return;
1089
1090     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1091     ok(hres == E_NOINTERFACE,
1092         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1093         hres);
1094
1095     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1096     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1097     IUnknown_Release(unk);
1098     if(FAILED(hres))
1099         return;
1100
1101     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1102                                         (void**)&http_protocol);
1103     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1104     if(SUCCEEDED(hres)) {
1105         BYTE buf[512];
1106         DWORD cb;
1107         MSG msg;
1108
1109         bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
1110
1111         test_priority(http_protocol);
1112
1113         SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1114         SET_EXPECT(ReportProgress_CONNECTING);
1115         SET_EXPECT(ReportProgress_SENDINGREQUEST);
1116
1117         if(!http_protocol_start(url, TRUE))
1118             return;
1119
1120         hres = IInternetProtocol_Read(http_protocol, buf, 2, &cb);
1121         ok(hres == E_PENDING, "Read failed: %08x, expected E_PENDING\n", hres);
1122         ok(!cb, "cb=%d, expected 0\n", cb);
1123
1124         SET_EXPECT(Switch);
1125         SET_EXPECT(ReportResult);
1126         expect_hrResult = S_OK;
1127
1128         GetMessageW(&msg, NULL, 0, 0);
1129
1130         CHECK_CALLED(Switch);
1131         CHECK_CALLED(ReportResult);
1132
1133         IInternetProtocol_Release(http_protocol);
1134     }
1135
1136     IClassFactory_Release(factory);
1137 }
1138
1139 static void test_http_protocol(void)
1140 {
1141     static const WCHAR winehq_url[] =
1142         {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
1143             'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
1144
1145     tested_protocol = HTTP_TEST;
1146     test_http_protocol_url(winehq_url);
1147
1148 }
1149
1150 static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1151 {
1152     if(msg == WM_USER) {
1153         HRESULT hres;
1154         DWORD cb;
1155         BYTE buf[3600];
1156
1157         SET_EXPECT(ReportData);
1158         if(!state) {
1159             CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1160             CHECK_CALLED(ReportProgress_CONNECTING);
1161             CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1162
1163             SET_EXPECT(OnResponse);
1164             SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1165         }
1166
1167         hres = IInternetProtocol_Continue(http_protocol, (PROTOCOLDATA*)lParam);
1168         ok(hres == S_OK, "Continue failed: %08x\n", hres);
1169
1170         CHECK_CALLED(ReportData);
1171         if(!state) {
1172             CHECK_CALLED(OnResponse);
1173             CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1174         }
1175
1176         do hres = IInternetProtocol_Read(http_protocol, buf, sizeof(buf), &cb);
1177         while(cb);
1178
1179         ok(hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
1180
1181         if(hres == S_FALSE)
1182             PostMessageW(protocol_hwnd, WM_USER+1, 0, 0);
1183
1184         if(!state) {
1185             state = 1;
1186
1187             hres = IInternetProtocol_LockRequest(http_protocol, 0);
1188             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1189
1190             do hres = IInternetProtocol_Read(http_protocol, buf, sizeof(buf), &cb);
1191             while(cb);
1192             ok(hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
1193         }
1194     }
1195
1196     return DefWindowProc(hwnd, msg, wParam, lParam);
1197 }
1198
1199 static HWND create_protocol_window(void)
1200 {
1201     static const WCHAR wszProtocolWindow[] =
1202         {'P','r','o','t','o','c','o','l','W','i','n','d','o','w',0};
1203     static WNDCLASSEXW wndclass = {
1204         sizeof(WNDCLASSEXW),
1205         0,
1206         wnd_proc,
1207         0, 0, NULL, NULL, NULL, NULL, NULL,
1208         wszProtocolWindow,
1209         NULL
1210     };
1211
1212     RegisterClassExW(&wndclass);
1213     return CreateWindowW(wszProtocolWindow, wszProtocolWindow,
1214                          WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
1215                          CW_USEDEFAULT, NULL, NULL, NULL, NULL);
1216 }
1217
1218 static void test_mk_protocol(void)
1219 {
1220     IInternetProtocolInfo *protocol_info;
1221     IInternetProtocol *protocol;
1222     IClassFactory *factory;
1223     IUnknown *unk;
1224     HRESULT hres;
1225
1226     static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
1227                                        ':',':','/','t','e','s','t','.','h','t','m','l',0};
1228     static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
1229
1230     trace("Testing mk protocol...\n");
1231     tested_protocol = MK_TEST;
1232
1233     hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
1234             &IID_IUnknown, (void**)&unk);
1235     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1236
1237     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1238     ok(hres == E_NOINTERFACE,
1239         "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1240         hres);
1241
1242     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1243     ok(hres == S_OK, "Could not get IClassFactory interface\n");
1244     IUnknown_Release(unk);
1245     if(FAILED(hres))
1246         return;
1247
1248     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1249                                         (void**)&protocol);
1250     IClassFactory_Release(factory);
1251     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1252
1253     SET_EXPECT(GetBindInfo);
1254     hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
1255     ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
1256     CHECK_CALLED(GetBindInfo);
1257
1258     SET_EXPECT(GetBindInfo);
1259     SET_EXPECT(ReportProgress_DIRECTBIND);
1260     SET_EXPECT(ReportProgress_SENDINGREQUEST);
1261     SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1262     SET_EXPECT(ReportResult);
1263     expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1264
1265     hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
1266     ok(hres == INET_E_RESOURCE_NOT_FOUND, "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1267
1268     CHECK_CALLED(GetBindInfo);
1269     CHECK_CALLED(ReportProgress_DIRECTBIND);
1270     CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1271     CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1272     CHECK_CALLED(ReportResult);
1273
1274     IInternetProtocol_Release(protocol);
1275 }
1276
1277 static void test_CreateBinding(void)
1278 {
1279     IInternetProtocol *protocol;
1280     IInternetPriority *priority;
1281     IInternetSession *session;
1282     LONG p;
1283     BYTE buf[1000];
1284     DWORD read;
1285     HRESULT hres;
1286
1287     static const WCHAR test_url[] =
1288         {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
1289     static const WCHAR wsz_test[] = {'t','e','s','t',0};
1290
1291     trace("Testing CreateBinding...\n");
1292     tested_protocol = BIND_TEST;
1293
1294     hres = CoInternetGetSession(0, &session, 0);
1295     ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
1296
1297     hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
1298     ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
1299
1300     hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
1301     ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
1302     ok(protocol != NULL, "protocol == NULL\n");
1303
1304     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
1305     ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
1306
1307     hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
1308     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1309     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
1310     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1311     hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
1312     ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1313
1314     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
1315     ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
1316
1317     p = 0xdeadbeef;
1318     hres = IInternetPriority_GetPriority(priority, &p);
1319     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1320     ok(!p, "p=%d\n", p);
1321
1322     hres = IInternetPriority_SetPriority(priority, 100);
1323     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1324
1325     p = 0xdeadbeef;
1326     hres = IInternetPriority_GetPriority(priority, &p);
1327     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1328     ok(p == 100, "p=%d\n", p);
1329
1330     SET_EXPECT(QueryService_InternetProtocol);
1331     SET_EXPECT(CreateInstance);
1332     SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
1333     SET_EXPECT(SetPriority);
1334     SET_EXPECT(Start);
1335
1336     expect_hrResult = S_OK;
1337     hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
1338     ok(hres == S_OK, "Start failed: %08x\n", hres);
1339
1340     CHECK_CALLED(QueryService_InternetProtocol);
1341     CHECK_CALLED(CreateInstance);
1342     CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
1343     CHECK_CALLED(SetPriority);
1344     CHECK_CALLED(Start);
1345
1346     SET_EXPECT(Read);
1347     read = 0xdeadbeef;
1348     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
1349     ok(hres == S_OK, "Read failed: %08x\n", hres);
1350     ok(read == 100, "read = %d\n", read);
1351     CHECK_CALLED(Read);
1352
1353     SET_EXPECT(Read);
1354     read = 0xdeadbeef;
1355     hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
1356     ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1357     ok(!read, "read = %d\n", read);
1358     CHECK_CALLED(Read);
1359
1360     p = 0xdeadbeef;
1361     hres = IInternetPriority_GetPriority(priority, &p);
1362     ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1363     ok(p == 100, "p=%d\n", p);
1364
1365     hres = IInternetPriority_SetPriority(priority, 101);
1366     ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1367
1368     SET_EXPECT(Terminate);
1369     hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
1370     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1371     CHECK_CALLED(Terminate);
1372
1373     IInternetPriority_Release(priority);
1374     IInternetBindInfo_Release(prot_bind_info);
1375     IInternetProtocol_Release(protocol);
1376     IInternetSession_Release(session);
1377 }
1378
1379 START_TEST(protocol)
1380 {
1381     OleInitialize(NULL);
1382
1383     protocol_hwnd = create_protocol_window();
1384
1385     test_file_protocol();
1386     test_http_protocol();
1387     test_mk_protocol();
1388     test_CreateBinding();
1389
1390     DestroyWindow(protocol_hwnd);
1391
1392     OleUninitialize();
1393 }