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