push 739d3025d82fc820f7a9c38697877dd3d18e8c13
[wine/hacks.git] / dlls / urlmon / tests / protocol.c
blob72cb2fceb1930698c4955a1f39242391e244d39f
1 /*
2 * Copyright 2005-2007 Jacek Caban for CodeWeavers
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.
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.
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
19 #define COBJMACROS
20 #define CONST_VTABLE
22 #include <wine/test.h>
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "ole2.h"
28 #include "urlmon.h"
30 #include "initguid.h"
32 #define DEFINE_EXPECT(func) \
33 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
35 #define SET_EXPECT(func) \
36 expect_ ## func = TRUE
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)
45 #define CHECK_EXPECT2(func) \
46 do { \
47 ok(expect_ ##func, "unexpected call " #func "\n"); \
48 called_ ## func = TRUE; \
49 }while(0)
51 #define CHECK_CALLED(func) \
52 do { \
53 ok(called_ ## func, "expected " #func "\n"); \
54 expect_ ## func = called_ ## func = FALSE; \
55 }while(0)
57 #define CHECK_NOT_CALLED(func) \
58 do { \
59 ok(!called_ ## func, "unexpected " #func "\n"); \
60 expect_ ## func = called_ ## func = FALSE; \
61 }while(0)
63 #define CLEAR_CALLED(func) \
64 expect_ ## func = called_ ## func = FALSE
66 DEFINE_EXPECT(GetBindInfo);
67 DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
68 DEFINE_EXPECT(ReportProgress_DIRECTBIND);
69 DEFINE_EXPECT(ReportProgress_RAWMIMETYPE);
70 DEFINE_EXPECT(ReportProgress_FINDINGRESOURCE);
71 DEFINE_EXPECT(ReportProgress_CONNECTING);
72 DEFINE_EXPECT(ReportProgress_SENDINGREQUEST);
73 DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
74 DEFINE_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
75 DEFINE_EXPECT(ReportProgress_PROTOCOLCLASSID);
76 DEFINE_EXPECT(ReportData);
77 DEFINE_EXPECT(ReportResult);
78 DEFINE_EXPECT(GetBindString_ACCEPT_MIMES);
79 DEFINE_EXPECT(GetBindString_USER_AGENT);
80 DEFINE_EXPECT(GetBindString_POST_COOKIE);
81 DEFINE_EXPECT(QueryService_HttpNegotiate);
82 DEFINE_EXPECT(QueryService_InternetProtocol);
83 DEFINE_EXPECT(BeginningTransaction);
84 DEFINE_EXPECT(GetRootSecurityId);
85 DEFINE_EXPECT(OnResponse);
86 DEFINE_EXPECT(Switch);
87 DEFINE_EXPECT(CreateInstance);
88 DEFINE_EXPECT(Start);
89 DEFINE_EXPECT(Terminate);
90 DEFINE_EXPECT(Read);
91 DEFINE_EXPECT(SetPriority);
93 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
94 static const WCHAR index_url[] =
95 {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
97 static HRESULT expect_hrResult;
98 static LPCWSTR file_name, http_url, expect_wsz;
99 static IInternetProtocol *http_protocol = NULL;
100 static BOOL first_data_notif = FALSE, http_is_first = FALSE,
101 http_post_test = FALSE;
102 static int state = 0;
103 static DWORD bindf = 0;
104 static IInternetBindInfo *prot_bind_info;
105 static void *expect_pv;
106 static HANDLE event_complete;
108 static enum {
109 FILE_TEST,
110 HTTP_TEST,
111 MK_TEST,
112 BIND_TEST
113 } tested_protocol;
115 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
117 if(IsEqualGUID(&IID_IUnknown, riid)
118 || IsEqualGUID(&IID_IHttpNegotiate, riid)
119 || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
120 *ppv = iface;
121 return S_OK;
124 ok(0, "unexpected call\n");
125 return E_NOINTERFACE;
128 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
130 return 2;
133 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
135 return 1;
138 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
139 LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
141 LPWSTR addl_headers;
143 static const WCHAR wszHeaders[] =
144 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
145 'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
146 'd','e','d','\r','\n',0};
148 CHECK_EXPECT(BeginningTransaction);
150 ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
151 ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
152 ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
153 if(pszAdditionalHeaders)
155 ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
156 if (http_post_test)
158 addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
159 if (!addl_headers)
161 http_post_test = FALSE;
162 skip("Out of memory\n");
163 return E_OUTOFMEMORY;
165 lstrcpyW(addl_headers, wszHeaders);
166 *pszAdditionalHeaders = addl_headers;
170 return S_OK;
173 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
174 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
176 CHECK_EXPECT(OnResponse);
178 ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
179 ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
180 ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
181 ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
183 return S_OK;
186 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
187 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
189 static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
191 CHECK_EXPECT(GetRootSecurityId);
193 ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
194 ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
195 ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
197 if(pcbSecurityId) {
198 ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
199 *pcbSecurityId = sizeof(sec_id);
202 if(pbSecurityId)
203 memcpy(pbSecurityId, sec_id, sizeof(sec_id));
205 return E_FAIL;
208 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
209 HttpNegotiate_QueryInterface,
210 HttpNegotiate_AddRef,
211 HttpNegotiate_Release,
212 HttpNegotiate_BeginningTransaction,
213 HttpNegotiate_OnResponse,
214 HttpNegotiate_GetRootSecurityId
217 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
219 static HRESULT QueryInterface(REFIID,void**);
221 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
223 return QueryInterface(riid, ppv);
226 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
228 return 2;
231 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
233 return 1;
236 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
237 REFIID riid, void **ppv)
239 if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
240 CHECK_EXPECT2(QueryService_HttpNegotiate);
241 return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
244 if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
245 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
246 CHECK_EXPECT(QueryService_InternetProtocol);
247 return E_NOINTERFACE;
250 ok(0, "unexpected call\n");
251 return E_FAIL;
254 static const IServiceProviderVtbl ServiceProviderVtbl = {
255 ServiceProvider_QueryInterface,
256 ServiceProvider_AddRef,
257 ServiceProvider_Release,
258 ServiceProvider_QueryService
261 static IServiceProvider service_provider = { &ServiceProviderVtbl };
263 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
265 return QueryInterface(riid, ppv);
268 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
270 return 2;
273 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
275 return 1;
278 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
280 HRESULT hres;
282 CHECK_EXPECT(Switch);
283 ok(pProtocolData != NULL, "pProtocolData == NULL\n");
284 if (!state) {
285 if (http_is_first) {
286 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
287 CHECK_CALLED(ReportProgress_CONNECTING);
288 } else todo_wine {
289 CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
290 CHECK_NOT_CALLED(ReportProgress_CONNECTING);
292 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
293 SET_EXPECT(OnResponse);
294 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
297 SET_EXPECT(ReportData);
298 hres = IInternetProtocol_Continue(http_protocol, pProtocolData);
299 ok(hres == S_OK, "Continue failed: %08x\n", hres);
300 CHECK_CALLED(ReportData);
302 if (!state) {
303 state = 1;
304 CHECK_CALLED(OnResponse);
305 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
308 SetEvent(event_complete);
309 return S_OK;
312 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
313 LPCWSTR szStatusText)
315 static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
316 '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
317 static const WCHAR text_html[] = {'t','e','x','t','/','h','t','m','l',0};
318 static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
319 static const WCHAR host[] =
320 {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
321 static const WCHAR post_host[] =
322 {'c','r','o','s','s','o','v','e','r','.','c','o','d','e',
323 'w','e','a','v','e','r','s','.','c','o','m',0};
324 static const WCHAR wszWineHQIP[] =
325 {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
326 static const WCHAR wszCrossoverIP[] =
327 {'2','0','9','.','4','6','.','2','5','.','1','3','2',0};
328 /* I'm not sure if it's a good idea to hardcode here the IP address... */
330 switch(ulStatusCode) {
331 case BINDSTATUS_MIMETYPEAVAILABLE:
332 CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
333 ok(szStatusText != NULL, "szStatusText == NULL\n");
334 if(szStatusText) {
335 if(tested_protocol == BIND_TEST)
336 ok(szStatusText == expect_wsz, "unexpected szStatusText\n");
337 else if (http_post_test)
338 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
339 !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
340 "szStatusText != text/plain\n");
341 else
342 ok(lstrlenW(text_html) <= lstrlenW(szStatusText) &&
343 !memcmp(szStatusText, text_html, lstrlenW(text_html)*sizeof(WCHAR)),
344 "szStatusText != text/html\n");
346 break;
347 case BINDSTATUS_DIRECTBIND:
348 CHECK_EXPECT2(ReportProgress_DIRECTBIND);
349 ok(szStatusText == NULL, "szStatusText != NULL\n");
350 break;
351 case BINDSTATUS_RAWMIMETYPE:
352 CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
353 ok(szStatusText != NULL, "szStatusText == NULL\n");
354 if(szStatusText)
355 ok(lstrlenW(szStatusText) < lstrlenW(text_html) ||
356 !memcmp(szStatusText, text_html, lstrlenW(text_html)*sizeof(WCHAR)),
357 "szStatusText != text/html\n");
358 break;
359 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
360 CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
361 ok(szStatusText != NULL, "szStatusText == NULL\n");
362 if(szStatusText) {
363 if(tested_protocol == BIND_TEST)
364 ok(szStatusText == expect_wsz, "unexpected szStatusText\n");
365 else
366 ok(!lstrcmpW(szStatusText, file_name), "szStatusText != file_name\n");
368 break;
369 case BINDSTATUS_FINDINGRESOURCE:
370 CHECK_EXPECT(ReportProgress_FINDINGRESOURCE);
371 ok(szStatusText != NULL, "szStatusText == NULL\n");
372 if(szStatusText)
374 if (!http_post_test)
375 ok(!lstrcmpW(szStatusText, host),
376 "szStatustext != \"www.winehq.org\"\n");
377 else
378 ok(!lstrcmpW(szStatusText, post_host),
379 "szStatustext != \"crossover.codeweavers.com\"\n");
381 break;
382 case BINDSTATUS_CONNECTING:
383 CHECK_EXPECT(ReportProgress_CONNECTING);
384 ok(szStatusText != NULL, "szStatusText == NULL\n");
385 if(szStatusText)
386 ok(!lstrcmpW(szStatusText, http_post_test ?
387 wszCrossoverIP : wszWineHQIP),
388 "Unexpected szStatusText\n");
389 break;
390 case BINDSTATUS_SENDINGREQUEST:
391 CHECK_EXPECT(ReportProgress_SENDINGREQUEST);
392 if(tested_protocol == FILE_TEST) {
393 ok(szStatusText != NULL, "szStatusText == NULL\n");
394 if(szStatusText)
395 ok(!*szStatusText, "wrong szStatusText\n");
396 }else {
397 ok(szStatusText == NULL, "szStatusText != NULL\n");
399 break;
400 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
401 CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
402 ok(szStatusText != NULL, "szStatusText == NULL\n");
403 if(szStatusText)
404 ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
405 break;
406 case BINDSTATUS_PROTOCOLCLASSID:
407 CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
408 ok(szStatusText != NULL, "szStatusText == NULL\n");
409 ok(!lstrcmpW(szStatusText, null_guid), "unexpected szStatusText\n");
410 break;
411 default:
412 ok(0, "Unexpected call %d\n", ulStatusCode);
415 return S_OK;
418 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
419 ULONG ulProgress, ULONG ulProgressMax)
421 if(tested_protocol == FILE_TEST) {
422 CHECK_EXPECT2(ReportData);
424 ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
425 ulProgress, ulProgressMax);
426 ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
427 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION),
428 "grcfBSCF = %08x\n", grfBSCF);
429 }else if(tested_protocol == HTTP_TEST) {
430 if(!(grfBSCF & BSCF_LASTDATANOTIFICATION))
431 CHECK_EXPECT(ReportData);
432 else if (http_post_test)
433 ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
435 ok(ulProgress, "ulProgress == 0\n");
437 if(first_data_notif) {
438 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
439 first_data_notif = FALSE;
440 } else {
441 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
442 || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION),
443 "grcfBSCF = %08x\n", grfBSCF);
446 if(!(bindf & BINDF_FROMURLMON) &&
447 !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
448 if(!state) {
449 state = 1;
450 if(http_is_first) {
451 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
452 CHECK_CALLED(ReportProgress_CONNECTING);
453 } else todo_wine {
454 CHECK_NOT_CALLED(ReportProgress_FINDINGRESOURCE);
455 CHECK_NOT_CALLED(ReportProgress_CONNECTING);
457 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
458 CHECK_CALLED(OnResponse);
459 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
461 SetEvent(event_complete);
464 return S_OK;
467 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
468 DWORD dwError, LPCWSTR szResult)
470 CHECK_EXPECT(ReportResult);
472 ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
473 hrResult, expect_hrResult);
474 if(SUCCEEDED(hrResult))
475 ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
476 else
477 ok(dwError != ERROR_SUCCESS, "dwError == ERROR_SUCCESS\n");
478 ok(!szResult, "szResult != NULL\n");
480 return S_OK;
483 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
484 ProtocolSink_QueryInterface,
485 ProtocolSink_AddRef,
486 ProtocolSink_Release,
487 ProtocolSink_Switch,
488 ProtocolSink_ReportProgress,
489 ProtocolSink_ReportData,
490 ProtocolSink_ReportResult
493 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
495 static HRESULT QueryInterface(REFIID riid, void **ppv)
497 *ppv = NULL;
499 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
500 *ppv = &protocol_sink;
501 if(IsEqualGUID(&IID_IServiceProvider, riid))
502 *ppv = &service_provider;
504 if(*ppv)
505 return S_OK;
507 return E_NOINTERFACE;
510 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
512 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
513 *ppv = iface;
514 return S_OK;
516 return E_NOINTERFACE;
519 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
521 return 2;
524 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
526 return 1;
529 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
531 DWORD cbSize;
533 static const CHAR szPostData[] = "mode=Test";
535 CHECK_EXPECT(GetBindInfo);
537 ok(grfBINDF != NULL, "grfBINDF == NULL\n");
538 ok(pbindinfo != NULL, "pbindinfo == NULL\n");
539 ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
541 *grfBINDF = bindf;
542 cbSize = pbindinfo->cbSize;
543 memset(pbindinfo, 0, cbSize);
544 pbindinfo->cbSize = cbSize;
546 if (http_post_test)
548 /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly
549 * with urlmon on native (Win98 and WinXP) */
550 pbindinfo->stgmedData.hGlobal = GlobalAlloc(GPTR, sizeof(szPostData));
551 if (!pbindinfo->stgmedData.hGlobal)
553 http_post_test = FALSE;
554 skip("Out of memory\n");
555 return E_OUTOFMEMORY;
557 lstrcpy((LPSTR)pbindinfo->stgmedData.hGlobal, szPostData);
558 pbindinfo->cbstgmedData = sizeof(szPostData)-1;
559 pbindinfo->dwBindVerb = BINDVERB_POST;
560 pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
563 return S_OK;
566 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
567 LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
569 static const WCHAR acc_mime[] = {'*','/','*',0};
570 static const WCHAR user_agent[] = {'W','i','n','e',0};
572 ok(ppwzStr != NULL, "ppwzStr == NULL\n");
573 ok(pcElFetched != NULL, "pcElFetched == NULL\n");
575 switch(ulStringType) {
576 case BINDSTRING_ACCEPT_MIMES:
577 CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
578 ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
579 if(pcElFetched) {
580 ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
581 *pcElFetched = 1;
583 if(ppwzStr) {
584 *ppwzStr = CoTaskMemAlloc(sizeof(acc_mime));
585 memcpy(*ppwzStr, acc_mime, sizeof(acc_mime));
587 return S_OK;
588 case BINDSTRING_USER_AGENT:
589 CHECK_EXPECT(GetBindString_USER_AGENT);
590 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
591 if(pcElFetched) {
592 ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
593 *pcElFetched = 1;
595 if(ppwzStr) {
596 *ppwzStr = CoTaskMemAlloc(sizeof(user_agent));
597 memcpy(*ppwzStr, user_agent, sizeof(user_agent));
599 return S_OK;
600 case BINDSTRING_POST_COOKIE:
601 CHECK_EXPECT(GetBindString_POST_COOKIE);
602 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
603 if(pcElFetched)
604 ok(*pcElFetched == 0, "*pcElFetch=%d, expectd 0\n", *pcElFetched);
605 return S_OK;
606 default:
607 ok(0, "unexpected call\n");
610 return E_NOTIMPL;
613 static IInternetBindInfoVtbl bind_info_vtbl = {
614 BindInfo_QueryInterface,
615 BindInfo_AddRef,
616 BindInfo_Release,
617 BindInfo_GetBindInfo,
618 BindInfo_GetBindString
621 static IInternetBindInfo bind_info = { &bind_info_vtbl };
623 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
624 REFIID riid, void **ppv)
626 ok(0, "unexpected call\n");
627 return E_NOINTERFACE;
630 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
632 return 2;
635 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
637 return 1;
640 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
642 CHECK_EXPECT(SetPriority);
643 ok(nPriority == 100, "nPriority=%d\n", nPriority);
644 return S_OK;
647 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
649 ok(0, "unexpected call\n");
650 return E_NOTIMPL;
654 static const IInternetPriorityVtbl InternetPriorityVtbl = {
655 InternetPriority_QueryInterface,
656 InternetPriority_AddRef,
657 InternetPriority_Release,
658 InternetPriority_SetPriority,
659 InternetPriority_GetPriority
662 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
664 static HRESULT WINAPI Protocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
666 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
667 *ppv = iface;
668 return S_OK;
671 if(IsEqualGUID(&IID_IInternetPriority, riid)) {
672 *ppv = &InternetPriority;
673 return S_OK;
676 ok(0, "unexpected call\n");
677 *ppv = NULL;
678 return E_NOINTERFACE;
681 static ULONG WINAPI Protocol_AddRef(IInternetProtocol *iface)
683 return 2;
686 static ULONG WINAPI Protocol_Release(IInternetProtocol *iface)
688 return 1;
691 static HRESULT WINAPI Protocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
692 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
693 DWORD grfPI, DWORD dwReserved)
695 BINDINFO bindinfo, exp_bindinfo;
696 DWORD cbindf = 0;
697 HRESULT hres;
699 static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
700 static const WCHAR empty_str[] = {0};
702 CHECK_EXPECT(Start);
704 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
705 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
706 ok(!grfPI, "grfPI = %x\n", grfPI);
707 ok(!dwReserved, "dwReserved = %d\n", dwReserved);
709 memset(&bindinfo, 0, sizeof(bindinfo));
710 bindinfo.cbSize = sizeof(bindinfo);
711 memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
712 SET_EXPECT(GetBindInfo);
713 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
714 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
715 CHECK_CALLED(GetBindInfo);
716 ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
717 cbindf, (bindf|BINDF_FROMURLMON));
718 ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
720 SET_EXPECT(ReportProgress_SENDINGREQUEST);
721 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
722 BINDSTATUS_SENDINGREQUEST, empty_str);
723 ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
724 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
726 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
727 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
728 BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = empty_str);
729 ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
730 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
732 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
733 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
734 BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, expect_wsz = wszTextHtml);
735 ok(hres == S_OK,
736 "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
737 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
739 hres = IInternetProtocolSink_ReportData(pOIProtSink,
740 BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, 13, 13);
741 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
743 SET_EXPECT(ReportResult);
744 hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
745 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
746 CHECK_CALLED(ReportResult);
748 return S_OK;
751 static HRESULT WINAPI Protocol_Continue(IInternetProtocol *iface,
752 PROTOCOLDATA *pProtocolData)
754 ok(0, "unexpected call\n");
755 return E_NOTIMPL;
758 static HRESULT WINAPI Protocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
759 DWORD dwOptions)
761 ok(0, "unexpected call\n");
762 return E_NOTIMPL;
765 static HRESULT WINAPI Protocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
767 CHECK_EXPECT(Terminate);
768 ok(!dwOptions, "dwOptions=%d\n", dwOptions);
769 return S_OK;
772 static HRESULT WINAPI Protocol_Suspend(IInternetProtocol *iface)
774 ok(0, "unexpected call\n");
775 return E_NOTIMPL;
778 static HRESULT WINAPI Protocol_Resume(IInternetProtocol *iface)
780 ok(0, "unexpected call\n");
781 return E_NOTIMPL;
784 static HRESULT WINAPI Protocol_Read(IInternetProtocol *iface, void *pv,
785 ULONG cb, ULONG *pcbRead)
787 static DWORD read;
789 CHECK_EXPECT(Read);
791 ok(pv == expect_pv, "pv != expect_pv\n");
792 ok(cb == 1000, "cb=%d\n", cb);
793 ok(pcbRead != NULL, "pcbRead == NULL\n");
794 ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
796 if(read)
797 return S_FALSE;
799 memset(pv, 'x', 100);
800 *pcbRead = read = 100;
801 return S_OK;
804 static HRESULT WINAPI Protocol_Seek(IInternetProtocol *iface,
805 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
807 ok(0, "unexpected call\n");
808 return E_NOTIMPL;
811 static HRESULT WINAPI Protocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
813 ok(0, "unexpected call\n");
814 return S_OK;
817 static HRESULT WINAPI Protocol_UnlockRequest(IInternetProtocol *iface)
819 ok(0, "unexpected call\n");
820 return S_OK;
823 static const IInternetProtocolVtbl ProtocolVtbl = {
824 Protocol_QueryInterface,
825 Protocol_AddRef,
826 Protocol_Release,
827 Protocol_Start,
828 Protocol_Continue,
829 Protocol_Abort,
830 Protocol_Terminate,
831 Protocol_Suspend,
832 Protocol_Resume,
833 Protocol_Read,
834 Protocol_Seek,
835 Protocol_LockRequest,
836 Protocol_UnlockRequest
839 static IInternetProtocol Protocol = { &ProtocolVtbl };
841 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
843 ok(0, "unexpected call\n");
844 return E_NOINTERFACE;
847 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
849 return 2;
852 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
854 return 1;
857 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
858 REFIID riid, void **ppv)
860 CHECK_EXPECT(CreateInstance);
862 ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
863 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid\n");
864 ok(ppv != NULL, "ppv == NULL\n");
866 *ppv = &Protocol;
867 return S_OK;
870 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
872 ok(0, "unexpected call\n");
873 return S_OK;
876 static const IClassFactoryVtbl ClassFactoryVtbl = {
877 ClassFactory_QueryInterface,
878 ClassFactory_AddRef,
879 ClassFactory_Release,
880 ClassFactory_CreateInstance,
881 ClassFactory_LockServer
884 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
886 static void test_priority(IInternetProtocol *protocol)
888 IInternetPriority *priority;
889 LONG pr;
890 HRESULT hres;
892 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
893 (void**)&priority);
894 ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
895 if(FAILED(hres))
896 return;
898 hres = IInternetPriority_GetPriority(priority, &pr);
899 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
900 ok(pr == 0, "pr=%d, expected 0\n", pr);
902 hres = IInternetPriority_SetPriority(priority, 1);
903 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
905 hres = IInternetPriority_GetPriority(priority, &pr);
906 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
907 ok(pr == 1, "pr=%d, expected 1\n", pr);
909 IInternetPriority_Release(priority);
912 static void file_protocol_start(IInternetProtocol *protocol, LPCWSTR url, BOOL is_first)
914 HRESULT hres;
916 SET_EXPECT(GetBindInfo);
917 if(!(bindf & BINDF_FROMURLMON))
918 SET_EXPECT(ReportProgress_DIRECTBIND);
919 if(is_first) {
920 SET_EXPECT(ReportProgress_SENDINGREQUEST);
921 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
922 if(bindf & BINDF_FROMURLMON)
923 SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
924 else
925 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
927 SET_EXPECT(ReportData);
928 if(is_first)
929 SET_EXPECT(ReportResult);
931 expect_hrResult = S_OK;
933 hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
934 ok(hres == S_OK, "Start failed: %08x\n", hres);
936 CHECK_CALLED(GetBindInfo);
937 if(!(bindf & BINDF_FROMURLMON))
938 CHECK_CALLED(ReportProgress_DIRECTBIND);
939 if(is_first) {
940 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
941 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
942 if(bindf & BINDF_FROMURLMON)
943 CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
944 else
945 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
947 CHECK_CALLED(ReportData);
948 if(is_first)
949 CHECK_CALLED(ReportResult);
952 static void test_file_protocol_url(LPCWSTR url)
954 IInternetProtocolInfo *protocol_info;
955 IUnknown *unk;
956 IClassFactory *factory;
957 HRESULT hres;
959 hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
960 &IID_IUnknown, (void**)&unk);
961 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
962 if(!SUCCEEDED(hres))
963 return;
965 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
966 ok(hres == E_NOINTERFACE,
967 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
969 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
970 ok(hres == S_OK, "Could not get IClassFactory interface\n");
971 if(SUCCEEDED(hres)) {
972 IInternetProtocol *protocol;
973 BYTE buf[512];
974 ULONG cb;
975 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
976 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
978 if(SUCCEEDED(hres)) {
979 file_protocol_start(protocol, url, TRUE);
980 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
981 ok(hres == S_OK, "Read failed: %08x\n", hres);
982 ok(cb == 2, "cb=%u expected 2\n", cb);
983 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
984 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
985 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
986 ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
987 ok(cb == 0, "cb=%u expected 0\n", cb);
988 hres = IInternetProtocol_UnlockRequest(protocol);
989 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
991 file_protocol_start(protocol, url, FALSE);
992 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
993 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
994 hres = IInternetProtocol_LockRequest(protocol, 0);
995 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
996 hres = IInternetProtocol_UnlockRequest(protocol);
997 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
999 IInternetProtocol_Release(protocol);
1002 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1003 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1005 if(SUCCEEDED(hres)) {
1006 file_protocol_start(protocol, url, TRUE);
1007 hres = IInternetProtocol_LockRequest(protocol, 0);
1008 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1009 hres = IInternetProtocol_Terminate(protocol, 0);
1010 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1011 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1012 ok(hres == S_OK, "Read failed: %08x\n\n", hres);
1013 hres = IInternetProtocol_UnlockRequest(protocol);
1014 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1015 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1016 ok(hres == S_OK, "Read failed: %08x\n", hres);
1017 hres = IInternetProtocol_Terminate(protocol, 0);
1018 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1020 IInternetProtocol_Release(protocol);
1023 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
1024 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1026 if(SUCCEEDED(hres)) {
1027 file_protocol_start(protocol, url, TRUE);
1028 hres = IInternetProtocol_Terminate(protocol, 0);
1029 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1030 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
1031 ok(hres == S_OK, "Read failed: %08x\n", hres);
1032 ok(cb == 2, "cb=%u expected 2\n", cb);
1034 IInternetProtocol_Release(protocol);
1037 IClassFactory_Release(factory);
1040 IUnknown_Release(unk);
1043 static void test_file_protocol_fail(void)
1045 IInternetProtocol *protocol;
1046 HRESULT hres;
1048 static const WCHAR index_url2[] =
1049 {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
1051 hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1052 &IID_IInternetProtocol, (void**)&protocol);
1053 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1054 if(FAILED(hres))
1055 return;
1057 SET_EXPECT(GetBindInfo);
1058 expect_hrResult = MK_E_SYNTAX;
1059 hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
1060 ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
1061 CHECK_CALLED(GetBindInfo);
1063 SET_EXPECT(GetBindInfo);
1064 if(!(bindf & BINDF_FROMURLMON))
1065 SET_EXPECT(ReportProgress_DIRECTBIND);
1066 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1067 SET_EXPECT(ReportResult);
1068 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1069 hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
1070 ok(hres == INET_E_RESOURCE_NOT_FOUND,
1071 "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1072 CHECK_CALLED(GetBindInfo);
1073 if(!(bindf & BINDF_FROMURLMON))
1074 CHECK_CALLED(ReportProgress_DIRECTBIND);
1075 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1076 CHECK_CALLED(ReportResult);
1078 IInternetProtocol_Release(protocol);
1080 hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1081 &IID_IInternetProtocol, (void**)&protocol);
1082 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1083 if(FAILED(hres))
1084 return;
1086 SET_EXPECT(GetBindInfo);
1087 if(!(bindf & BINDF_FROMURLMON))
1088 SET_EXPECT(ReportProgress_DIRECTBIND);
1089 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1090 SET_EXPECT(ReportResult);
1091 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1093 hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
1094 ok(hres == INET_E_RESOURCE_NOT_FOUND,
1095 "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1096 CHECK_CALLED(GetBindInfo);
1097 if(!(bindf & BINDF_FROMURLMON))
1098 CHECK_CALLED(ReportProgress_DIRECTBIND);
1099 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1100 CHECK_CALLED(ReportResult);
1102 IInternetProtocol_Release(protocol);
1105 static void test_file_protocol(void) {
1106 WCHAR buf[MAX_PATH];
1107 DWORD size;
1108 ULONG len;
1109 HANDLE file;
1111 static const WCHAR wszFile[] = {'f','i','l','e',':',0};
1112 static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
1113 static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
1114 static const char html_doc[] = "<HTML></HTML>";
1116 trace("Testing file protocol...\n");
1117 tested_protocol = FILE_TEST;
1119 file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
1120 FILE_ATTRIBUTE_NORMAL, NULL);
1121 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
1122 if(file == INVALID_HANDLE_VALUE)
1123 return;
1124 WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
1125 CloseHandle(file);
1127 file_name = wszIndexHtml;
1128 bindf = 0;
1129 test_file_protocol_url(index_url);
1130 bindf = BINDF_FROMURLMON;
1131 test_file_protocol_url(index_url);
1133 memcpy(buf, wszFile, sizeof(wszFile));
1134 len = sizeof(wszFile)/sizeof(WCHAR)-1;
1135 len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1136 buf[len++] = '\\';
1137 memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1139 file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
1140 bindf = 0;
1141 test_file_protocol_url(buf);
1142 bindf = BINDF_FROMURLMON;
1143 test_file_protocol_url(buf);
1145 memcpy(buf, wszFile2, sizeof(wszFile2));
1146 len = sizeof(wszFile2)/sizeof(WCHAR)-1;
1147 len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1148 buf[len++] = '\\';
1149 memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1151 file_name = buf + sizeof(wszFile2)/sizeof(WCHAR)-1;
1152 bindf = 0;
1153 test_file_protocol_url(buf);
1154 bindf = BINDF_FROMURLMON;
1155 test_file_protocol_url(buf);
1157 memcpy(buf, wszFile3, sizeof(wszFile3));
1158 len = sizeof(wszFile3)/sizeof(WCHAR)-1;
1159 len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
1160 buf[len++] = '\\';
1161 memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
1163 file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
1164 bindf = 0;
1165 test_file_protocol_url(buf);
1166 bindf = BINDF_FROMURLMON;
1167 test_file_protocol_url(buf);
1169 DeleteFileW(wszIndexHtml);
1171 bindf = 0;
1172 test_file_protocol_fail();
1173 bindf = BINDF_FROMURLMON;
1174 test_file_protocol_fail();
1177 static BOOL http_protocol_start(LPCWSTR url, BOOL is_first)
1179 static BOOL got_user_agent = FALSE;
1180 HRESULT hres;
1182 first_data_notif = TRUE;
1183 state = 0;
1185 SET_EXPECT(GetBindInfo);
1186 if (!(bindf & BINDF_FROMURLMON))
1187 SET_EXPECT(ReportProgress_DIRECTBIND);
1188 SET_EXPECT(GetBindString_USER_AGENT);
1189 SET_EXPECT(GetBindString_ACCEPT_MIMES);
1190 SET_EXPECT(QueryService_HttpNegotiate);
1191 SET_EXPECT(BeginningTransaction);
1192 SET_EXPECT(GetRootSecurityId);
1193 if (http_post_test)
1194 SET_EXPECT(GetBindString_POST_COOKIE);
1196 hres = IInternetProtocol_Start(http_protocol, url, &protocol_sink, &bind_info, 0, 0);
1197 ok(hres == S_OK, "Start failed: %08x\n", hres);
1198 if(FAILED(hres))
1199 return FALSE;
1201 CHECK_CALLED(GetBindInfo);
1202 if (!(bindf & BINDF_FROMURLMON))
1203 CHECK_CALLED(ReportProgress_DIRECTBIND);
1204 if (!got_user_agent)
1206 CHECK_CALLED(GetBindString_USER_AGENT);
1207 got_user_agent = TRUE;
1209 else todo_wine
1211 /* user agent only retrieved once, even with different URLs */
1212 CHECK_NOT_CALLED(GetBindString_USER_AGENT);
1214 CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1215 CHECK_CALLED(QueryService_HttpNegotiate);
1216 CHECK_CALLED(BeginningTransaction);
1217 /* GetRootSecurityId called on WinXP but not on Win98 */
1218 CLEAR_CALLED(GetRootSecurityId);
1219 if (http_post_test)
1220 CHECK_CALLED(GetBindString_POST_COOKIE);
1222 return TRUE;
1225 /* is_first refers to whether this is the first call to this function
1226 * _for this url_ */
1227 static void test_http_protocol_url(LPCWSTR url, BOOL is_first)
1229 IInternetProtocolInfo *protocol_info;
1230 IClassFactory *factory;
1231 IUnknown *unk;
1232 HRESULT hres;
1234 trace("Testing http protocol...\n");
1235 http_url = url;
1236 http_is_first = is_first;
1238 hres = CoGetClassObject(&CLSID_HttpProtocol, CLSCTX_INPROC_SERVER, NULL,
1239 &IID_IUnknown, (void**)&unk);
1240 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1241 if(!SUCCEEDED(hres))
1242 return;
1244 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1245 ok(hres == E_NOINTERFACE,
1246 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1247 hres);
1249 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1250 ok(hres == S_OK, "Could not get IClassFactory interface\n");
1251 IUnknown_Release(unk);
1252 if(FAILED(hres))
1253 return;
1255 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1256 (void**)&http_protocol);
1257 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1258 if(SUCCEEDED(hres)) {
1259 BYTE buf[3600];
1260 DWORD cb;
1261 int *called = (bindf & BINDF_FROMURLMON) ? &called_Switch : &called_ReportData;
1263 test_priority(http_protocol);
1265 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1266 SET_EXPECT(ReportProgress_CONNECTING);
1267 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1268 if(!(bindf & BINDF_FROMURLMON)) {
1269 SET_EXPECT(OnResponse);
1270 SET_EXPECT(ReportProgress_RAWMIMETYPE);
1271 SET_EXPECT(ReportData);
1272 } else {
1273 SET_EXPECT(Switch);
1276 if(!http_protocol_start(url, is_first))
1277 return;
1279 SET_EXPECT(ReportResult);
1280 expect_hrResult = S_OK;
1282 hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb);
1283 ok((!*called && hres == E_PENDING && cb==0) ||
1284 (*called && hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
1286 WaitForSingleObject(event_complete, INFINITE);
1287 if(bindf & BINDF_FROMURLMON)
1288 CHECK_CALLED(Switch);
1289 else
1290 CHECK_CALLED(ReportData);
1292 while(1) {
1293 if(bindf & BINDF_FROMURLMON)
1294 SET_EXPECT(Switch);
1295 else
1296 SET_EXPECT(ReportData);
1297 hres = IInternetProtocol_Read(http_protocol, buf, sizeof(buf), &cb);
1298 if(hres == E_PENDING) {
1299 hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb);
1300 ok((!*called && hres == E_PENDING && cb==0) ||
1301 (*called && hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
1302 WaitForSingleObject(event_complete, INFINITE);
1303 if(bindf & BINDF_FROMURLMON)
1304 CHECK_CALLED(Switch);
1305 else
1306 CHECK_CALLED(ReportData);
1307 } else {
1308 if(bindf & BINDF_FROMURLMON)
1309 CHECK_NOT_CALLED(Switch);
1310 else
1311 CHECK_NOT_CALLED(ReportData);
1312 if(cb == 0) break;
1315 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1316 CHECK_CALLED(ReportResult);
1318 hres = IInternetProtocol_LockRequest(http_protocol, 0);
1319 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
1321 hres = IInternetProtocol_Read(http_protocol, buf, 1, &cb);
1322 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1324 hres = IInternetProtocol_Terminate(http_protocol, 0);
1325 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1327 /* This wait is to give the internet handles being freed in Terminate
1328 * enough time to actually terminate in all cases. Internet handles
1329 * terminate asynchronously and native reuses the main InternetOpen
1330 * handle. The only case in which this seems to be necessary is on
1331 * wine with native wininet and urlmon, resulting in the next time
1332 * test_http_protocol_url being called the first data notification actually
1333 * being an extra last data notification from the previous connection
1334 * about once out of every ten times. */
1335 Sleep(100);
1337 hres = IInternetProtocol_UnlockRequest(http_protocol);
1338 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
1340 IInternetProtocol_Release(http_protocol);
1343 IClassFactory_Release(factory);
1346 static void test_http_protocol(void)
1348 static const WCHAR winehq_url[] =
1349 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
1350 'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0};
1351 static const WCHAR posttest_url[] =
1352 {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.',
1353 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/',
1354 'p','o','s','t','t','e','s','t','.','p','h','p',0};
1356 tested_protocol = HTTP_TEST;
1357 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
1358 test_http_protocol_url(winehq_url, TRUE);
1359 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
1360 test_http_protocol_url(winehq_url, FALSE);
1362 http_post_test = TRUE;
1363 /* Without this flag we get a ReportProgress_CACHEFILENAMEAVAILABLE
1364 * notification with BINDVERB_POST */
1365 bindf |= BINDF_NOWRITECACHE;
1366 test_http_protocol_url(posttest_url, TRUE);
1367 http_post_test = FALSE;
1370 static void test_mk_protocol(void)
1372 IInternetProtocolInfo *protocol_info;
1373 IInternetProtocol *protocol;
1374 IClassFactory *factory;
1375 IUnknown *unk;
1376 HRESULT hres;
1378 static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
1379 ':',':','/','t','e','s','t','.','h','t','m','l',0};
1380 static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
1382 trace("Testing mk protocol...\n");
1383 tested_protocol = MK_TEST;
1385 hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
1386 &IID_IUnknown, (void**)&unk);
1387 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
1389 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
1390 ok(hres == E_NOINTERFACE,
1391 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
1392 hres);
1394 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
1395 ok(hres == S_OK, "Could not get IClassFactory interface\n");
1396 IUnknown_Release(unk);
1397 if(FAILED(hres))
1398 return;
1400 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
1401 (void**)&protocol);
1402 IClassFactory_Release(factory);
1403 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
1405 SET_EXPECT(GetBindInfo);
1406 hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
1407 ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
1408 CHECK_CALLED(GetBindInfo);
1410 SET_EXPECT(GetBindInfo);
1411 SET_EXPECT(ReportProgress_DIRECTBIND);
1412 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1413 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1414 SET_EXPECT(ReportResult);
1415 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
1417 hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
1418 ok(hres == INET_E_RESOURCE_NOT_FOUND, "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
1420 CHECK_CALLED(GetBindInfo);
1421 CHECK_CALLED(ReportProgress_DIRECTBIND);
1422 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1423 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1424 CHECK_CALLED(ReportResult);
1426 IInternetProtocol_Release(protocol);
1429 static void test_CreateBinding(void)
1431 IInternetProtocol *protocol;
1432 IInternetPriority *priority;
1433 IInternetSession *session;
1434 LONG p;
1435 BYTE buf[1000];
1436 DWORD read;
1437 HRESULT hres;
1439 static const WCHAR test_url[] =
1440 {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
1441 static const WCHAR wsz_test[] = {'t','e','s','t',0};
1443 trace("Testing CreateBinding...\n");
1444 tested_protocol = BIND_TEST;
1446 hres = CoInternetGetSession(0, &session, 0);
1447 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
1449 hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
1450 ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
1452 hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
1453 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
1454 ok(protocol != NULL, "protocol == NULL\n");
1456 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
1457 ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
1459 hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
1460 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1461 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
1462 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1463 hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
1464 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
1466 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
1467 ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
1469 p = 0xdeadbeef;
1470 hres = IInternetPriority_GetPriority(priority, &p);
1471 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1472 ok(!p, "p=%d\n", p);
1474 hres = IInternetPriority_SetPriority(priority, 100);
1475 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1477 p = 0xdeadbeef;
1478 hres = IInternetPriority_GetPriority(priority, &p);
1479 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1480 ok(p == 100, "p=%d\n", p);
1482 SET_EXPECT(QueryService_InternetProtocol);
1483 SET_EXPECT(CreateInstance);
1484 SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
1485 SET_EXPECT(SetPriority);
1486 SET_EXPECT(Start);
1488 expect_hrResult = S_OK;
1489 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
1490 ok(hres == S_OK, "Start failed: %08x\n", hres);
1492 CHECK_CALLED(QueryService_InternetProtocol);
1493 CHECK_CALLED(CreateInstance);
1494 CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
1495 CHECK_CALLED(SetPriority);
1496 CHECK_CALLED(Start);
1498 SET_EXPECT(Read);
1499 read = 0xdeadbeef;
1500 hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
1501 ok(hres == S_OK, "Read failed: %08x\n", hres);
1502 ok(read == 100, "read = %d\n", read);
1503 CHECK_CALLED(Read);
1505 SET_EXPECT(Read);
1506 read = 0xdeadbeef;
1507 hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
1508 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
1509 ok(!read, "read = %d\n", read);
1510 CHECK_CALLED(Read);
1512 p = 0xdeadbeef;
1513 hres = IInternetPriority_GetPriority(priority, &p);
1514 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
1515 ok(p == 100, "p=%d\n", p);
1517 hres = IInternetPriority_SetPriority(priority, 101);
1518 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
1520 SET_EXPECT(Terminate);
1521 hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
1522 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
1523 CHECK_CALLED(Terminate);
1525 IInternetPriority_Release(priority);
1526 IInternetBindInfo_Release(prot_bind_info);
1527 IInternetProtocol_Release(protocol);
1528 IInternetSession_Release(session);
1531 START_TEST(protocol)
1533 OleInitialize(NULL);
1535 event_complete = CreateEvent(NULL, FALSE, FALSE, NULL);
1537 test_file_protocol();
1538 test_http_protocol();
1539 test_mk_protocol();
1540 test_CreateBinding();
1542 CloseHandle(event_complete);
1544 OleUninitialize();