[URLMON_WINETEST] Sync with Wine Staging 2.2. CORE-12823
[reactos.git] / rostests / winetests / urlmon / protocol.c
1 /*
2 * Copyright 2005-2011 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 WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #define COBJMACROS
24 #define CONST_VTABLE
25
26 #include <wine/test.h>
27 //#include <stdarg.h>
28 #include <stdio.h>
29
30 //#include "windef.h"
31 //#include "winbase.h"
32 #include <winnls.h>
33 #include <ole2.h>
34 #include <urlmon.h>
35 #include <wininet.h>
36
37 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD, IInternetSession **, DWORD);
38 static HRESULT (WINAPI *pReleaseBindInfo)(BINDINFO*);
39 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
40
41 #define DEFINE_EXPECT(func) \
42 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
43
44 #define SET_EXPECT(func) \
45 expect_ ## func = TRUE
46
47 #define CHECK_EXPECT2(func) \
48 do { \
49 ok(expect_ ##func, "unexpected call " #func "\n"); \
50 called_ ## func = TRUE; \
51 }while(0)
52
53 #define CHECK_EXPECT(func) \
54 do { \
55 CHECK_EXPECT2(func); \
56 expect_ ## func = FALSE; \
57 }while(0)
58
59 #define CHECK_CALLED(func) \
60 do { \
61 ok(called_ ## func, "expected " #func "\n"); \
62 expect_ ## func = called_ ## func = FALSE; \
63 }while(0)
64
65 #define CHECK_NOT_CALLED(func) \
66 do { \
67 ok(!called_ ## func, "unexpected " #func "\n"); \
68 expect_ ## func = called_ ## func = FALSE; \
69 }while(0)
70
71 #define CLEAR_CALLED(func) \
72 expect_ ## func = called_ ## func = FALSE
73
74 DEFINE_EXPECT(GetBindInfo);
75 DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
76 DEFINE_EXPECT(ReportProgress_DIRECTBIND);
77 DEFINE_EXPECT(ReportProgress_RAWMIMETYPE);
78 DEFINE_EXPECT(ReportProgress_FINDINGRESOURCE);
79 DEFINE_EXPECT(ReportProgress_CONNECTING);
80 DEFINE_EXPECT(ReportProgress_SENDINGREQUEST);
81 DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
82 DEFINE_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
83 DEFINE_EXPECT(ReportProgress_PROTOCOLCLASSID);
84 DEFINE_EXPECT(ReportProgress_COOKIE_SENT);
85 DEFINE_EXPECT(ReportProgress_REDIRECTING);
86 DEFINE_EXPECT(ReportProgress_ENCODING);
87 DEFINE_EXPECT(ReportProgress_ACCEPTRANGES);
88 DEFINE_EXPECT(ReportProgress_PROXYDETECTING);
89 DEFINE_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
90 DEFINE_EXPECT(ReportProgress_DECODING);
91 DEFINE_EXPECT(ReportData);
92 DEFINE_EXPECT(ReportData2);
93 DEFINE_EXPECT(ReportResult);
94 DEFINE_EXPECT(GetBindString_ACCEPT_MIMES);
95 DEFINE_EXPECT(GetBindString_USER_AGENT);
96 DEFINE_EXPECT(GetBindString_POST_COOKIE);
97 DEFINE_EXPECT(GetBindString_URL);
98 DEFINE_EXPECT(GetBindString_ROOTDOC_URL);
99 DEFINE_EXPECT(QueryService_HttpNegotiate);
100 DEFINE_EXPECT(QueryService_InternetProtocol);
101 DEFINE_EXPECT(QueryService_HttpSecurity);
102 DEFINE_EXPECT(QueryInterface_IWinInetInfo);
103 DEFINE_EXPECT(QueryInterface_IWinInetHttpInfo);
104 DEFINE_EXPECT(BeginningTransaction);
105 DEFINE_EXPECT(GetRootSecurityId);
106 DEFINE_EXPECT(OnResponse);
107 DEFINE_EXPECT(Switch);
108 DEFINE_EXPECT(Continue);
109 DEFINE_EXPECT(CreateInstance);
110 DEFINE_EXPECT(Start);
111 DEFINE_EXPECT(StartEx);
112 DEFINE_EXPECT(Terminate);
113 DEFINE_EXPECT(Read);
114 DEFINE_EXPECT(Read2);
115 DEFINE_EXPECT(SetPriority);
116 DEFINE_EXPECT(LockRequest);
117 DEFINE_EXPECT(UnlockRequest);
118 DEFINE_EXPECT(Abort);
119 DEFINE_EXPECT(MimeFilter_CreateInstance);
120 DEFINE_EXPECT(MimeFilter_Start);
121 DEFINE_EXPECT(MimeFilter_ReportData);
122 DEFINE_EXPECT(MimeFilter_ReportResult);
123 DEFINE_EXPECT(MimeFilter_Terminate);
124 DEFINE_EXPECT(MimeFilter_LockRequest);
125 DEFINE_EXPECT(MimeFilter_UnlockRequest);
126 DEFINE_EXPECT(MimeFilter_Read);
127 DEFINE_EXPECT(MimeFilter_Switch);
128 DEFINE_EXPECT(MimeFilter_Continue);
129 DEFINE_EXPECT(Stream_Seek);
130 DEFINE_EXPECT(Stream_Read);
131
132 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
133 static const WCHAR index_url[] =
134 {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
135
136 static const WCHAR acc_mimeW[] = {'*','/','*',0};
137 static const WCHAR user_agentW[] = {'W','i','n','e',0};
138 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
139 static const WCHAR hostW[] = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
140 static const WCHAR winehq_ipW[] = {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
141 static const WCHAR emptyW[] = {0};
142 static const WCHAR pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
143 static const WCHAR gifW[] = {'i','m','a','g','e','/','g','i','f',0};
144
145 static HRESULT expect_hrResult;
146 static LPCWSTR file_name, http_url, expect_wsz;
147 static IInternetProtocol *async_protocol = NULL;
148 static BOOL first_data_notif, http_is_first, test_redirect;
149 static int prot_state, read_report_data, post_stream_read;
150 static DWORD bindf, ex_priority , pi;
151 static IInternetProtocol *binding_protocol, *filtered_protocol;
152 static IInternetBindInfo *prot_bind_info;
153 static IInternetProtocolSink *binding_sink, *filtered_sink;
154 static void *expect_pv;
155 static HANDLE event_complete, event_complete2, event_continue, event_continue_done;
156 static BOOL binding_test;
157 static PROTOCOLDATA protocoldata, *pdata, continue_protdata;
158 static DWORD prot_read, filter_state, http_post_test, thread_id;
159 static BOOL security_problem, test_async_req, impl_protex;
160 static BOOL async_read_pending, mimefilter_test, direct_read, wait_for_switch, emulate_prot, short_read, test_abort;
161 static BOOL empty_file, no_mime, bind_from_cache, file_with_hash;
162
163 enum {
164 STATE_CONNECTING,
165 STATE_SENDINGREQUEST,
166 STATE_STARTDOWNLOADING,
167 STATE_DOWNLOADING
168 } state;
169
170 static enum {
171 FILE_TEST,
172 HTTP_TEST,
173 HTTPS_TEST,
174 FTP_TEST,
175 MK_TEST,
176 ITS_TEST,
177 BIND_TEST
178 } tested_protocol;
179
180 static const WCHAR protocol_names[][10] = {
181 {'f','i','l','e',0},
182 {'h','t','t','p',0},
183 {'h','t','t','p','s',0},
184 {'f','t','p',0},
185 {'m','k',0},
186 {'i','t','s',0},
187 {'t','e','s','t',0}
188 };
189
190 static const WCHAR binding_urls[][130] = {
191 {'f','i','l','e',':','t','e','s','t','.','h','t','m','l',0},
192 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
193 'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0},
194 {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
195 '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0},
196 {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
197 '/','p','u','b','/','o','t','h','e','r',
198 '/','w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0},
199 {'m','k',':','t','e','s','t',0},
200 {'i','t','s',':','t','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0},
201 {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0}
202 };
203
204 static const CHAR post_data[] = "mode=Test";
205
206 static int strcmp_wa(LPCWSTR strw, const char *stra)
207 {
208 CHAR buf[512];
209 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
210 return lstrcmpA(stra, buf);
211 }
212
213 static const char *w2a(LPCWSTR str)
214 {
215 static char buf[INTERNET_MAX_URL_LENGTH];
216 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
217 return buf;
218 }
219
220 static HRESULT WINAPI HttpSecurity_QueryInterface(IHttpSecurity *iface, REFIID riid, void **ppv)
221 {
222 if(IsEqualGUID(&IID_IUnknown, riid)
223 || IsEqualGUID(&IID_IHttpSecurity, riid)) {
224 *ppv = iface;
225 return S_OK;
226 }
227
228 ok(0, "unexpected call\n");
229 return E_NOINTERFACE;
230 }
231
232 static ULONG WINAPI HttpSecurity_AddRef(IHttpSecurity *iface)
233 {
234 return 2;
235 }
236
237 static ULONG WINAPI HttpSecurity_Release(IHttpSecurity *iface)
238 {
239 return 1;
240 }
241
242 static HRESULT WINAPI HttpSecurity_GetWindow(IHttpSecurity* iface, REFGUID rguidReason, HWND *phwnd)
243 {
244 trace("HttpSecurity_GetWindow\n");
245
246 return S_FALSE;
247 }
248
249 static HRESULT WINAPI HttpSecurity_OnSecurityProblem(IHttpSecurity *iface, DWORD dwProblem)
250 {
251 trace("Security problem: %u\n", dwProblem);
252 ok(dwProblem == ERROR_INTERNET_SEC_CERT_REV_FAILED, "Expected ERROR_INTERNET_SEC_CERT_REV_FAILED got %u\n", dwProblem);
253
254 /* Only retry once */
255 if (security_problem)
256 return E_ABORT;
257
258 security_problem = TRUE;
259 SET_EXPECT(BeginningTransaction);
260
261 return RPC_E_RETRY;
262 }
263
264 static IHttpSecurityVtbl HttpSecurityVtbl = {
265 HttpSecurity_QueryInterface,
266 HttpSecurity_AddRef,
267 HttpSecurity_Release,
268 HttpSecurity_GetWindow,
269 HttpSecurity_OnSecurityProblem
270 };
271
272 static IHttpSecurity http_security = { &HttpSecurityVtbl };
273
274 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
275 {
276 if(IsEqualGUID(&IID_IUnknown, riid)
277 || IsEqualGUID(&IID_IHttpNegotiate, riid)
278 || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
279 *ppv = iface;
280 return S_OK;
281 }
282
283 ok(0, "unexpected call\n");
284 return E_NOINTERFACE;
285 }
286
287 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
288 {
289 return 2;
290 }
291
292 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
293 {
294 return 1;
295 }
296
297 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
298 LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
299 {
300 LPWSTR addl_headers;
301
302 static const WCHAR wszHeaders[] =
303 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
304 'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
305 'd','e','d','\r','\n',0};
306
307 CHECK_EXPECT(BeginningTransaction);
308
309 if(binding_test)
310 ok(!lstrcmpW(szURL, binding_urls[tested_protocol]), "szURL != http_url\n");
311 else
312 ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
313 ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
314 ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
315 if(pszAdditionalHeaders)
316 {
317 ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
318 if (http_post_test)
319 {
320 addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
321 memcpy(addl_headers, wszHeaders, sizeof(wszHeaders));
322 *pszAdditionalHeaders = addl_headers;
323 }
324 }
325
326 return S_OK;
327 }
328
329 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
330 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
331 {
332 CHECK_EXPECT(OnResponse);
333
334 ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
335 ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
336 ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
337 ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
338
339 return S_OK;
340 }
341
342 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
343 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
344 {
345 static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
346
347 CHECK_EXPECT(GetRootSecurityId);
348
349 ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
350 ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
351 ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
352
353 if(pcbSecurityId) {
354 ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
355 *pcbSecurityId = sizeof(sec_id);
356 }
357
358 if(pbSecurityId)
359 memcpy(pbSecurityId, sec_id, sizeof(sec_id));
360
361 return E_FAIL;
362 }
363
364 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
365 HttpNegotiate_QueryInterface,
366 HttpNegotiate_AddRef,
367 HttpNegotiate_Release,
368 HttpNegotiate_BeginningTransaction,
369 HttpNegotiate_OnResponse,
370 HttpNegotiate_GetRootSecurityId
371 };
372
373 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
374
375 static HRESULT QueryInterface(REFIID,void**);
376
377 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
378 {
379 return QueryInterface(riid, ppv);
380 }
381
382 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
383 {
384 return 2;
385 }
386
387 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
388 {
389 return 1;
390 }
391
392 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
393 REFIID riid, void **ppv)
394 {
395 if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
396 CHECK_EXPECT2(QueryService_HttpNegotiate);
397 return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
398 }
399
400 if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
401 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
402 CHECK_EXPECT(QueryService_InternetProtocol);
403 return E_NOINTERFACE;
404 }
405
406 if(IsEqualGUID(&IID_IHttpSecurity, guidService)) {
407 ok(IsEqualGUID(&IID_IHttpSecurity, riid), "unexpected riid\n");
408 CHECK_EXPECT(QueryService_HttpSecurity);
409 return IHttpSecurity_QueryInterface(&http_security, riid, ppv);
410 }
411
412 if(IsEqualGUID(&IID_IGetBindHandle, guidService)) {
413 trace("QueryService(IID_IGetBindHandle)\n");
414 *ppv = NULL;
415 return E_NOINTERFACE;
416 }
417
418 if(IsEqualGUID(&IID_IWindowForBindingUI, guidService)) {
419 trace("QueryService(IID_IWindowForBindingUI)\n");
420 *ppv = NULL;
421 return E_NOINTERFACE;
422 }
423
424 ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService));
425 return E_FAIL;
426 }
427
428 static const IServiceProviderVtbl ServiceProviderVtbl = {
429 ServiceProvider_QueryInterface,
430 ServiceProvider_AddRef,
431 ServiceProvider_Release,
432 ServiceProvider_QueryService
433 };
434
435 static IServiceProvider service_provider = { &ServiceProviderVtbl };
436
437 static HRESULT WINAPI Stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
438 {
439 static const IID IID_strm_unknown = {0x2f68429a,0x199a,0x4043,{0x93,0x11,0xf2,0xfe,0x7c,0x13,0xcc,0xb9}};
440
441 if(!IsEqualGUID(&IID_strm_unknown, riid)) /* IE11 */
442 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
443
444 *ppv = NULL;
445 return E_NOINTERFACE;
446 }
447
448 static ULONG WINAPI Stream_AddRef(IStream *iface)
449 {
450 return 2;
451 }
452
453 static ULONG WINAPI Stream_Release(IStream *iface)
454 {
455 return 1;
456 }
457
458 static HRESULT WINAPI Stream_Read(IStream *iface, void *pv,
459 ULONG cb, ULONG *pcbRead)
460 {
461 CHECK_EXPECT2(Stream_Read);
462
463 ok(GetCurrentThreadId() != thread_id, "wrong thread %d\n", GetCurrentThreadId());
464
465 ok(pv != NULL, "pv == NULL\n");
466 ok(cb == 0x20000 || broken(cb == 0x2000), "cb = %d\n", cb);
467 ok(pcbRead != NULL, "pcbRead == NULL\n");
468
469 if(post_stream_read) {
470 *pcbRead = 0;
471 return S_FALSE;
472 }
473
474 memcpy(pv, post_data, sizeof(post_data)-1);
475 post_stream_read += *pcbRead = sizeof(post_data)-1;
476 return S_OK;
477 }
478
479 static HRESULT WINAPI Stream_Write(IStream *iface, const void *pv,
480 ULONG cb, ULONG *pcbWritten)
481 {
482 ok(0, "unexpected call\n");
483 return E_NOTIMPL;
484 }
485
486 static HRESULT WINAPI Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
487 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
488 {
489 CHECK_EXPECT(Stream_Seek);
490
491 ok(!dlibMove.QuadPart, "dlibMove != 0\n");
492 ok(dwOrigin == STREAM_SEEK_SET, "dwOrigin = %d\n", dwOrigin);
493 ok(!plibNewPosition, "plibNewPosition == NULL\n");
494
495 return S_OK;
496 }
497
498 static HRESULT WINAPI Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
499 {
500 ok(0, "unexpected call\n");
501 return E_NOTIMPL;
502 }
503
504 static HRESULT WINAPI Stream_CopyTo(IStream *iface, IStream *pstm,
505 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
506 {
507 ok(0, "unexpected call\n");
508 return E_NOTIMPL;
509 }
510
511 static HRESULT WINAPI Stream_Commit(IStream *iface, DWORD grfCommitFlags)
512 {
513 ok(0, "unexpected call\n");
514 return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI Stream_Revert(IStream *iface)
518 {
519 ok(0, "unexpected call\n");
520 return E_NOTIMPL;
521 }
522
523 static HRESULT WINAPI Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
524 ULARGE_INTEGER cb, DWORD dwLockType)
525 {
526 ok(0, "unexpected call\n");
527 return E_NOTIMPL;
528 }
529
530 static HRESULT WINAPI Stream_UnlockRegion(IStream *iface,
531 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
532 {
533 ok(0, "unexpected call\n");
534 return E_NOTIMPL;
535 }
536
537 static HRESULT WINAPI Stream_Stat(IStream *iface, STATSTG *pstatstg,
538 DWORD dwStatFlag)
539 {
540 ok(0, "unexpected call\n");
541 return E_NOTIMPL;
542 }
543
544 static HRESULT WINAPI Stream_Clone(IStream *iface, IStream **ppstm)
545 {
546 ok(0, "unexpected call\n");
547 return E_NOTIMPL;
548 }
549
550 static const IStreamVtbl StreamVtbl = {
551 Stream_QueryInterface,
552 Stream_AddRef,
553 Stream_Release,
554 Stream_Read,
555 Stream_Write,
556 Stream_Seek,
557 Stream_SetSize,
558 Stream_CopyTo,
559 Stream_Commit,
560 Stream_Revert,
561 Stream_LockRegion,
562 Stream_UnlockRegion,
563 Stream_Stat,
564 Stream_Clone
565 };
566
567 static IStream Stream = { &StreamVtbl };
568
569 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
570 {
571 return QueryInterface(riid, ppv);
572 }
573
574 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
575 {
576 return 2;
577 }
578
579 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
580 {
581 return 1;
582 }
583
584 static void call_continue(PROTOCOLDATA *protocol_data)
585 {
586 HRESULT hres;
587
588 if (winetest_debug > 1)
589 trace("continue in state %d\n", state);
590
591 if(state == STATE_CONNECTING) {
592 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST) {
593 if (http_is_first){
594 CLEAR_CALLED(ReportProgress_FINDINGRESOURCE);
595 CLEAR_CALLED(ReportProgress_PROXYDETECTING);
596 }
597 CLEAR_CALLED(ReportProgress_CONNECTING);
598 }
599 if(tested_protocol == FTP_TEST)
600 todo_wine CHECK_CALLED(ReportProgress_SENDINGREQUEST);
601 else if (tested_protocol != HTTPS_TEST)
602 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
603 if(test_redirect)
604 CHECK_CALLED(ReportProgress_REDIRECTING);
605 state = test_async_req ? STATE_SENDINGREQUEST : STATE_STARTDOWNLOADING;
606 }
607
608 switch(state) {
609 case STATE_SENDINGREQUEST:
610 SET_EXPECT(Stream_Read);
611 SET_EXPECT(ReportProgress_SENDINGREQUEST);
612 break;
613 case STATE_STARTDOWNLOADING:
614 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
615 SET_EXPECT(OnResponse);
616 if(tested_protocol == HTTPS_TEST || test_redirect || test_abort || empty_file)
617 SET_EXPECT(ReportProgress_ACCEPTRANGES);
618 SET_EXPECT(ReportProgress_ENCODING);
619 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
620 if(bindf & BINDF_NEEDFILE)
621 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
622 }
623 default:
624 break;
625 }
626
627 if(state != STATE_SENDINGREQUEST)
628 SET_EXPECT(ReportData);
629 hres = IInternetProtocol_Continue(async_protocol, protocol_data);
630 ok(hres == S_OK, "Continue failed: %08x\n", hres);
631 if(tested_protocol == FTP_TEST || security_problem)
632 CLEAR_CALLED(ReportData);
633 else if(state != STATE_SENDINGREQUEST)
634 CHECK_CALLED(ReportData);
635
636 switch(state) {
637 case STATE_SENDINGREQUEST:
638 CHECK_CALLED(Stream_Read);
639 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
640 state = STATE_STARTDOWNLOADING;
641 break;
642 case STATE_STARTDOWNLOADING:
643 if (! security_problem)
644 {
645 state = STATE_DOWNLOADING;
646 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
647 CHECK_CALLED(OnResponse);
648 if(tested_protocol == HTTPS_TEST || empty_file)
649 CHECK_CALLED(ReportProgress_ACCEPTRANGES);
650 else if(test_redirect || test_abort)
651 CLEAR_CALLED(ReportProgress_ACCEPTRANGES);
652 CLEAR_CALLED(ReportProgress_ENCODING);
653 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
654 if(bindf & BINDF_NEEDFILE)
655 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
656 }
657 }
658 else
659 {
660 security_problem = FALSE;
661 SET_EXPECT(ReportProgress_CONNECTING);
662 }
663 default:
664 break;
665 }
666 }
667
668 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
669 {
670 if(tested_protocol == FTP_TEST)
671 CHECK_EXPECT2(Switch);
672 else
673 CHECK_EXPECT(Switch);
674
675 ok(pProtocolData != NULL, "pProtocolData == NULL\n");
676 if(binding_test) {
677 ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
678 ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
679 pProtocolData->grfFlags, protocoldata.grfFlags );
680 ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
681 pProtocolData->dwState, protocoldata.dwState );
682 ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
683 pProtocolData->pData, protocoldata.pData );
684 ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
685 pProtocolData->cbData, protocoldata.cbData );
686 }
687
688 pdata = pProtocolData;
689
690 if(binding_test) {
691 SetEvent(event_complete);
692 ok( WaitForSingleObject(event_complete2, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
693 return S_OK;
694 }if(direct_read) {
695 continue_protdata = *pProtocolData;
696 SetEvent(event_continue);
697 ok( WaitForSingleObject(event_continue_done, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
698 }else {
699 call_continue(pProtocolData);
700 SetEvent(event_complete);
701 }
702
703 return S_OK;
704 }
705
706 static const char *status_names[] =
707 {
708 "0",
709 "FINDINGRESOURCE",
710 "CONNECTING",
711 "REDIRECTING",
712 "BEGINDOWNLOADDATA",
713 "DOWNLOADINGDATA",
714 "ENDDOWNLOADDATA",
715 "BEGINDOWNLOADCOMPONENTS",
716 "INSTALLINGCOMPONENTS",
717 "ENDDOWNLOADCOMPONENTS",
718 "USINGCACHEDCOPY",
719 "SENDINGREQUEST",
720 "CLASSIDAVAILABLE",
721 "MIMETYPEAVAILABLE",
722 "CACHEFILENAMEAVAILABLE",
723 "BEGINSYNCOPERATION",
724 "ENDSYNCOPERATION",
725 "BEGINUPLOADDATA",
726 "UPLOADINGDATA",
727 "ENDUPLOADINGDATA",
728 "PROTOCOLCLASSID",
729 "ENCODING",
730 "VERIFIEDMIMETYPEAVAILABLE",
731 "CLASSINSTALLLOCATION",
732 "DECODING",
733 "LOADINGMIMEHANDLER",
734 "CONTENTDISPOSITIONATTACH",
735 "FILTERREPORTMIMETYPE",
736 "CLSIDCANINSTANTIATE",
737 "IUNKNOWNAVAILABLE",
738 "DIRECTBIND",
739 "RAWMIMETYPE",
740 "PROXYDETECTING",
741 "ACCEPTRANGES",
742 "COOKIE_SENT",
743 "COMPACT_POLICY_RECEIVED",
744 "COOKIE_SUPPRESSED",
745 "COOKIE_STATE_UNKNOWN",
746 "COOKIE_STATE_ACCEPT",
747 "COOKIE_STATE_REJECT",
748 "COOKIE_STATE_PROMPT",
749 "COOKIE_STATE_LEASH",
750 "COOKIE_STATE_DOWNGRADE",
751 "POLICY_HREF",
752 "P3P_HEADER",
753 "SESSION_COOKIE_RECEIVED",
754 "PERSISTENT_COOKIE_RECEIVED",
755 "SESSION_COOKIES_ALLOWED",
756 "CACHECONTROL",
757 "CONTENTDISPOSITIONFILENAME",
758 "MIMETEXTPLAINMISMATCH",
759 "PUBLISHERAVAILABLE",
760 "DISPLAYNAMEAVAILABLE"
761 };
762
763 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
764 LPCWSTR szStatusText)
765 {
766 static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
767 '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
768 static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
769
770 if (winetest_debug > 1)
771 {
772 if (ulStatusCode < sizeof(status_names)/sizeof(status_names[0]))
773 trace( "progress: %s %s\n", status_names[ulStatusCode], wine_dbgstr_w(szStatusText) );
774 else
775 trace( "progress: %u %s\n", ulStatusCode, wine_dbgstr_w(szStatusText) );
776 }
777
778 switch(ulStatusCode) {
779 case BINDSTATUS_MIMETYPEAVAILABLE:
780 CHECK_EXPECT2(ReportProgress_MIMETYPEAVAILABLE);
781 if(tested_protocol != FILE_TEST && tested_protocol != ITS_TEST && !mimefilter_test && (pi & PI_MIMEVERIFICATION)) {
782 if(!short_read || !direct_read)
783 CHECK_CALLED(Read); /* set in Continue */
784 else if(short_read)
785 CHECK_CALLED(Read2); /* set in Read */
786 }
787 ok(szStatusText != NULL, "szStatusText == NULL\n");
788 if(szStatusText) {
789 if(tested_protocol == BIND_TEST)
790 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText %s\n", wine_dbgstr_w(szStatusText));
791 else if (http_post_test)
792 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
793 !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
794 "szStatusText != text/plain\n");
795 else if(empty_file)
796 ok(!strcmp_wa(szStatusText, "application/javascript"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
797 else if((pi & PI_MIMEVERIFICATION) && emulate_prot && !mimefilter_test
798 && tested_protocol==HTTP_TEST && !short_read)
799 ok(lstrlenW(gifW) <= lstrlenW(szStatusText) &&
800 !memcmp(szStatusText, gifW, lstrlenW(gifW)*sizeof(WCHAR)),
801 "szStatusText != image/gif\n");
802 else if(!mimefilter_test)
803 ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) &&
804 !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
805 "szStatusText != text/html\n");
806 }
807 break;
808 case BINDSTATUS_DIRECTBIND:
809 CHECK_EXPECT2(ReportProgress_DIRECTBIND);
810 ok(szStatusText == NULL, "szStatusText != NULL\n");
811 break;
812 case BINDSTATUS_RAWMIMETYPE:
813 CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
814 ok(szStatusText != NULL, "szStatusText == NULL\n");
815 if(szStatusText)
816 ok(lstrlenW(szStatusText) < lstrlenW(text_htmlW) ||
817 !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
818 "szStatusText != text/html\n");
819 break;
820 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
821 CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
822 ok(szStatusText != NULL, "szStatusText == NULL\n");
823 if(szStatusText) {
824 if(binding_test)
825 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText\n");
826 else if(tested_protocol == FILE_TEST)
827 ok(!lstrcmpW(szStatusText, file_name), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
828 else
829 ok(szStatusText != NULL, "szStatusText == NULL\n");
830 }
831 break;
832 case BINDSTATUS_FINDINGRESOURCE:
833 CHECK_EXPECT2(ReportProgress_FINDINGRESOURCE);
834 ok(szStatusText != NULL, "szStatusText == NULL\n");
835 break;
836 case BINDSTATUS_CONNECTING:
837 CHECK_EXPECT2(ReportProgress_CONNECTING);
838 ok(szStatusText != NULL, "szStatusText == NULL\n");
839 break;
840 case BINDSTATUS_SENDINGREQUEST:
841 CHECK_EXPECT2(ReportProgress_SENDINGREQUEST);
842 if(tested_protocol == FILE_TEST || tested_protocol == ITS_TEST) {
843 ok(szStatusText != NULL, "szStatusText == NULL\n");
844 if(szStatusText)
845 ok(!*szStatusText, "wrong szStatusText\n");
846 }
847 break;
848 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
849 CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
850 ok(szStatusText != NULL, "szStatusText == NULL\n");
851 if(szStatusText)
852 ok(!strcmp_wa(szStatusText, "text/html"), "szStatusText != text/html\n");
853 break;
854 case BINDSTATUS_PROTOCOLCLASSID:
855 CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
856 ok(szStatusText != NULL, "szStatusText == NULL\n");
857 ok(!lstrcmpW(szStatusText, null_guid), "unexpected classid %s\n", wine_dbgstr_w(szStatusText));
858 break;
859 case BINDSTATUS_COOKIE_SENT:
860 CHECK_EXPECT2(ReportProgress_COOKIE_SENT);
861 ok(szStatusText == NULL, "szStatusText != NULL\n");
862 break;
863 case BINDSTATUS_REDIRECTING:
864 CHECK_EXPECT(ReportProgress_REDIRECTING);
865 if(test_redirect)
866 ok(!strcmp_wa(szStatusText, "http://test.winehq.org/tests/hello.html"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
867 else
868 ok(szStatusText == NULL, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
869 break;
870 case BINDSTATUS_ENCODING:
871 CHECK_EXPECT(ReportProgress_ENCODING);
872 ok(!strcmp_wa(szStatusText, "gzip"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
873 break;
874 case BINDSTATUS_ACCEPTRANGES:
875 CHECK_EXPECT(ReportProgress_ACCEPTRANGES);
876 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
877 break;
878 case BINDSTATUS_PROXYDETECTING:
879 if(!called_ReportProgress_PROXYDETECTING)
880 SET_EXPECT(ReportProgress_CONNECTING);
881 CHECK_EXPECT2(ReportProgress_PROXYDETECTING);
882 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
883 break;
884 case BINDSTATUS_LOADINGMIMEHANDLER:
885 CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
886 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
887 break;
888 case BINDSTATUS_DECODING:
889 CHECK_EXPECT(ReportProgress_DECODING);
890 ok(!lstrcmpW(szStatusText, pjpegW), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
891 break;
892 case BINDSTATUS_RESERVED_7:
893 trace("BINDSTATUS_RESERVED_7\n");
894 break;
895 case BINDSTATUS_RESERVED_8:
896 trace("BINDSTATUS_RESERVED_8\n");
897 break;
898 default:
899 ok(0, "Unexpected status %d (%d)\n", ulStatusCode, ulStatusCode-BINDSTATUS_LAST);
900 };
901
902 return S_OK;
903 }
904
905 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
906 ULONG ulProgress, ULONG ulProgressMax)
907 {
908 HRESULT hres;
909
910 static int rec_depth;
911 rec_depth++;
912
913 if(!mimefilter_test && (tested_protocol == FILE_TEST || tested_protocol == ITS_TEST)) {
914 CHECK_EXPECT2(ReportData);
915
916 ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
917 ulProgress, ulProgressMax);
918 if(!file_with_hash)
919 ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
920 /* BSCF_SKIPDRAINDATAFORFILEURLS added in IE8 */
921 if(tested_protocol == FILE_TEST)
922 ok((grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION)) ||
923 (grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_SKIPDRAINDATAFORFILEURLS)),
924 "grcfBSCF = %08x\n", grfBSCF);
925 else
926 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
927 }else if(bind_from_cache) {
928 CHECK_EXPECT(ReportData);
929
930 ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
931 ok(ulProgress == 1000, "ulProgress = %u\n", ulProgress);
932 ok(!ulProgressMax, "ulProgressMax = %u\n", ulProgressMax);
933 }else if(direct_read) {
934 BYTE buf[14096];
935 ULONG read;
936
937 if(!read_report_data && rec_depth == 1) {
938 BOOL reported_all_data = called_ReportData2;
939
940 CHECK_EXPECT2(ReportData);
941
942 if(short_read) {
943 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE)
944 || grfBSCF == BSCF_FIRSTDATANOTIFICATION, /* < IE8 */
945 "grcfBSCF = %08x\n", grfBSCF);
946 CHECK_CALLED(Read); /* Set in Continue */
947 first_data_notif = FALSE;
948 }else if(first_data_notif) {
949 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
950 first_data_notif = FALSE;
951 }else if(reported_all_data) {
952 ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION),
953 "grcfBSCF = %08x\n", grfBSCF);
954 }else if(!direct_read) {
955 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
956 }
957
958 do {
959 read = 0;
960 if(emulate_prot)
961 SET_EXPECT(Read);
962 else
963 SET_EXPECT(ReportData2);
964 SET_EXPECT(ReportResult);
965 if(!emulate_prot)
966 SET_EXPECT(Switch);
967 hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
968 ok(hres == E_PENDING || hres == S_FALSE || hres == S_OK, "Read failed: %08x\n", hres);
969 if(hres == S_OK)
970 ok(read, "read == 0\n");
971 if(reported_all_data)
972 ok(hres == S_FALSE, "Read failed: %08x, expected S_FALSE\n", hres);
973 if(!emulate_prot && hres != E_PENDING)
974 CHECK_NOT_CALLED(Switch); /* otherwise checked in wait_for_switch loop */
975 if(emulate_prot)
976 CHECK_CALLED(Read);
977 if(!reported_all_data && called_ReportData2) {
978 if(!emulate_prot)
979 CHECK_CALLED(ReportData2);
980 CHECK_CALLED(ReportResult);
981 reported_all_data = TRUE;
982 }else {
983 if(!emulate_prot)
984 CHECK_NOT_CALLED(ReportData2);
985 CHECK_NOT_CALLED(ReportResult);
986 }
987 }while(hres == S_OK);
988 if(hres == S_FALSE)
989 wait_for_switch = FALSE;
990 }else {
991 CHECK_EXPECT(ReportData2);
992
993 ok(grfBSCF & BSCF_LASTDATANOTIFICATION, "grfBSCF = %08x\n", grfBSCF);
994
995 read = 0xdeadbeef;
996 if(emulate_prot)
997 SET_EXPECT(Read2);
998 hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
999 if(emulate_prot)
1000 CHECK_CALLED(Read2);
1001 ok(hres == S_FALSE, "Read returned: %08x, expected E_FALSE\n", hres);
1002 ok(!read, "read = %d\n", read);
1003 }
1004 }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST
1005 || tested_protocol == FTP_TEST)) {
1006 if(empty_file)
1007 CHECK_EXPECT2(ReportData);
1008 else if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
1009 CHECK_EXPECT(ReportData);
1010 else if (http_post_test)
1011 ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
1012
1013 if(empty_file) {
1014 ok(!ulProgress, "ulProgress = %d\n", ulProgress);
1015 ok(!ulProgressMax, "ulProgressMax = %d\n", ulProgressMax);
1016 }else {
1017 ok(ulProgress, "ulProgress == 0\n");
1018 }
1019
1020 if(empty_file) {
1021 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION),
1022 "grcfBSCF = %08x\n", grfBSCF);
1023 first_data_notif = FALSE;
1024 }else if(first_data_notif) {
1025 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
1026 || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
1027 "grcfBSCF = %08x\n", grfBSCF);
1028 first_data_notif = FALSE;
1029 } else {
1030 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
1031 || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
1032 || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
1033 "grcfBSCF = %08x\n", grfBSCF);
1034 }
1035
1036 if(!(bindf & BINDF_FROMURLMON) &&
1037 !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
1038 if(state == STATE_CONNECTING) {
1039 state = STATE_DOWNLOADING;
1040 if(http_is_first) {
1041 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1042 CHECK_CALLED(ReportProgress_CONNECTING);
1043 }
1044 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1045 CHECK_CALLED(OnResponse);
1046 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
1047 }
1048 SetEvent(event_complete);
1049 }
1050 }else if(!read_report_data) {
1051 BYTE buf[1000];
1052 ULONG read;
1053 HRESULT hres;
1054
1055 CHECK_EXPECT(ReportData);
1056
1057 if(tested_protocol != BIND_TEST) {
1058 do {
1059 if(mimefilter_test)
1060 SET_EXPECT(MimeFilter_Read);
1061 else if(rec_depth > 1)
1062 SET_EXPECT(Read2);
1063 else
1064 SET_EXPECT(Read);
1065 hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
1066 if(mimefilter_test)
1067 CHECK_CALLED(MimeFilter_Read);
1068 else if(rec_depth > 1)
1069 CHECK_CALLED(Read2);
1070 else
1071 CHECK_CALLED(Read);
1072 }while(hres == S_OK);
1073 }
1074 }
1075
1076 rec_depth--;
1077 return S_OK;
1078 }
1079
1080 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1081 DWORD dwError, LPCWSTR szResult)
1082 {
1083 CHECK_EXPECT(ReportResult);
1084
1085 if(tested_protocol == FTP_TEST)
1086 ok(hrResult == E_PENDING || hrResult == S_OK, "hrResult = %08x, expected E_PENDING or S_OK\n", hrResult);
1087 else
1088 ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
1089 hrResult, expect_hrResult);
1090 #ifdef __REACTOS__
1091 if(!winetest_interactive && tested_protocol != FTP_TEST && hrResult != expect_hrResult) {
1092 skip("CORE-10360/ROSTESTS-192: Test might hang, skipping the rest!\n");
1093 exit(1);
1094 }
1095 #endif
1096 if(SUCCEEDED(hrResult) || tested_protocol == FTP_TEST || test_abort)
1097 ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
1098 else
1099 ok(dwError != ERROR_SUCCESS ||
1100 broken(tested_protocol == MK_TEST), /* WinME and NT4 */
1101 "dwError == ERROR_SUCCESS\n");
1102 ok(!szResult, "szResult != NULL\n");
1103
1104 if(direct_read)
1105 SET_EXPECT(ReportData); /* checked after main loop */
1106
1107 return S_OK;
1108 }
1109
1110 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
1111 ProtocolSink_QueryInterface,
1112 ProtocolSink_AddRef,
1113 ProtocolSink_Release,
1114 ProtocolSink_Switch,
1115 ProtocolSink_ReportProgress,
1116 ProtocolSink_ReportData,
1117 ProtocolSink_ReportResult
1118 };
1119
1120 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
1121
1122 static HRESULT WINAPI MimeProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
1123 {
1124 if(IsEqualGUID(&IID_IUnknown, riid)
1125 || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
1126 *ppv = iface;
1127 return S_OK;
1128 }
1129
1130 ok(0, "unexpected call\n");
1131 return E_NOTIMPL;
1132 }
1133
1134 static ULONG WINAPI MimeProtocolSink_AddRef(IInternetProtocolSink *iface)
1135 {
1136 return 2;
1137 }
1138
1139 static ULONG WINAPI MimeProtocolSink_Release(IInternetProtocolSink *iface)
1140 {
1141 return 1;
1142 }
1143
1144 static HRESULT WINAPI MimeProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
1145 {
1146 HRESULT hres;
1147
1148 CHECK_EXPECT(MimeFilter_Switch);
1149
1150 SET_EXPECT(Switch);
1151 hres = IInternetProtocolSink_Switch(filtered_sink, pProtocolData);
1152 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1153 CHECK_CALLED(Switch);
1154
1155 return S_OK;
1156 }
1157
1158 static HRESULT WINAPI MimeProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
1159 LPCWSTR szStatusText)
1160 {
1161 switch(ulStatusCode) {
1162 case BINDSTATUS_LOADINGMIMEHANDLER:
1163 /*
1164 * IE9 for some reason (bug?) calls this on mime handler's protocol sink instead of the
1165 * main protocol sink. We check ReportProgress_LOADINGMIMEHANDLER both here and in
1166 * ProtocolSink_ReportProgress to workaround it.
1167 */
1168 CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1169 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
1170 break;
1171 default:
1172 ok(0, "Unexpected status code %d\n", ulStatusCode);
1173 }
1174
1175 return S_OK;
1176 }
1177
1178 static HRESULT WINAPI MimeProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
1179 ULONG ulProgress, ULONG ulProgressMax)
1180 {
1181 DWORD read = 0;
1182 BYTE buf[8192];
1183 HRESULT hres;
1184 BOOL report_mime = FALSE;
1185
1186 CHECK_EXPECT(MimeFilter_ReportData);
1187
1188 if(!filter_state && !no_mime) {
1189 SET_EXPECT(Read);
1190 hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
1191 if(tested_protocol == HTTP_TEST)
1192 ok(hres == S_OK || hres == E_PENDING || hres == S_FALSE, "Read failed: %08x\n", hres);
1193 else
1194 ok(hres == S_OK, "Read failed: %08x\n", hres);
1195 CHECK_CALLED(Read);
1196
1197 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1198 hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, text_htmlW);
1199 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1200 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1201
1202 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1203 hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW);
1204 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1205 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1206
1207 /* FIXME: test BINDSTATUS_CACHEFILENAMEAVAILABLE */
1208 }
1209
1210 if(no_mime && prot_read<200) {
1211 SET_EXPECT(Read);
1212 }else if(no_mime && prot_read<300) {
1213 report_mime = TRUE;
1214 SET_EXPECT(Read);
1215 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1216 SET_EXPECT(ReportData);
1217 }else if(!read_report_data) {
1218 SET_EXPECT(ReportData);
1219 }
1220 hres = IInternetProtocolSink_ReportData(filtered_sink, grfBSCF, ulProgress, ulProgressMax);
1221 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1222 if(no_mime && prot_read<=200) {
1223 CHECK_CALLED(Read);
1224 }else if(report_mime) {
1225 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1226 CHECK_CALLED(ReportData);
1227 }else if(!read_report_data) {
1228 CHECK_CALLED(ReportData);
1229 }
1230
1231 if(!filter_state)
1232 filter_state = 1;
1233
1234 return S_OK;
1235 }
1236
1237 static HRESULT WINAPI MimeProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1238 DWORD dwError, LPCWSTR szResult)
1239 {
1240 HRESULT hres;
1241
1242 CHECK_EXPECT(MimeFilter_ReportResult);
1243
1244 ok(hrResult == S_OK, "hrResult = %08x\n", hrResult);
1245 ok(dwError == ERROR_SUCCESS, "dwError = %u\n", dwError);
1246 ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1247
1248 SET_EXPECT(ReportResult);
1249 hres = IInternetProtocolSink_ReportResult(filtered_sink, hrResult, dwError, szResult);
1250 ok(SUCCEEDED(hres), "ReportResult failed: %08x\n", hres);
1251 CHECK_CALLED(ReportResult);
1252
1253 return S_OK;
1254 }
1255
1256 static IInternetProtocolSinkVtbl mime_protocol_sink_vtbl = {
1257 MimeProtocolSink_QueryInterface,
1258 MimeProtocolSink_AddRef,
1259 MimeProtocolSink_Release,
1260 MimeProtocolSink_Switch,
1261 MimeProtocolSink_ReportProgress,
1262 MimeProtocolSink_ReportData,
1263 MimeProtocolSink_ReportResult
1264 };
1265
1266 static IInternetProtocolSink mime_protocol_sink = { &mime_protocol_sink_vtbl };
1267
1268 static HRESULT QueryInterface(REFIID riid, void **ppv)
1269 {
1270 static const IID IID_undocumented = {0x58DFC7D0,0x5381,0x43E5,{0x9D,0x72,0x4C,0xDD,0xE4,0xCB,0x0F,0x1A}};
1271 static const IID IID_undocumentedIE10 = {0xc28722e5,0xbc1a,0x4c55,{0xa6,0x8d,0x33,0x21,0x9f,0x69,0x89,0x10}};
1272
1273 *ppv = NULL;
1274
1275 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
1276 *ppv = &protocol_sink;
1277 if(IsEqualGUID(&IID_IServiceProvider, riid))
1278 *ppv = &service_provider;
1279 if(IsEqualGUID(&IID_IUriContainer, riid))
1280 return E_NOINTERFACE; /* TODO */
1281
1282 /* NOTE: IE8 queries for undocumented {58DFC7D0-5381-43E5-9D72-4CDDE4CB0F1A} interface. */
1283 if(IsEqualGUID(&IID_undocumented, riid))
1284 return E_NOINTERFACE;
1285 /* NOTE: IE10 queries for undocumented {c28722e5-bc1a-4c55-a68d-33219f698910} interface. */
1286 if(IsEqualGUID(&IID_undocumentedIE10, riid))
1287 return E_NOINTERFACE;
1288
1289 if(*ppv)
1290 return S_OK;
1291
1292 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
1293 return E_NOINTERFACE;
1294 }
1295
1296 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
1297 {
1298 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
1299 *ppv = iface;
1300 return S_OK;
1301 }
1302 return E_NOINTERFACE;
1303 }
1304
1305 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
1306 {
1307 return 2;
1308 }
1309
1310 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
1311 {
1312 return 1;
1313 }
1314
1315 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
1316 {
1317 DWORD cbSize;
1318
1319 CHECK_EXPECT(GetBindInfo);
1320
1321 ok(grfBINDF != NULL, "grfBINDF == NULL\n");
1322 ok(pbindinfo != NULL, "pbindinfo == NULL\n");
1323 ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
1324
1325 *grfBINDF = bindf;
1326 if(binding_test)
1327 *grfBINDF |= BINDF_FROMURLMON;
1328 cbSize = pbindinfo->cbSize;
1329 memset(pbindinfo, 0, cbSize);
1330 pbindinfo->cbSize = cbSize;
1331
1332 if(http_post_test)
1333 {
1334 pbindinfo->cbstgmedData = sizeof(post_data)-1;
1335 pbindinfo->dwBindVerb = BINDVERB_POST;
1336 pbindinfo->stgmedData.tymed = http_post_test;
1337
1338 if(http_post_test == TYMED_HGLOBAL) {
1339 HGLOBAL data;
1340
1341 /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly */
1342 data = GlobalAlloc(GPTR, sizeof(post_data));
1343 memcpy(data, post_data, sizeof(post_data));
1344 U(pbindinfo->stgmedData).hGlobal = data;
1345 }else {
1346 IStream *post_stream;
1347 HGLOBAL data;
1348 HRESULT hres;
1349
1350 if(0) {
1351 /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly */
1352 data = GlobalAlloc(GPTR, sizeof(post_data));
1353 memcpy(data, post_data, sizeof(post_data));
1354 U(pbindinfo->stgmedData).hGlobal = data;
1355
1356 hres = CreateStreamOnHGlobal(data, FALSE, &post_stream);
1357 ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
1358
1359 U(pbindinfo->stgmedData).pstm =post_stream;/* &Stream; */
1360 }
1361 U(pbindinfo->stgmedData).pstm = &Stream;
1362 }
1363 }
1364
1365 return S_OK;
1366 }
1367
1368 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
1369 LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1370 {
1371 ok(ppwzStr != NULL, "ppwzStr == NULL\n");
1372 ok(pcElFetched != NULL, "pcElFetched == NULL\n");
1373
1374 switch(ulStringType) {
1375 case BINDSTRING_ACCEPT_MIMES:
1376 CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
1377 ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
1378 if(pcElFetched) {
1379 ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
1380 *pcElFetched = 1;
1381 }
1382 if(ppwzStr) {
1383 *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
1384 memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
1385 }
1386 return S_OK;
1387 case BINDSTRING_USER_AGENT:
1388 CHECK_EXPECT(GetBindString_USER_AGENT);
1389 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1390 if(pcElFetched) {
1391 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1392 *pcElFetched = 1;
1393 }
1394 if(ppwzStr) {
1395 *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
1396 memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
1397 }
1398 return S_OK;
1399 case BINDSTRING_POST_COOKIE:
1400 CHECK_EXPECT(GetBindString_POST_COOKIE);
1401 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1402 if(pcElFetched)
1403 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1404 return S_OK;
1405 case BINDSTRING_URL: {
1406 DWORD size;
1407
1408 CHECK_EXPECT(GetBindString_URL);
1409 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1410 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1411 *pcElFetched = 1;
1412
1413 size = (lstrlenW(binding_urls[tested_protocol])+1)*sizeof(WCHAR);
1414 *ppwzStr = CoTaskMemAlloc(size);
1415 memcpy(*ppwzStr, binding_urls[tested_protocol], size);
1416 return S_OK;
1417 }
1418 case BINDSTRING_ROOTDOC_URL:
1419 CHECK_EXPECT(GetBindString_ROOTDOC_URL);
1420 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1421 return E_NOTIMPL;
1422 case BINDSTRING_ENTERPRISE_ID:
1423 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1424 return E_NOTIMPL;
1425 default:
1426 ok(0, "unexpected ulStringType %d\n", ulStringType);
1427 }
1428
1429 return E_NOTIMPL;
1430 }
1431
1432 static IInternetBindInfoVtbl bind_info_vtbl = {
1433 BindInfo_QueryInterface,
1434 BindInfo_AddRef,
1435 BindInfo_Release,
1436 BindInfo_GetBindInfo,
1437 BindInfo_GetBindString
1438 };
1439
1440 static IInternetBindInfo bind_info = { &bind_info_vtbl };
1441
1442 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1443 REFIID riid, void **ppv)
1444 {
1445 ok(0, "unexpected call\n");
1446 return E_NOINTERFACE;
1447 }
1448
1449 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1450 {
1451 return 2;
1452 }
1453
1454 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1455 {
1456 return 1;
1457 }
1458
1459 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1460 {
1461 CHECK_EXPECT(SetPriority);
1462 ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
1463 return S_OK;
1464 }
1465
1466 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1467 {
1468 ok(0, "unexpected call\n");
1469 return E_NOTIMPL;
1470 }
1471
1472
1473 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1474 InternetPriority_QueryInterface,
1475 InternetPriority_AddRef,
1476 InternetPriority_Release,
1477 InternetPriority_SetPriority,
1478 InternetPriority_GetPriority
1479 };
1480
1481 static IInternetPriority InternetPriority = { &InternetPriorityVtbl };
1482
1483 static ULONG WINAPI Protocol_AddRef(IInternetProtocolEx *iface)
1484 {
1485 return 2;
1486 }
1487
1488 static ULONG WINAPI Protocol_Release(IInternetProtocolEx *iface)
1489 {
1490 return 1;
1491 }
1492
1493 static HRESULT WINAPI Protocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
1494 DWORD dwOptions)
1495 {
1496 HRESULT hres;
1497
1498 CHECK_EXPECT(Abort);
1499
1500 SET_EXPECT(ReportResult);
1501 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1502 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1503 CHECK_CALLED(ReportResult);
1504
1505 return S_OK;
1506 }
1507
1508 static HRESULT WINAPI Protocol_Suspend(IInternetProtocolEx *iface)
1509 {
1510 ok(0, "unexpected call\n");
1511 return E_NOTIMPL;
1512 }
1513
1514 static HRESULT WINAPI Protocol_Resume(IInternetProtocolEx *iface)
1515 {
1516 ok(0, "unexpected call\n");
1517 return E_NOTIMPL;
1518 }
1519
1520 static HRESULT WINAPI Protocol_Seek(IInternetProtocolEx *iface,
1521 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1522 {
1523 ok(0, "unexpected call\n");
1524 return E_NOTIMPL;
1525 }
1526
1527 static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
1528 {
1529 static const IID unknown_iid = {0x7daf9908,0x8415,0x4005,{0x95,0xae, 0xbd,0x27,0xf6,0xe3,0xdc,0x00}};
1530
1531 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
1532 *ppv = iface;
1533 return S_OK;
1534 }
1535
1536 if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
1537 if(impl_protex) {
1538 *ppv = iface;
1539 return S_OK;
1540 }
1541 *ppv = NULL;
1542 return E_NOINTERFACE;
1543 }
1544
1545 if(IsEqualGUID(&IID_IInternetPriority, riid)) {
1546 *ppv = &InternetPriority;
1547 return S_OK;
1548 }
1549
1550 if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
1551 CHECK_EXPECT(QueryInterface_IWinInetInfo);
1552 *ppv = NULL;
1553 return E_NOINTERFACE;
1554 }
1555
1556 if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
1557 CHECK_EXPECT(QueryInterface_IWinInetHttpInfo);
1558 *ppv = NULL;
1559 return E_NOINTERFACE;
1560 }
1561
1562 if(!IsEqualGUID(riid, &unknown_iid)) /* IE10 */
1563 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
1564 *ppv = NULL;
1565 return E_NOINTERFACE;
1566 }
1567
1568 static DWORD WINAPI thread_proc(PVOID arg)
1569 {
1570 HRESULT hres;
1571
1572 memset(&protocoldata, -1, sizeof(protocoldata));
1573
1574 prot_state = 0;
1575
1576 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1577 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1578 BINDSTATUS_FINDINGRESOURCE, hostW);
1579 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1580 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1581
1582 SET_EXPECT(ReportProgress_CONNECTING);
1583 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1584 BINDSTATUS_CONNECTING, winehq_ipW);
1585 CHECK_CALLED(ReportProgress_CONNECTING);
1586 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1587
1588 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1589 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1590 BINDSTATUS_SENDINGREQUEST, NULL);
1591 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1592 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1593
1594 prot_state = 1;
1595 SET_EXPECT(Switch);
1596 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1597 CHECK_CALLED(Switch);
1598 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1599
1600 if(!short_read) {
1601 prot_state = 2;
1602 if(mimefilter_test)
1603 SET_EXPECT(MimeFilter_Switch);
1604 else
1605 SET_EXPECT(Switch);
1606 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1607 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1608 if(mimefilter_test)
1609 CHECK_CALLED(MimeFilter_Switch);
1610 else
1611 CHECK_CALLED(Switch);
1612
1613 if(test_abort) {
1614 SetEvent(event_complete);
1615 return 0;
1616 }
1617
1618 prot_state = 2;
1619 if(mimefilter_test)
1620 SET_EXPECT(MimeFilter_Switch);
1621 else
1622 SET_EXPECT(Switch);
1623 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1624 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1625 if(mimefilter_test)
1626 CHECK_CALLED(MimeFilter_Switch);
1627 else
1628 CHECK_CALLED(Switch);
1629
1630 prot_state = 3;
1631 if(mimefilter_test)
1632 SET_EXPECT(MimeFilter_Switch);
1633 else
1634 SET_EXPECT(Switch);
1635 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1636 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1637 if(mimefilter_test)
1638 CHECK_CALLED(MimeFilter_Switch);
1639 else
1640 CHECK_CALLED(Switch);
1641 }
1642
1643 SetEvent(event_complete);
1644
1645 return 0;
1646 }
1647
1648 static void protocol_start(IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD pi)
1649 {
1650 BINDINFO bindinfo, exp_bindinfo;
1651 DWORD cbindf = 0;
1652 HRESULT hres;
1653
1654 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
1655 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
1656 ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
1657 ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
1658 ok(!pi, "pi = %x\n", pi);
1659
1660 if(binding_test)
1661 ok(pOIProtSink == binding_sink, "pOIProtSink != binding_sink\n");
1662
1663 memset(&bindinfo, 0, sizeof(bindinfo));
1664 bindinfo.cbSize = sizeof(bindinfo);
1665 memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
1666 SET_EXPECT(GetBindInfo);
1667 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
1668 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
1669 CHECK_CALLED(GetBindInfo);
1670 ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
1671 cbindf, (bindf|BINDF_FROMURLMON));
1672 ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
1673 pReleaseBindInfo(&bindinfo);
1674
1675 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1676 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
1677 ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
1678 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1679
1680 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
1681 IServiceProvider *service_provider;
1682 IHttpNegotiate *http_negotiate;
1683 IHttpNegotiate2 *http_negotiate2;
1684 LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
1685 LPWSTR additional_headers = NULL;
1686 BYTE sec_id[100];
1687 DWORD fetched = 0, size = 100;
1688 DWORD tid;
1689
1690 SET_EXPECT(GetBindString_USER_AGENT);
1691 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
1692 &ua, 1, &fetched);
1693 CHECK_CALLED(GetBindString_USER_AGENT);
1694 ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
1695 ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
1696 ok(ua != NULL, "ua = %p\n", ua);
1697 ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", wine_dbgstr_w(ua));
1698 CoTaskMemFree(ua);
1699
1700 fetched = 256;
1701 SET_EXPECT(GetBindString_ACCEPT_MIMES);
1702 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
1703 accept_mimes, 256, &fetched);
1704 CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1705
1706 ok(hres == S_OK,
1707 "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
1708 ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
1709 ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", wine_dbgstr_w(accept_mimes[0]));
1710 CoTaskMemFree(accept_mimes[0]);
1711
1712 hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
1713 (void**)&service_provider);
1714 ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
1715
1716 SET_EXPECT(QueryService_HttpNegotiate);
1717 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1718 &IID_IHttpNegotiate, (void**)&http_negotiate);
1719 CHECK_CALLED(QueryService_HttpNegotiate);
1720 ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1721
1722 SET_EXPECT(BeginningTransaction);
1723 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
1724 NULL, 0, &additional_headers);
1725 CHECK_CALLED(BeginningTransaction);
1726 IHttpNegotiate_Release(http_negotiate);
1727 ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
1728 ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
1729
1730 SET_EXPECT(QueryService_HttpNegotiate);
1731 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
1732 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
1733 CHECK_CALLED(QueryService_HttpNegotiate);
1734 ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1735
1736 size = 512;
1737 SET_EXPECT(GetRootSecurityId);
1738 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
1739 CHECK_CALLED(GetRootSecurityId);
1740 IHttpNegotiate2_Release(http_negotiate2);
1741 ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
1742 ok(size == 13, "size=%d\n", size);
1743
1744 IServiceProvider_Release(service_provider);
1745
1746 CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
1747 return;
1748 }
1749
1750 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1751 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
1752 BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1753 ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1754 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1755
1756 if(mimefilter_test) {
1757 SET_EXPECT(MimeFilter_CreateInstance);
1758 SET_EXPECT(MimeFilter_Start);
1759 SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1760 }
1761 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1762 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
1763 mimefilter_test ? pjpegW : (expect_wsz = text_htmlW));
1764 ok(hres == S_OK,
1765 "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
1766 if(mimefilter_test) {
1767 CHECK_CALLED(MimeFilter_CreateInstance);
1768 CHECK_CALLED(MimeFilter_Start);
1769 CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1770 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1771 }else {
1772 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1773 }
1774
1775 if(mimefilter_test)
1776 SET_EXPECT(MimeFilter_ReportData);
1777 else
1778 SET_EXPECT(ReportData);
1779 hres = IInternetProtocolSink_ReportData(pOIProtSink,
1780 BSCF_FIRSTDATANOTIFICATION | (tested_protocol == ITS_TEST ? BSCF_DATAFULLYAVAILABLE : BSCF_LASTDATANOTIFICATION),
1781 13, 13);
1782 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1783 if(mimefilter_test)
1784 CHECK_CALLED(MimeFilter_ReportData);
1785 else
1786 CHECK_CALLED(ReportData);
1787
1788 if(tested_protocol == ITS_TEST) {
1789 SET_EXPECT(ReportData);
1790 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
1791 ok(hres == S_OK, "ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres);
1792 CHECK_CALLED(ReportData);
1793 }
1794
1795 if(tested_protocol == BIND_TEST) {
1796 hres = IInternetProtocol_Terminate(binding_protocol, 0);
1797 ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
1798 }
1799
1800 if(mimefilter_test)
1801 SET_EXPECT(MimeFilter_ReportResult);
1802 else
1803 SET_EXPECT(ReportResult);
1804 hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
1805 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1806 if(mimefilter_test)
1807 CHECK_CALLED(MimeFilter_ReportResult);
1808 else
1809 CHECK_CALLED(ReportResult);
1810 }
1811
1812 static HRESULT WINAPI ProtocolEmul_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
1813 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1814 DWORD grfPI, HANDLE_PTR dwReserved)
1815 {
1816 CHECK_EXPECT(Start);
1817
1818 ok(!dwReserved, "dwReserved = %lx\n", dwReserved);
1819 protocol_start(pOIProtSink, pOIBindInfo, grfPI);
1820 return S_OK;
1821 }
1822
1823 static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocolEx *iface,
1824 PROTOCOLDATA *pProtocolData)
1825 {
1826 DWORD bscf = 0, pr;
1827 HRESULT hres;
1828
1829 CHECK_EXPECT(Continue);
1830
1831 ok(pProtocolData != NULL, "pProtocolData == NULL\n");
1832 if(!pProtocolData || tested_protocol == BIND_TEST)
1833 return S_OK;
1834 if(binding_test) {
1835 ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
1836 ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
1837 pProtocolData->grfFlags, protocoldata.grfFlags );
1838 ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
1839 pProtocolData->dwState, protocoldata.dwState );
1840 ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
1841 pProtocolData->pData, protocoldata.pData );
1842 ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
1843 pProtocolData->cbData, protocoldata.cbData );
1844 }
1845
1846 switch(prot_state) {
1847 case 1: {
1848 IServiceProvider *service_provider;
1849 IHttpNegotiate *http_negotiate;
1850 static const WCHAR header[] = {'?',0};
1851
1852 hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
1853 (void**)&service_provider);
1854 ok(hres == S_OK, "Could not get IServiceProvicder\n");
1855
1856 SET_EXPECT(QueryService_HttpNegotiate);
1857 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1858 &IID_IHttpNegotiate, (void**)&http_negotiate);
1859 IServiceProvider_Release(service_provider);
1860 CHECK_CALLED(QueryService_HttpNegotiate);
1861 ok(hres == S_OK, "Could not get IHttpNegotiate\n");
1862
1863 SET_EXPECT(OnResponse);
1864 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
1865 IHttpNegotiate_Release(http_negotiate);
1866 CHECK_CALLED(OnResponse);
1867 IHttpNegotiate_Release(http_negotiate);
1868 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
1869
1870 if(mimefilter_test) {
1871 SET_EXPECT(MimeFilter_CreateInstance);
1872 SET_EXPECT(MimeFilter_Start);
1873 SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1874 }else if(!(pi & PI_MIMEVERIFICATION)) {
1875 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1876 }
1877 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1878 BINDSTATUS_MIMETYPEAVAILABLE, mimefilter_test ? pjpegW : text_htmlW);
1879 if(mimefilter_test) {
1880 CHECK_CALLED(MimeFilter_CreateInstance);
1881 CHECK_CALLED(MimeFilter_Start);
1882 CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1883 }else if(!(pi & PI_MIMEVERIFICATION)) {
1884 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1885 }
1886 ok(hres == S_OK,
1887 "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
1888
1889 bscf |= BSCF_FIRSTDATANOTIFICATION;
1890 break;
1891 }
1892 case 2:
1893 case 3:
1894 bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
1895 break;
1896 }
1897
1898 pr = prot_read;
1899 if(mimefilter_test)
1900 SET_EXPECT(MimeFilter_ReportData);
1901 if((!mimefilter_test || no_mime) && (pi & PI_MIMEVERIFICATION)) {
1902 if(pr < 200)
1903 SET_EXPECT(Read); /* checked in ReportData for short_read */
1904 if(pr == 200) {
1905 if(!mimefilter_test)
1906 SET_EXPECT(Read); /* checked in BINDSTATUS_MIMETYPEAVAILABLE or ReportData */
1907 SET_EXPECT(GetBindInfo);
1908 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1909 }
1910 if(pr >= 200)
1911 SET_EXPECT(ReportData);
1912 }else {
1913 SET_EXPECT(ReportData);
1914 }
1915
1916 hres = IInternetProtocolSink_ReportData(binding_sink, bscf, pr, 400);
1917 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1918
1919 if(mimefilter_test) {
1920 SET_EXPECT(MimeFilter_ReportData);
1921 }else if(pi & PI_MIMEVERIFICATION) {
1922 if(!short_read && pr < 200)
1923 CHECK_CALLED(Read);
1924 if(pr == 200) {
1925 CLEAR_CALLED(GetBindInfo); /* IE9 */
1926 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1927 }
1928 }else {
1929 CHECK_CALLED(ReportData);
1930 }
1931
1932 if(prot_state == 3)
1933 prot_state = 4;
1934
1935 return S_OK;
1936 }
1937
1938 static HRESULT WINAPI ProtocolEmul_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
1939 {
1940 CHECK_EXPECT(Terminate);
1941 ok(!dwOptions, "dwOptions=%d\n", dwOptions);
1942 return S_OK;
1943 }
1944
1945 static HRESULT WINAPI ProtocolEmul_Read(IInternetProtocolEx *iface, void *pv,
1946 ULONG cb, ULONG *pcbRead)
1947 {
1948 if(read_report_data)
1949 CHECK_EXPECT2(Read2);
1950
1951 if(mimefilter_test || short_read) {
1952 if(!read_report_data)
1953 CHECK_EXPECT2(Read);
1954 }else if((pi & PI_MIMEVERIFICATION)) {
1955 if(!read_report_data)
1956 CHECK_EXPECT2(Read);
1957
1958 if(prot_read < 300) {
1959 ok(pv != expect_pv, "pv == expect_pv\n");
1960 if(prot_read < 300)
1961 ok(cb == 2048-prot_read, "cb=%d\n", cb);
1962 else
1963 ok(cb == 700, "cb=%d\n", cb);
1964 }else {
1965 ok(expect_pv <= pv && (BYTE*)pv < (BYTE*)expect_pv + cb, "pv != expect_pv\n");
1966 }
1967 }else {
1968 if(!read_report_data)
1969 CHECK_EXPECT(Read);
1970
1971 ok(pv == expect_pv, "pv != expect_pv\n");
1972 ok(cb == 1000, "cb=%d\n", cb);
1973 ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
1974 }
1975 ok(pcbRead != NULL, "pcbRead == NULL\n");
1976
1977 if(prot_state == 3 || (short_read && prot_state != 4)) {
1978 HRESULT hres;
1979
1980 prot_state = 4;
1981 if(short_read) {
1982 SET_EXPECT(Read2); /* checked in BINDSTATUS_MIMETYPEAVAILABLE */
1983 SET_EXPECT(GetBindInfo);
1984 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1985 }
1986 if(mimefilter_test)
1987 SET_EXPECT(MimeFilter_ReportData);
1988 else if(direct_read)
1989 SET_EXPECT(ReportData2);
1990 read_report_data++;
1991 hres = IInternetProtocolSink_ReportData(binding_sink,
1992 BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION, 0, 0);
1993 read_report_data--;
1994 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1995 if(short_read) {
1996 CLEAR_CALLED(GetBindInfo); /* IE9 */
1997 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1998 }
1999 if(mimefilter_test)
2000 CHECK_CALLED(MimeFilter_ReportData);
2001 else if(direct_read)
2002 CHECK_CALLED(ReportData2);
2003
2004 if(mimefilter_test)
2005 SET_EXPECT(MimeFilter_ReportResult);
2006 else
2007 SET_EXPECT(ReportResult);
2008 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
2009 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
2010 if(mimefilter_test)
2011 CHECK_CALLED(MimeFilter_ReportResult);
2012 else
2013 CHECK_CALLED(ReportResult);
2014
2015 if(cb > 100)
2016 cb = 100;
2017 memset(pv, 'x', cb);
2018 if(cb>6)
2019 memcpy(pv, "gif87a", 6);
2020 prot_read += *pcbRead = cb;
2021 return S_OK;
2022 }
2023
2024 if(prot_state == 4) {
2025 *pcbRead = 0;
2026 return S_FALSE;
2027 }
2028
2029 if((async_read_pending = !async_read_pending)) {
2030 *pcbRead = 0;
2031 return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
2032 }
2033
2034 if(cb > 100)
2035 cb = 100;
2036 memset(pv, 'x', cb);
2037 if(cb>6)
2038 memcpy(pv, "gif87a", 6);
2039 prot_read += *pcbRead = cb;
2040 return S_OK;
2041 }
2042
2043 static HRESULT WINAPI ProtocolEmul_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2044 {
2045 CHECK_EXPECT(LockRequest);
2046 ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
2047 return S_OK;
2048 }
2049
2050 static HRESULT WINAPI ProtocolEmul_UnlockRequest(IInternetProtocolEx *iface)
2051 {
2052 CHECK_EXPECT(UnlockRequest);
2053 return S_OK;
2054 }
2055
2056 static HRESULT WINAPI ProtocolEmul_StartEx(IInternetProtocolEx *iface, IUri *pUri,
2057 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2058 DWORD grfPI, HANDLE *dwReserved)
2059 {
2060 CHECK_EXPECT(StartEx);
2061 ok(!dwReserved, "dwReserved = %p\n", dwReserved);
2062 protocol_start(pOIProtSink, pOIBindInfo, grfPI);
2063 return S_OK;
2064 }
2065
2066 static const IInternetProtocolExVtbl ProtocolVtbl = {
2067 ProtocolEmul_QueryInterface,
2068 Protocol_AddRef,
2069 Protocol_Release,
2070 ProtocolEmul_Start,
2071 ProtocolEmul_Continue,
2072 Protocol_Abort,
2073 ProtocolEmul_Terminate,
2074 Protocol_Suspend,
2075 Protocol_Resume,
2076 ProtocolEmul_Read,
2077 Protocol_Seek,
2078 ProtocolEmul_LockRequest,
2079 ProtocolEmul_UnlockRequest,
2080 ProtocolEmul_StartEx
2081 };
2082
2083 static IInternetProtocolEx Protocol = { &ProtocolVtbl };
2084
2085 static HRESULT WINAPI MimeProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
2086 {
2087 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
2088 *ppv = iface;
2089 return S_OK;
2090 }
2091
2092 if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
2093 *ppv = &mime_protocol_sink;
2094 return S_OK;
2095 }
2096
2097 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
2098 *ppv = NULL;
2099 return E_NOINTERFACE;
2100 }
2101
2102 static HRESULT WINAPI MimeProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
2103 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2104 DWORD grfPI, HANDLE_PTR dwReserved)
2105 {
2106 PROTOCOLFILTERDATA *data;
2107 LPOLESTR url_str = NULL;
2108 DWORD fetched = 0;
2109 BINDINFO bindinfo;
2110 DWORD cbindf = 0;
2111 HRESULT hres;
2112
2113 CHECK_EXPECT(MimeFilter_Start);
2114
2115 ok(!lstrcmpW(szUrl, pjpegW), "wrong url %s\n", wine_dbgstr_w(szUrl));
2116 ok(grfPI == (PI_FILTER_MODE|PI_FORCE_ASYNC), "grfPI=%x, expected PI_FILTER_MODE|PI_FORCE_ASYNC\n", grfPI);
2117 ok(dwReserved, "dwReserved == 0\n");
2118 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
2119 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
2120
2121 if(binding_test) {
2122 ok(pOIProtSink != binding_sink, "pOIProtSink == protocol_sink\n");
2123 ok(pOIBindInfo == prot_bind_info, "pOIBindInfo != bind_info\n");
2124 }else {
2125 ok(pOIProtSink == &protocol_sink, "pOIProtSink != protocol_sink\n");
2126 ok(pOIBindInfo == &bind_info, "pOIBindInfo != bind_info\n");
2127 }
2128
2129 data = (void*)dwReserved;
2130 ok(data->cbSize == sizeof(*data), "data->cbSize = %d\n", data->cbSize);
2131 ok(!data->pProtocolSink, "data->pProtocolSink != NULL\n");
2132 ok(data->pProtocol != NULL, "data->pProtocol == NULL\n");
2133 ok(!data->pUnk, "data->pUnk != NULL\n");
2134 ok(!data->dwFilterFlags, "data->dwProtocolFlags = %x\n", data->dwFilterFlags);
2135 if(binding_test) {
2136 IInternetProtocolSink *prot_sink;
2137
2138 IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocolSink, (void**)&prot_sink);
2139 ok(prot_sink == pOIProtSink, "QI(data->pProtocol, IID_IInternetProtocolSink) != pOIProtSink\n");
2140 IInternetProtocolSink_Release(prot_sink);
2141
2142 ok(data->pProtocol != binding_protocol, "data->pProtocol == binding_protocol\n");
2143
2144 filtered_protocol = data->pProtocol;
2145 IInternetProtocol_AddRef(filtered_protocol);
2146 }else {
2147 IInternetProtocol *prot;
2148
2149 IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocol, (void**)&prot);
2150 ok(prot == async_protocol, "QI(data->pProtocol, IID_IInternetProtocol) != async_protocol\n");
2151 IInternetProtocol_Release(prot);
2152
2153 ok(data->pProtocol != async_protocol, "data->pProtocol == async_protocol\n");
2154 }
2155
2156 filtered_sink = pOIProtSink;
2157
2158 SET_EXPECT(ReportProgress_DECODING);
2159 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DECODING, pjpegW);
2160 ok(hres == S_OK, "ReportProgress(BINDSTATUS_DECODING) failed: %08x\n", hres);
2161 CHECK_CALLED(ReportProgress_DECODING);
2162
2163 SET_EXPECT(GetBindInfo);
2164 memset(&bindinfo, 0, sizeof(bindinfo));
2165 bindinfo.cbSize = sizeof(bindinfo);
2166 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
2167 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
2168 ok(cbindf == (bindf|BINDF_FROMURLMON), "cbindf = %x, expected %x\n", cbindf, bindf);
2169 CHECK_CALLED(GetBindInfo);
2170
2171 SET_EXPECT(GetBindString_URL);
2172 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_URL, &url_str, 1, &fetched);
2173 ok(hres == S_OK, "GetBindString(BINDSTRING_URL) failed: %08x\n", hres);
2174 ok(fetched == 1, "fetched = %d\n", fetched);
2175 ok(!lstrcmpW(url_str, binding_urls[tested_protocol]), "wrong url_str %s\n", wine_dbgstr_w(url_str));
2176 CoTaskMemFree(url_str);
2177 CHECK_CALLED(GetBindString_URL);
2178
2179 return S_OK;
2180 }
2181
2182 static HRESULT WINAPI Protocol_Continue(IInternetProtocolEx *iface,
2183 PROTOCOLDATA *pProtocolData)
2184 {
2185 CHECK_EXPECT(MimeFilter_Continue);
2186 return E_NOTIMPL;
2187 }
2188
2189 static HRESULT WINAPI MimeProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2190 {
2191 HRESULT hres;
2192
2193 CHECK_EXPECT(MimeFilter_Terminate);
2194
2195 ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2196
2197 SET_EXPECT(Terminate);
2198 hres = IInternetProtocol_Terminate(filtered_protocol, dwOptions);
2199 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2200 CHECK_CALLED(Terminate);
2201
2202 return S_OK;
2203 }
2204
2205 static HRESULT WINAPI MimeProtocol_Read(IInternetProtocolEx *iface, void *pv,
2206 ULONG cb, ULONG *pcbRead)
2207 {
2208 BYTE buf[2096];
2209 DWORD read = 0;
2210 HRESULT hres;
2211
2212 CHECK_EXPECT(MimeFilter_Read);
2213
2214 ok(pv != NULL, "pv == NULL\n");
2215 ok(cb != 0, "cb == 0\n");
2216 ok(pcbRead != NULL, "pcbRead == NULL\n");
2217
2218 if(read_report_data)
2219 SET_EXPECT(Read2);
2220 else
2221 SET_EXPECT(Read);
2222 hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
2223 ok(hres == S_OK || hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
2224 if(read_report_data)
2225 CHECK_CALLED(Read2);
2226 else
2227 CHECK_CALLED(Read);
2228
2229 if(pcbRead) {
2230 ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
2231 *pcbRead = read;
2232 }
2233
2234 memset(pv, 'x', read);
2235 return hres;
2236 }
2237
2238 static HRESULT WINAPI MimeProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2239 {
2240 HRESULT hres;
2241
2242 CHECK_EXPECT(MimeFilter_LockRequest);
2243
2244 ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2245
2246 SET_EXPECT(LockRequest);
2247 hres = IInternetProtocol_LockRequest(filtered_protocol, dwOptions);
2248 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2249 CHECK_CALLED(LockRequest);
2250
2251 return S_OK;
2252 }
2253
2254 static HRESULT WINAPI MimeProtocol_UnlockRequest(IInternetProtocolEx *iface)
2255 {
2256 HRESULT hres;
2257
2258 CHECK_EXPECT(MimeFilter_UnlockRequest);
2259
2260 SET_EXPECT(UnlockRequest);
2261 hres = IInternetProtocol_UnlockRequest(filtered_protocol);
2262 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2263 CHECK_CALLED(UnlockRequest);
2264
2265 return S_OK;
2266 }
2267
2268 static const IInternetProtocolExVtbl MimeProtocolVtbl = {
2269 MimeProtocol_QueryInterface,
2270 Protocol_AddRef,
2271 Protocol_Release,
2272 MimeProtocol_Start,
2273 Protocol_Continue,
2274 Protocol_Abort,
2275 MimeProtocol_Terminate,
2276 Protocol_Suspend,
2277 Protocol_Resume,
2278 MimeProtocol_Read,
2279 Protocol_Seek,
2280 MimeProtocol_LockRequest,
2281 MimeProtocol_UnlockRequest
2282 };
2283
2284 static IInternetProtocolEx MimeProtocol = { &MimeProtocolVtbl };
2285
2286 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2287 {
2288 ok(0, "unexpected call\n");
2289 return E_NOINTERFACE;
2290 }
2291
2292 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
2293 {
2294 return 2;
2295 }
2296
2297 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
2298 {
2299 return 1;
2300 }
2301
2302 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
2303 REFIID riid, void **ppv)
2304 {
2305 CHECK_EXPECT(CreateInstance);
2306
2307 ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
2308 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2309 ok(ppv != NULL, "ppv == NULL\n");
2310
2311 *ppv = &Protocol;
2312 return S_OK;
2313 }
2314
2315 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
2316 {
2317 ok(0, "unexpected call\n");
2318 return S_OK;
2319 }
2320
2321 static const IClassFactoryVtbl ClassFactoryVtbl = {
2322 ClassFactory_QueryInterface,
2323 ClassFactory_AddRef,
2324 ClassFactory_Release,
2325 ClassFactory_CreateInstance,
2326 ClassFactory_LockServer
2327 };
2328
2329 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
2330
2331 static HRESULT WINAPI MimeFilter_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
2332 {
2333 CHECK_EXPECT(MimeFilter_CreateInstance);
2334
2335 ok(!outer, "outer = %p\n", outer);
2336 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2337
2338 *ppv = &MimeProtocol;
2339 return S_OK;
2340 }
2341
2342 static const IClassFactoryVtbl MimeFilterCFVtbl = {
2343 ClassFactory_QueryInterface,
2344 ClassFactory_AddRef,
2345 ClassFactory_Release,
2346 MimeFilter_CreateInstance,
2347 ClassFactory_LockServer
2348 };
2349
2350 static IClassFactory mimefilter_cf = { &MimeFilterCFVtbl };
2351
2352 #define TEST_BINDING 0x0001
2353 #define TEST_FILTER 0x0002
2354 #define TEST_FIRST_HTTP 0x0004
2355 #define TEST_DIRECT_READ 0x0008
2356 #define TEST_POST 0x0010
2357 #define TEST_EMULATEPROT 0x0020
2358 #define TEST_SHORT_READ 0x0040
2359 #define TEST_REDIRECT 0x0080
2360 #define TEST_ABORT 0x0100
2361 #define TEST_ASYNCREQ 0x0200
2362 #define TEST_USEIURI 0x0400
2363 #define TEST_IMPLPROTEX 0x0800
2364 #define TEST_EMPTY 0x1000
2365 #define TEST_NOMIME 0x2000
2366 #define TEST_FROMCACHE 0x4000
2367
2368 static void register_filter(BOOL do_register)
2369 {
2370 IInternetSession *session;
2371 HRESULT hres;
2372
2373 hres = pCoInternetGetSession(0, &session, 0);
2374 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2375
2376 if(do_register) {
2377 hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, pjpegW);
2378 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2379 hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, gifW);
2380 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2381 }else {
2382 hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, pjpegW);
2383 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2384 hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, gifW);
2385 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2386 }
2387
2388 IInternetSession_Release(session);
2389 }
2390
2391 static void init_test(int prot, DWORD flags)
2392 {
2393 tested_protocol = prot;
2394 binding_test = (flags & TEST_BINDING) != 0;
2395 first_data_notif = TRUE;
2396 prot_read = 0;
2397 prot_state = 0;
2398 async_read_pending = TRUE;
2399 mimefilter_test = (flags & TEST_FILTER) != 0;
2400 no_mime = (flags & TEST_NOMIME) != 0;
2401 filter_state = 0;
2402 post_stream_read = 0;
2403 ResetEvent(event_complete);
2404 ResetEvent(event_complete2);
2405 ResetEvent(event_continue);
2406 ResetEvent(event_continue_done);
2407 async_protocol = binding_protocol = filtered_protocol = NULL;
2408 filtered_sink = NULL;
2409 http_is_first = (flags & TEST_FIRST_HTTP) != 0;
2410 first_data_notif = TRUE;
2411 state = STATE_CONNECTING;
2412 test_async_req = (flags & TEST_ASYNCREQ) != 0;
2413 direct_read = (flags & TEST_DIRECT_READ) != 0;
2414 emulate_prot = (flags & TEST_EMULATEPROT) != 0;
2415 wait_for_switch = TRUE;
2416 short_read = (flags & TEST_SHORT_READ) != 0;
2417 http_post_test = TYMED_NULL;
2418 test_redirect = (flags & TEST_REDIRECT) != 0;
2419 test_abort = (flags & TEST_ABORT) != 0;
2420 impl_protex = (flags & TEST_IMPLPROTEX) != 0;
2421 empty_file = (flags & TEST_EMPTY) != 0;
2422 bind_from_cache = (flags & TEST_FROMCACHE) != 0;
2423 file_with_hash = FALSE;
2424
2425 register_filter(mimefilter_test);
2426 }
2427
2428 static void test_priority(IInternetProtocol *protocol)
2429 {
2430 IInternetPriority *priority;
2431 LONG pr;
2432 HRESULT hres;
2433
2434 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
2435 (void**)&priority);
2436 ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
2437 if(FAILED(hres))
2438 return;
2439
2440 hres = IInternetPriority_GetPriority(priority, &pr);
2441 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2442 ok(pr == 0, "pr=%d, expected 0\n", pr);
2443
2444 hres = IInternetPriority_SetPriority(priority, 1);
2445 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2446
2447 hres = IInternetPriority_GetPriority(priority, &pr);
2448 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2449 ok(pr == 1, "pr=%d, expected 1\n", pr);
2450
2451 IInternetPriority_Release(priority);
2452 }
2453
2454 static void test_early_abort(const CLSID *clsid)
2455 {
2456 IInternetProtocol *protocol;
2457 HRESULT hres;
2458
2459 hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2460 &IID_IInternetProtocol, (void**)&protocol);
2461 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2462
2463 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
2464 ok(hres == S_OK, "Abort failed: %08x\n", hres);
2465
2466 hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
2467 ok(hres == S_OK, "Abort failed: %08x\n", hres);
2468
2469 IInternetProtocol_Release(protocol);
2470 }
2471
2472 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url,
2473 IInternetProtocolEx *protocolex, IUri *uri, BOOL is_first)
2474 {
2475 HRESULT hres;
2476
2477 SET_EXPECT(GetBindInfo);
2478 if(!(bindf & BINDF_FROMURLMON))
2479 SET_EXPECT(ReportProgress_DIRECTBIND);
2480 if(is_first) {
2481 SET_EXPECT(ReportProgress_SENDINGREQUEST);
2482 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
2483 if(bindf & BINDF_FROMURLMON)
2484 SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2485 else
2486 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2487 }
2488 SET_EXPECT(ReportData);
2489 if(is_first)
2490 SET_EXPECT(ReportResult);
2491
2492 expect_hrResult = S_OK;
2493
2494 if(protocolex) {
2495 hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
2496 ok(hres == S_OK, "StartEx failed: %08x\n", hres);
2497 }else {
2498 hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
2499 if(hres == INET_E_RESOURCE_NOT_FOUND) {
2500 win_skip("Start failed\n");
2501 return FALSE;
2502 }
2503 ok(hres == S_OK, "Start failed: %08x\n", hres);
2504 }
2505
2506 CHECK_CALLED(GetBindInfo);
2507 if(!(bindf & BINDF_FROMURLMON))
2508 CLEAR_CALLED(ReportProgress_DIRECTBIND); /* Not called by IE10 */
2509 if(is_first) {
2510 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2511 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
2512 if(bindf & BINDF_FROMURLMON)
2513 CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2514 else
2515 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2516 }
2517 CHECK_CALLED(ReportData);
2518 if(is_first)
2519 CHECK_CALLED(ReportResult);
2520
2521 return TRUE;
2522 }
2523
2524 static void test_file_protocol_url(LPCWSTR url)
2525 {
2526 IInternetProtocolInfo *protocol_info;
2527 IUnknown *unk;
2528 IClassFactory *factory;
2529 IInternetProtocol *protocol;
2530 BYTE buf[512];
2531 ULONG cb;
2532 HRESULT hres;
2533
2534 hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
2535 &IID_IUnknown, (void**)&unk);
2536 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2537 if(FAILED(hres))
2538 return;
2539
2540 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2541 ok(hres == E_NOINTERFACE,
2542 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
2543
2544 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2545 ok(hres == S_OK, "Could not get IClassFactory interface\n");
2546 IUnknown_Release(unk);
2547 if(FAILED(hres))
2548 return;
2549
2550 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2551 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2552
2553 if(SUCCEEDED(hres)) {
2554 if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2555 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2556 ok(hres == S_OK, "Read failed: %08x\n", hres);
2557 ok(cb == 2, "cb=%u expected 2\n", cb);
2558 buf[2] = 0;
2559 ok(!memcmp(buf, file_with_hash ? "XX" : "<H", 2), "Unexpected data %s\n", buf);
2560 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2561 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2562 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2563 ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
2564 ok(cb == 0, "cb=%u expected 0\n", cb);
2565 hres = IInternetProtocol_UnlockRequest(protocol);
2566 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2567 }
2568
2569 if(file_protocol_start(protocol, url, NULL, NULL, FALSE)) {
2570 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2571 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2572 hres = IInternetProtocol_LockRequest(protocol, 0);
2573 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2574 hres = IInternetProtocol_UnlockRequest(protocol);
2575 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2576 }
2577
2578 IInternetProtocol_Release(protocol);
2579 }
2580
2581 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2582 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2583 if(SUCCEEDED(hres)) {
2584 if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2585 hres = IInternetProtocol_LockRequest(protocol, 0);
2586 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2587 hres = IInternetProtocol_Terminate(protocol, 0);
2588 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2589 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2590 ok(hres == S_OK, "Read failed: %08x\n\n", hres);
2591 hres = IInternetProtocol_UnlockRequest(protocol);
2592 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2593 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2594 todo_wine_if(file_with_hash) /* FIXME: An effect of UnlockRequest call? */
2595 ok(hres == S_OK, "Read failed: %08x\n", hres);
2596 hres = IInternetProtocol_Terminate(protocol, 0);
2597 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2598 }
2599
2600 IInternetProtocol_Release(protocol);
2601 }
2602
2603 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2604 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2605 if(SUCCEEDED(hres)) {
2606 if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2607 hres = IInternetProtocol_Terminate(protocol, 0);
2608 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2609 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2610 ok(hres == S_OK, "Read failed: %08x\n", hres);
2611 ok(cb == 2, "cb=%u expected 2\n", cb);
2612 }
2613
2614 IInternetProtocol_Release(protocol);
2615 }
2616
2617 if(pCreateUri) {
2618 IInternetProtocolEx *protocolex;
2619 IUri *uri;
2620
2621 hres = pCreateUri(url, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
2622 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2623
2624 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2625 ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2626
2627 if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2628 hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2629 ok(hres == S_OK, "Read failed: %08x\n", hres);
2630 hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2631 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2632 hres = IInternetProtocolEx_UnlockRequest(protocolex);
2633 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2634 }
2635
2636 IUri_Release(uri);
2637 IInternetProtocolEx_Release(protocolex);
2638
2639 hres = pCreateUri(url, 0, 0, &uri);
2640 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2641
2642 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2643 ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2644
2645 if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2646 hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2647 ok(hres == S_OK, "Read failed: %08x\n", hres);
2648 hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2649 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2650 hres = IInternetProtocolEx_UnlockRequest(protocolex);
2651 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2652 }
2653
2654 IUri_Release(uri);
2655 IInternetProtocolEx_Release(protocolex);
2656 }else {
2657 win_skip("Skipping file protocol StartEx tests\n");
2658 }
2659
2660 IClassFactory_Release(factory);
2661 }
2662
2663 static void test_file_protocol_fail(void)
2664 {
2665 IInternetProtocol *protocol;
2666 HRESULT hres;
2667
2668 static const WCHAR index_url2[] =
2669 {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
2670
2671 hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2672 &IID_IInternetProtocol, (void**)&protocol);
2673 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2674 if(FAILED(hres))
2675 return;
2676
2677 SET_EXPECT(GetBindInfo);
2678 expect_hrResult = MK_E_SYNTAX;
2679 hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
2680 ok(hres == MK_E_SYNTAX ||
2681 hres == E_INVALIDARG,
2682 "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres);
2683 CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2684
2685 SET_EXPECT(GetBindInfo);
2686 if(!(bindf & BINDF_FROMURLMON))
2687 SET_EXPECT(ReportProgress_DIRECTBIND);
2688 SET_EXPECT(ReportProgress_SENDINGREQUEST);
2689 SET_EXPECT(ReportResult);
2690 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2691 hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
2692 ok(hres == INET_E_RESOURCE_NOT_FOUND,
2693 "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
2694 CHECK_CALLED(GetBindInfo);
2695 if(!(bindf & BINDF_FROMURLMON))
2696 CHECK_CALLED(ReportProgress_DIRECTBIND);
2697 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2698 CHECK_CALLED(ReportResult);
2699
2700 IInternetProtocol_Release(protocol);
2701
2702 hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2703 &IID_IInternetProtocol, (void**)&protocol);
2704 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2705 if(FAILED(hres))
2706 return;
2707
2708 SET_EXPECT(GetBindInfo);
2709 if(!(bindf & BINDF_FROMURLMON))
2710 SET_EXPECT(ReportProgress_DIRECTBIND);
2711 SET_EXPECT(ReportProgress_SENDINGREQUEST);
2712 SET_EXPECT(ReportResult);
2713 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
2714
2715 hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
2716 ok(hres == INET_E_RESOURCE_NOT_FOUND,
2717 "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
2718 CHECK_CALLED(GetBindInfo);
2719 if(!(bindf & BINDF_FROMURLMON))
2720 CHECK_CALLED(ReportProgress_DIRECTBIND);
2721 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2722 CHECK_CALLED(ReportResult);
2723
2724 SET_EXPECT(GetBindInfo);
2725 hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
2726 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2727 CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2728
2729 SET_EXPECT(GetBindInfo);
2730 hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0);
2731 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
2732 CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
2733
2734 IInternetProtocol_Release(protocol);
2735 }
2736
2737 static void test_file_protocol(void) {
2738 WCHAR buf[INTERNET_MAX_URL_LENGTH], file_name_buf[MAX_PATH];
2739 DWORD size;
2740 ULONG len;
2741 HANDLE file;
2742
2743 static const WCHAR wszFile[] = {'f','i','l','e',':',0};
2744 static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
2745 static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
2746 static const WCHAR wszFile4[] = {'f','i','l','e',':','\\','\\',0};
2747 static const char html_doc[] = "<HTML></HTML>";
2748 static const WCHAR fragmentW[] = {'#','f','r','a','g',0};
2749
2750 trace("Testing file protocol...\n");
2751 init_test(FILE_TEST, 0);
2752
2753 SetLastError(0xdeadbeef);
2754 file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2755 FILE_ATTRIBUTE_NORMAL, NULL);
2756 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
2757 if(file == INVALID_HANDLE_VALUE)
2758 return;
2759 WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
2760 CloseHandle(file);
2761
2762 file_name = wszIndexHtml;
2763 bindf = 0;
2764 test_file_protocol_url(index_url);
2765 bindf = BINDF_FROMURLMON;
2766 test_file_protocol_url(index_url);
2767 bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
2768 test_file_protocol_url(index_url);
2769
2770 memcpy(buf, wszFile, sizeof(wszFile));
2771 len = sizeof(wszFile)/sizeof(WCHAR)-1;
2772 len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2773 buf[len++] = '\\';
2774 memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2775
2776 file_name = buf + sizeof(wszFile)/sizeof(WCHAR)-1;
2777 bindf = 0;
2778 test_file_protocol_url(buf);
2779 bindf = BINDF_FROMURLMON;
2780 test_file_protocol_url(buf);
2781
2782 memcpy(buf, wszFile2, sizeof(wszFile2));
2783 len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
2784 file_name_buf[len++] = '\\';
2785 memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2786 lstrcpyW(buf+sizeof(wszFile2)/sizeof(WCHAR)-1, file_name_buf);
2787 file_name = file_name_buf;
2788 bindf = 0;
2789 test_file_protocol_url(buf);
2790 bindf = BINDF_FROMURLMON;
2791 test_file_protocol_url(buf);
2792
2793 buf[sizeof(wszFile2)/sizeof(WCHAR)] = '|';
2794 test_file_protocol_url(buf);
2795
2796 memcpy(buf, wszFile3, sizeof(wszFile3));
2797 len = sizeof(wszFile3)/sizeof(WCHAR)-1;
2798 len += GetCurrentDirectoryW(sizeof(buf)/sizeof(WCHAR)-len, buf+len);
2799 buf[len++] = '\\';
2800 memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2801
2802 file_name = buf + sizeof(wszFile3)/sizeof(WCHAR)-1;
2803 bindf = 0;
2804 test_file_protocol_url(buf);
2805 bindf = BINDF_FROMURLMON;
2806 test_file_protocol_url(buf);
2807
2808 memcpy(buf, wszFile4, sizeof(wszFile4));
2809 len = GetCurrentDirectoryW(sizeof(file_name_buf)/sizeof(WCHAR), file_name_buf);
2810 file_name_buf[len++] = '\\';
2811 memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
2812 lstrcpyW(buf+sizeof(wszFile4)/sizeof(WCHAR)-1, file_name_buf);
2813 file_name = file_name_buf;
2814 bindf = 0;
2815 test_file_protocol_url(buf);
2816 bindf = BINDF_FROMURLMON;
2817 test_file_protocol_url(buf);
2818
2819 buf[sizeof(wszFile4)/sizeof(WCHAR)] = '|';
2820 test_file_protocol_url(buf);
2821
2822 /* Fragment part of URL is skipped if the file doesn't exist. */
2823 lstrcatW(buf, fragmentW);
2824 test_file_protocol_url(buf);
2825
2826 /* Fragment part is considered a part of the file name, if the file exsists. */
2827 len = lstrlenW(file_name_buf);
2828 lstrcpyW(file_name_buf+len, fragmentW);
2829 file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
2830 FILE_ATTRIBUTE_NORMAL, NULL);
2831 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
2832 WriteFile(file, "XXX", 3, &size, NULL);
2833 CloseHandle(file);
2834 file_name_buf[len] = 0;
2835
2836 file_with_hash = TRUE;
2837 test_file_protocol_url(buf);
2838
2839 DeleteFileW(wszIndexHtml);
2840 DeleteFileW(file_name_buf);
2841
2842 bindf = 0;
2843 test_file_protocol_fail();
2844 bindf = BINDF_FROMURLMON;
2845 test_file_protocol_fail();
2846 }
2847
2848 static void create_cache_entry(const WCHAR *urlw)
2849 {
2850 FILETIME now, tomorrow, yesterday;
2851 char file_path[MAX_PATH];
2852 BYTE content[1000];
2853 ULARGE_INTEGER li;
2854 const char *url;
2855 HANDLE file;
2856 DWORD size;
2857 unsigned i;
2858 BOOL res;
2859
2860 BYTE cache_headers[] = "HTTP/1.1 200 OK\r\n\r\n";
2861
2862 trace("Testing cache read...\n");
2863
2864 url = w2a(urlw);
2865
2866 for(i = 0; i < sizeof(content); i++)
2867 content[i] = '0' + (i%10);
2868
2869 GetSystemTimeAsFileTime(&now);
2870 li.u.HighPart = now.dwHighDateTime;
2871 li.u.LowPart = now.dwLowDateTime;
2872 li.QuadPart += (LONGLONG)10000000 * 3600 * 24;
2873 tomorrow.dwHighDateTime = li.u.HighPart;
2874 tomorrow.dwLowDateTime = li.u.LowPart;
2875 li.QuadPart -= (LONGLONG)10000000 * 3600 * 24 * 2;
2876 yesterday.dwHighDateTime = li.u.HighPart;
2877 yesterday.dwLowDateTime = li.u.LowPart;
2878
2879 res = CreateUrlCacheEntryA(url, sizeof(content), "", file_path, 0);
2880 ok(res, "CreateUrlCacheEntryA failed: %u\n", GetLastError());
2881
2882 file = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2883 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
2884
2885 WriteFile(file, content, sizeof(content), &size, NULL);
2886 CloseHandle(file);
2887
2888 res = CommitUrlCacheEntryA(url, file_path, tomorrow, yesterday, NORMAL_CACHE_ENTRY,
2889 cache_headers, sizeof(cache_headers)-1, "", 0);
2890 ok(res, "CommitUrlCacheEntryA failed: %u\n", GetLastError());
2891 }
2892
2893 static BOOL http_protocol_start(LPCWSTR url, BOOL use_iuri)
2894 {
2895 static BOOL got_user_agent = FALSE;
2896 IUri *uri = NULL;
2897 HRESULT hres;
2898
2899 if(use_iuri && pCreateUri) {
2900 hres = pCreateUri(url, 0, 0, &uri);
2901 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2902 }
2903
2904 SET_EXPECT(GetBindInfo);
2905 if (!(bindf & BINDF_FROMURLMON))
2906 SET_EXPECT(ReportProgress_DIRECTBIND);
2907 if(!got_user_agent)
2908 SET_EXPECT(GetBindString_USER_AGENT);
2909 SET_EXPECT(GetBindString_ROOTDOC_URL);
2910 SET_EXPECT(GetBindString_ACCEPT_MIMES);
2911 SET_EXPECT(QueryService_HttpNegotiate);
2912 SET_EXPECT(BeginningTransaction);
2913 SET_EXPECT(GetRootSecurityId);
2914 if(http_post_test) {
2915 SET_EXPECT(GetBindString_POST_COOKIE);
2916 if(http_post_test == TYMED_ISTREAM)
2917 SET_EXPECT(Stream_Seek);
2918 }
2919 if(bind_from_cache) {
2920 SET_EXPECT(OnResponse);
2921 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2922 SET_EXPECT(ReportData);
2923 }
2924
2925 if(uri) {
2926 IInternetProtocolEx *protocolex;
2927
2928 hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
2929 ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
2930
2931 hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
2932 ok(hres == S_OK, "Start failed: %08x\n", hres);
2933
2934 IInternetProtocolEx_Release(protocolex);
2935 IUri_Release(uri);
2936 }else {
2937 hres = IInternetProtocol_Start(async_protocol, url, &protocol_sink, &bind_info, 0, 0);
2938 ok(hres == S_OK, "Start failed: %08x\n", hres);
2939 }
2940 if(FAILED(hres))
2941 return FALSE;
2942
2943 CHECK_CALLED(GetBindInfo);
2944 if (!(bindf & BINDF_FROMURLMON))
2945 CHECK_CALLED(ReportProgress_DIRECTBIND);
2946 if (!got_user_agent)
2947 {
2948 CHECK_CALLED(GetBindString_USER_AGENT);
2949 got_user_agent = TRUE;
2950 }
2951 CLEAR_CALLED(GetBindString_ROOTDOC_URL); /* New in IE11 */
2952 CHECK_CALLED(GetBindString_ACCEPT_MIMES);
2953 CHECK_CALLED(QueryService_HttpNegotiate);
2954 CHECK_CALLED(BeginningTransaction);
2955 /* GetRootSecurityId called on WinXP but not on Win98 */
2956 CLEAR_CALLED(GetRootSecurityId);
2957 if(http_post_test) {
2958 CHECK_CALLED(GetBindString_POST_COOKIE);
2959 if(http_post_test == TYMED_ISTREAM)
2960 CHECK_CALLED(Stream_Seek);
2961 }
2962 if(bind_from_cache) {
2963 CHECK_CALLED(OnResponse);
2964 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2965 CHECK_CALLED(ReportData);
2966 }
2967
2968 return TRUE;
2969 }
2970
2971 static void test_protocol_terminate(IInternetProtocol *protocol)
2972 {
2973 BYTE buf[3600];
2974 DWORD cb;
2975 HRESULT hres;
2976
2977 hres = IInternetProtocol_LockRequest(protocol, 0);
2978 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2979
2980 hres = IInternetProtocol_Read(protocol, buf, 1, &cb);
2981 ok(hres == (test_abort ? S_OK : S_FALSE), "Read failed: %08x\n", hres);
2982
2983 hres = IInternetProtocol_Terminate(protocol, 0);
2984 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2985
2986 /* This wait is to give the internet handles being freed in Terminate
2987 * enough time to actually terminate in all cases. Internet handles
2988 * terminate asynchronously and native reuses the main InternetOpen
2989 * handle. The only case in which this seems to be necessary is on
2990 * wine with native wininet and urlmon, resulting in the next time
2991 * test_http_protocol_url being called the first data notification actually
2992 * being an extra last data notification from the previous connection
2993 * about once out of every ten times. */
2994 Sleep(100);
2995
2996 hres = IInternetProtocol_UnlockRequest(protocol);
2997 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2998 }
2999
3000 static void test_http_info(IInternetProtocol *protocol)
3001 {
3002 IWinInetHttpInfo *info;
3003 HRESULT hres;
3004
3005 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&info);
3006 ok(hres == S_OK, "Could not get IWinInterHttpInfo iface: %08x\n", hres);
3007
3008 /* TODO */
3009
3010 IWinInetHttpInfo_Release(info);
3011 }
3012
3013 /* is_first refers to whether this is the first call to this function
3014 * _for this url_ */
3015 static void test_http_protocol_url(LPCWSTR url, int prot, DWORD flags, DWORD tymed)
3016 {
3017 IInternetProtocolInfo *protocol_info;
3018 IClassFactory *factory;
3019 IUnknown *unk;
3020 HRESULT hres;
3021
3022 init_test(prot, flags);
3023 http_url = url;
3024 http_post_test = tymed;
3025
3026 if(flags & TEST_FROMCACHE)
3027 create_cache_entry(url);
3028
3029 hres = CoGetClassObject(prot == HTTPS_TEST ? &CLSID_HttpSProtocol : &CLSID_HttpProtocol,
3030 CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3031 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3032 if(FAILED(hres))
3033 return;
3034
3035 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3036 ok(hres == E_NOINTERFACE,
3037 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
3038 hres);
3039
3040 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3041 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3042 IUnknown_Release(unk);
3043 if(FAILED(hres))
3044 return;
3045
3046 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3047 (void**)&async_protocol);
3048 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3049 if(SUCCEEDED(hres)) {
3050 BYTE buf[3600];
3051 DWORD cb;
3052 ULONG ref;
3053
3054 test_priority(async_protocol);
3055 test_http_info(async_protocol);
3056
3057 SET_EXPECT(ReportProgress_COOKIE_SENT);
3058 if(http_is_first) {
3059 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
3060 SET_EXPECT(ReportProgress_CONNECTING);
3061 }
3062 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3063 if(test_redirect)
3064 SET_EXPECT(ReportProgress_REDIRECTING);
3065 SET_EXPECT(ReportProgress_PROXYDETECTING);
3066 if(prot == HTTP_TEST)
3067 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
3068 else
3069 SET_EXPECT(QueryService_HttpSecurity);
3070 if(!(bindf & BINDF_FROMURLMON)) {
3071 SET_EXPECT(OnResponse);
3072 SET_EXPECT(ReportProgress_RAWMIMETYPE);
3073 SET_EXPECT(ReportData);
3074 } else {
3075 SET_EXPECT(Switch);
3076 }
3077
3078 if(!http_protocol_start(url, (flags & TEST_USEIURI) != 0)) {
3079 IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3080 IInternetProtocol_Release(async_protocol);
3081 return;
3082 }
3083
3084 if(!direct_read && !test_abort && !bind_from_cache)
3085 SET_EXPECT(ReportResult);
3086 expect_hrResult = test_abort ? E_ABORT : S_OK;
3087
3088 if(direct_read) {
3089 SET_EXPECT(Switch);
3090 while(wait_for_switch) {
3091 ok( WaitForSingleObject(event_continue, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3092 CHECK_CALLED(Switch); /* Set in ReportData */
3093 call_continue(&continue_protdata);
3094 SetEvent(event_continue_done);
3095 }
3096 }else if(bind_from_cache) {
3097 BYTE buf[1500];
3098
3099 hres = IInternetProtocol_Read(async_protocol, buf, 100, &cb);
3100 ok(hres == S_OK && cb == 100, "Read failed: %08x (%d bytes)\n", hres, cb);
3101
3102 SET_EXPECT(ReportResult);
3103 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3104 ok(hres == S_OK && cb == 900, "Read failed: %08x (%d bytes)\n", hres, cb);
3105 CHECK_CALLED(ReportResult);
3106
3107 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3108 ok(hres == S_FALSE && !cb, "Read failed: %08x (%d bytes)\n", hres, cb);
3109 }else {
3110 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3111 ok((hres == E_PENDING && cb==0) ||
3112 (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3113
3114 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3115 if(bindf & BINDF_FROMURLMON)
3116 CHECK_CALLED(Switch);
3117 else
3118 CHECK_CALLED(ReportData);
3119 if(prot == HTTPS_TEST)
3120 CLEAR_CALLED(QueryService_HttpSecurity);
3121
3122 while(1) {
3123 if(bindf & BINDF_FROMURLMON)
3124 SET_EXPECT(Switch);
3125 else
3126 SET_EXPECT(ReportData);
3127 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3128 if(hres == E_PENDING) {
3129 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3130 ok((hres == E_PENDING && cb==0) ||
3131 (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3132 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3133 if(bindf & BINDF_FROMURLMON)
3134 CHECK_CALLED(Switch);
3135 else
3136 CHECK_CALLED(ReportData);
3137
3138 if(test_abort) {
3139 HRESULT hres;
3140
3141 SET_EXPECT(ReportResult);
3142 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3143 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3144 CHECK_CALLED(ReportResult);
3145
3146 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3147 ok(hres == INET_E_RESULT_DISPATCHED || hres == S_OK /* IE10 */, "Abort failed: %08x\n", hres);
3148 break;
3149 }
3150 }else {
3151 if(bindf & BINDF_FROMURLMON)
3152 CHECK_NOT_CALLED(Switch);
3153 else
3154 CHECK_NOT_CALLED(ReportData);
3155 if(cb == 0) break;
3156 }
3157 }
3158 if(!test_abort) {
3159 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3160 CHECK_CALLED(ReportResult);
3161 }
3162 }
3163 if(prot == HTTPS_TEST)
3164 CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3165
3166 if (prot == HTTP_TEST || prot == HTTPS_TEST)
3167 CLEAR_CALLED(ReportProgress_COOKIE_SENT);
3168
3169 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3170 ok(hres == INET_E_RESULT_DISPATCHED || hres == S_OK /* IE10 */, "Abort failed: %08x\n", hres);
3171
3172 test_protocol_terminate(async_protocol);
3173
3174 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3175 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3176
3177 ref = IInternetProtocol_Release(async_protocol);
3178 ok(!ref, "ref=%x\n", ref);
3179 }
3180
3181 IClassFactory_Release(factory);
3182
3183 if(flags & TEST_FROMCACHE) {
3184 BOOL res;
3185
3186 res = DeleteUrlCacheEntryW(url);
3187 ok(res, "DeleteUrlCacheEntryA failed: %u\n", GetLastError());
3188 }
3189 }
3190
3191 static void test_http_protocol(void)
3192 {
3193 static const WCHAR posttest_url[] =
3194 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3195 't','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3196 static const WCHAR redirect_url[] =
3197 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3198 't','e','s','t','s','/','r','e','d','i','r','e','c','t',0};
3199 static const WCHAR winetest_url[] =
3200 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3201 't','e','s','t','s','/','d','a','t','a','.','p','h','p',0};
3202 static const WCHAR empty_url[] =
3203 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3204 't','e','s','t','s','/','e','m','p','t','y','.','j','s',0};
3205 static const WCHAR cache_only_url[] =
3206 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3207 't','e','s','t','s','/','c','a','c','h','e','-','o','n','l','y',0};
3208
3209
3210 trace("Testing http protocol (not from urlmon)...\n");
3211 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
3212 test_http_protocol_url(winetest_url, HTTP_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3213
3214 trace("Testing http protocol (from urlmon)...\n");
3215 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3216 test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3217
3218 trace("Testing http protocol (to file)...\n");
3219 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE;
3220 test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3221
3222 trace("Testing http protocol (post data)...\n");
3223 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3224 test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST, TYMED_HGLOBAL);
3225
3226 trace("Testing http protocol (post data stream)...\n");
3227 test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST|TEST_ASYNCREQ, TYMED_ISTREAM);
3228
3229 trace("Testing http protocol (direct read)...\n");
3230 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3231 test_http_protocol_url(winetest_url, HTTP_TEST, TEST_DIRECT_READ|TEST_USEIURI, TYMED_NULL);
3232
3233 trace("Testing http protocol (redirected)...\n");
3234 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3235 test_http_protocol_url(redirect_url, HTTP_TEST, TEST_REDIRECT, TYMED_NULL);
3236
3237 trace("Testing http protocol empty file...\n");
3238 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3239 test_http_protocol_url(empty_url, HTTP_TEST, TEST_EMPTY, TYMED_NULL);
3240
3241 /* This is a bit ugly. We unconditionally disable this test on Wine. This won't work until we have
3242 * support for reading from cache via HTTP layer in wininet. Until then, Wine will fail badly, affecting
3243 * other, unrelated, tests. Working around it is not worth the trouble, we may simply make sure those
3244 * tests work on Windows and have them around for the future.
3245 */
3246 if(broken(1)) {
3247 trace("Testing http protocol (from cache)...\n");
3248 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3249 test_http_protocol_url(cache_only_url, HTTP_TEST, TEST_FROMCACHE, TYMED_NULL);
3250 }
3251
3252 trace("Testing http protocol abort...\n");
3253 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3254 test_http_protocol_url(winetest_url, HTTP_TEST, TEST_ABORT, TYMED_NULL);
3255
3256 test_early_abort(&CLSID_HttpProtocol);
3257 test_early_abort(&CLSID_HttpSProtocol);
3258 }
3259
3260 static void test_https_protocol(void)
3261 {
3262 static const WCHAR https_winehq_url[] =
3263 {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3264 't','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
3265
3266 trace("Testing https protocol (from urlmon)...\n");
3267 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3268 test_http_protocol_url(https_winehq_url, HTTPS_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3269 }
3270
3271
3272 static void test_ftp_protocol(void)
3273 {
3274 IInternetProtocolInfo *protocol_info;
3275 IClassFactory *factory;
3276 IUnknown *unk;
3277 BYTE buf[4096];
3278 ULONG ref;
3279 DWORD cb;
3280 HRESULT hres;
3281
3282 static const WCHAR ftp_urlW[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
3283 '/','p','u','b','/','o','t','h','e','r','/',
3284 'w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0};
3285
3286 trace("Testing ftp protocol...\n");
3287
3288 init_test(FTP_TEST, 0);
3289
3290 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3291 state = STATE_STARTDOWNLOADING;
3292 expect_hrResult = E_PENDING;
3293
3294 hres = CoGetClassObject(&CLSID_FtpProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3295 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3296 if(FAILED(hres))
3297 return;
3298
3299 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3300 ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3301
3302 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3303 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3304 IUnknown_Release(unk);
3305 if(FAILED(hres))
3306 return;
3307
3308 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3309 (void**)&async_protocol);
3310 IClassFactory_Release(factory);
3311 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3312
3313 test_priority(async_protocol);
3314 test_http_info(async_protocol);
3315
3316 SET_EXPECT(GetBindInfo);
3317 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
3318 SET_EXPECT(ReportProgress_CONNECTING);
3319 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3320 SET_EXPECT(Switch);
3321
3322 hres = IInternetProtocol_Start(async_protocol, ftp_urlW, &protocol_sink, &bind_info, 0, 0);
3323 ok(hres == S_OK, "Start failed: %08x\n", hres);
3324 CHECK_CALLED(GetBindInfo);
3325
3326 SET_EXPECT(ReportResult);
3327
3328 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3329 ok((hres == E_PENDING && cb==0) ||
3330 (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3331
3332 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3333
3334 while(1) {
3335 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3336 if(hres == E_PENDING)
3337 {
3338 DWORD ret = WaitForSingleObject(event_complete, 90000);
3339 ok( ret == WAIT_OBJECT_0, "wait timed out\n" );
3340 if (ret != WAIT_OBJECT_0) break;
3341 }
3342 else
3343 if(cb == 0) break;
3344 }
3345
3346 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3347 CHECK_CALLED(ReportResult);
3348 CHECK_CALLED(Switch);
3349
3350 test_protocol_terminate(async_protocol);
3351
3352 if(pCreateUri) {
3353 IInternetProtocolEx *protocolex;
3354
3355 hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3356 ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3357 IInternetProtocolEx_Release(protocolex);
3358 }
3359
3360 ref = IInternetProtocol_Release(async_protocol);
3361 ok(!ref, "ref=%d\n", ref);
3362
3363 test_early_abort(&CLSID_FtpProtocol);
3364 }
3365
3366 static void test_gopher_protocol(void)
3367 {
3368 IInternetProtocolInfo *protocol_info;
3369 IClassFactory *factory;
3370 IUnknown *unk;
3371 HRESULT hres;
3372
3373 trace("Testing gopher protocol...\n");
3374
3375 hres = CoGetClassObject(&CLSID_GopherProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3376 ok(hres == S_OK ||
3377 broken(hres == REGDB_E_CLASSNOTREG || hres == CLASS_E_CLASSNOTAVAILABLE), /* Gopher protocol has been removed as of Vista */
3378 "CoGetClassObject failed: %08x\n", hres);
3379 if(FAILED(hres))
3380 return;
3381
3382 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3383 ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3384
3385 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3386 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3387 IUnknown_Release(unk);
3388 if(FAILED(hres))
3389 return;
3390
3391 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3392 (void**)&async_protocol);
3393 IClassFactory_Release(factory);
3394 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3395
3396 test_priority(async_protocol);
3397
3398 IInternetProtocol_Release(async_protocol);
3399
3400 test_early_abort(&CLSID_GopherProtocol);
3401 }
3402
3403 static void test_mk_protocol(void)
3404 {
3405 IInternetProtocolInfo *protocol_info;
3406 IInternetProtocol *protocol;
3407 IClassFactory *factory;
3408 IUnknown *unk;
3409 HRESULT hres;
3410
3411 static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
3412 ':',':','/','t','e','s','t','.','h','t','m','l',0};
3413 static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
3414
3415 trace("Testing mk protocol...\n");
3416 init_test(MK_TEST, 0);
3417
3418 hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
3419 &IID_IUnknown, (void**)&unk);
3420 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3421
3422 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3423 ok(hres == E_NOINTERFACE,
3424 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
3425 hres);
3426
3427 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3428 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3429 IUnknown_Release(unk);
3430 if(FAILED(hres))
3431 return;
3432
3433 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3434 (void**)&protocol);
3435 IClassFactory_Release(factory);
3436 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3437
3438 SET_EXPECT(GetBindInfo);
3439 hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
3440 ok(hres == MK_E_SYNTAX || hres == INET_E_INVALID_URL,
3441 "Start failed: %08x, expected MK_E_SYNTAX or INET_E_INVALID_URL\n", hres);
3442 CLEAR_CALLED(GetBindInfo);
3443
3444 SET_EXPECT(GetBindInfo);
3445 SET_EXPECT(ReportProgress_DIRECTBIND);
3446 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3447 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
3448 SET_EXPECT(ReportResult);
3449 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
3450
3451 hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
3452 ok(hres == INET_E_RESOURCE_NOT_FOUND ||
3453 hres == INET_E_INVALID_URL, /* win2k3 */
3454 "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND or INET_E_INVALID_URL\n", hres);
3455
3456 if (hres == INET_E_RESOURCE_NOT_FOUND) {
3457 CHECK_CALLED(GetBindInfo);
3458 CLEAR_CALLED(ReportProgress_DIRECTBIND);
3459 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
3460 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3461 CHECK_CALLED(ReportResult);
3462 }else {
3463 CLEAR_CALLED(GetBindInfo);
3464 CLEAR_CALLED(ReportProgress_DIRECTBIND);
3465 CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3466 CLEAR_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3467 CLEAR_CALLED(ReportResult);
3468 }
3469
3470 IInternetProtocol_Release(protocol);
3471 }
3472
3473 static void test_CreateBinding(void)
3474 {
3475 IInternetProtocol *protocol;
3476 IInternetPriority *priority;
3477 IInternetSession *session;
3478 IWinInetHttpInfo *http_info;
3479 IWinInetInfo *inet_info;
3480 LONG p;
3481 BYTE buf[1000];
3482 DWORD read;
3483 HRESULT hres;
3484
3485 static const WCHAR test_url[] =
3486 {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
3487 static const WCHAR wsz_test[] = {'t','e','s','t',0};
3488
3489 trace("Testing CreateBinding...\n");
3490 init_test(BIND_TEST, TEST_BINDING);
3491
3492 hres = pCoInternetGetSession(0, &session, 0);
3493 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
3494
3495 hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
3496 ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
3497
3498 hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3499 binding_protocol = protocol;
3500 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3501 ok(protocol != NULL, "protocol == NULL\n");
3502
3503 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
3504 ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
3505
3506 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
3507 ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres);
3508
3509 hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
3510 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3511 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
3512 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3513 hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
3514 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3515
3516 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
3517 ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
3518
3519 p = 0xdeadbeef;
3520 hres = IInternetPriority_GetPriority(priority, &p);
3521 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3522 ok(!p, "p=%d\n", p);
3523
3524 ex_priority = 100;
3525 hres = IInternetPriority_SetPriority(priority, 100);
3526 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3527
3528 p = 0xdeadbeef;
3529 hres = IInternetPriority_GetPriority(priority, &p);
3530 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3531 ok(p == 100, "p=%d\n", p);
3532
3533 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3534 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3535
3536 SET_EXPECT(QueryService_InternetProtocol);
3537 SET_EXPECT(CreateInstance);
3538 SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
3539 SET_EXPECT(SetPriority);
3540 SET_EXPECT(Start);
3541
3542 expect_hrResult = S_OK;
3543 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
3544 ok(hres == S_OK, "Start failed: %08x\n", hres);
3545
3546 CHECK_CALLED(QueryService_InternetProtocol);
3547 CHECK_CALLED(CreateInstance);
3548 CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
3549 CHECK_CALLED(SetPriority);
3550 CHECK_CALLED(Start);
3551
3552 SET_EXPECT(QueryInterface_IWinInetInfo);
3553 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3554 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3555 CHECK_CALLED(QueryInterface_IWinInetInfo);
3556
3557 SET_EXPECT(QueryInterface_IWinInetInfo);
3558 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3559 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3560 CHECK_CALLED(QueryInterface_IWinInetInfo);
3561
3562 SET_EXPECT(QueryInterface_IWinInetHttpInfo);
3563 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
3564 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3565 CHECK_CALLED(QueryInterface_IWinInetHttpInfo);
3566
3567 SET_EXPECT(Read);
3568 read = 0xdeadbeef;
3569 hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3570 ok(hres == S_OK, "Read failed: %08x\n", hres);
3571 ok(read == 100, "read = %d\n", read);
3572 CHECK_CALLED(Read);
3573
3574 SET_EXPECT(Read);
3575 read = 0xdeadbeef;
3576 hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3577 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3578 ok(!read, "read = %d\n", read);
3579 CHECK_CALLED(Read);
3580
3581 p = 0xdeadbeef;
3582 hres = IInternetPriority_GetPriority(priority, &p);
3583 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3584 ok(p == 100, "p=%d\n", p);
3585
3586 hres = IInternetPriority_SetPriority(priority, 101);
3587 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3588
3589 SET_EXPECT(Terminate);
3590 hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
3591 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3592 CHECK_CALLED(Terminate);
3593
3594 SET_EXPECT(Continue);
3595 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
3596 ok(hres == S_OK, "Switch failed: %08x\n", hres);
3597 CHECK_CALLED(Continue);
3598
3599 hres = IInternetProtocolSink_ReportProgress(binding_sink,
3600 BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
3601 ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
3602
3603 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
3604 ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres);
3605
3606 hres = IInternetProtocolSink_ReportData(binding_sink, 0, 0, 0);
3607 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
3608
3609 IInternetProtocolSink_Release(binding_sink);
3610 IInternetPriority_Release(priority);
3611 IInternetBindInfo_Release(prot_bind_info);
3612 IInternetProtocol_Release(protocol);
3613
3614 hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3615 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3616 ok(protocol != NULL, "protocol == NULL\n");
3617
3618 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3619 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3620
3621 hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
3622 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3623
3624 IInternetProtocol_Release(protocol);
3625
3626 hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, wsz_test);
3627 ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
3628
3629 hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3630 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3631 ok(protocol != NULL, "protocol == NULL\n");
3632
3633 SET_EXPECT(QueryService_InternetProtocol);
3634 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
3635 ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
3636 CHECK_CALLED(QueryService_InternetProtocol);
3637
3638 IInternetProtocol_Release(protocol);
3639
3640 IInternetSession_Release(session);
3641 }
3642
3643 static void test_binding(int prot, DWORD grf_pi, DWORD test_flags)
3644 {
3645 IInternetProtocolEx *protocolex = NULL;
3646 IInternetProtocol *protocol;
3647 IInternetSession *session;
3648 IUri *uri = NULL;
3649 ULONG ref;
3650 HRESULT hres;
3651
3652 pi = grf_pi;
3653
3654 init_test(prot, test_flags|TEST_BINDING);
3655
3656 hres = pCoInternetGetSession(0, &session, 0);
3657 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
3658
3659 if(test_flags & TEST_EMULATEPROT) {
3660 hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, protocol_names[prot], 0, NULL, 0);
3661 ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
3662 }
3663
3664 hres = IInternetSession_CreateBinding(session, NULL, binding_urls[prot], NULL, NULL, &protocol, 0);
3665 binding_protocol = protocol;
3666 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3667 ok(protocol != NULL, "protocol == NULL\n");
3668
3669 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
3670 ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
3671
3672 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
3673 ok(hres == S_OK, "QueryInterface(IID_IInternetProtocolSink) failed: %08x\n", hres);
3674
3675 if(test_flags & TEST_USEIURI) {
3676 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3677 ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3678
3679 hres = pCreateUri(binding_urls[prot], Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
3680 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
3681 }
3682
3683 ex_priority = 0;
3684 SET_EXPECT(QueryService_InternetProtocol);
3685 SET_EXPECT(CreateInstance);
3686 SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
3687 SET_EXPECT(SetPriority);
3688 if(impl_protex)
3689 SET_EXPECT(StartEx);
3690 else
3691 SET_EXPECT(Start);
3692
3693 expect_hrResult = S_OK;
3694
3695 if(protocolex) {
3696 hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, pi, 0);
3697 ok(hres == S_OK, "StartEx failed: %08x\n", hres);
3698 }else {
3699 hres = IInternetProtocol_Start(protocol, binding_urls[prot], &protocol_sink, &bind_info, pi, 0);
3700 ok(hres == S_OK, "Start failed: %08x\n", hres);
3701 }
3702
3703 CHECK_CALLED(QueryService_InternetProtocol);
3704 CHECK_CALLED(CreateInstance);
3705 CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
3706 CLEAR_CALLED(SetPriority); /* IE11 does not call it. */
3707 if(impl_protex)
3708 CHECK_CALLED(StartEx);
3709 else
3710 CHECK_CALLED(Start);
3711
3712 if(protocolex)
3713 IInternetProtocolEx_Release(protocolex);
3714 if(uri)
3715 IUri_Release(uri);
3716
3717 if(prot == HTTP_TEST || prot == HTTPS_TEST) {
3718 while(prot_state < 4) {
3719 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3720 if(mimefilter_test && filtered_protocol) {
3721 SET_EXPECT(Continue);
3722 IInternetProtocol_Continue(filtered_protocol, pdata);
3723 CHECK_CALLED(Continue);
3724 }else {
3725 SET_EXPECT(Continue);
3726 IInternetProtocol_Continue(protocol, pdata);
3727 CHECK_CALLED(Continue);
3728 }
3729 if(test_abort && prot_state == 2) {
3730 SET_EXPECT(Abort);
3731 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3732 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3733 CHECK_CALLED(Abort);
3734
3735 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
3736 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3737 SetEvent(event_complete2);
3738 break;
3739 }
3740 SetEvent(event_complete2);
3741 }
3742 if(direct_read)
3743 CHECK_CALLED(ReportData); /* Set in ReportResult */
3744 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3745 }else {
3746 if(mimefilter_test)
3747 SET_EXPECT(MimeFilter_LockRequest);
3748 else
3749 SET_EXPECT(LockRequest);
3750 hres = IInternetProtocol_LockRequest(protocol, 0);
3751 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
3752 if(mimefilter_test)
3753 CHECK_CALLED(MimeFilter_LockRequest);
3754 else
3755 CHECK_CALLED(LockRequest);
3756
3757 if(mimefilter_test)
3758 SET_EXPECT(MimeFilter_UnlockRequest);
3759 else
3760 SET_EXPECT(UnlockRequest);
3761 hres = IInternetProtocol_UnlockRequest(protocol);
3762 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
3763 if(mimefilter_test)
3764 CHECK_CALLED(MimeFilter_UnlockRequest);
3765 else
3766 CHECK_CALLED(UnlockRequest);
3767 }
3768
3769 if(mimefilter_test)
3770 SET_EXPECT(MimeFilter_Terminate);
3771 else
3772 SET_EXPECT(Terminate);
3773 hres = IInternetProtocol_Terminate(protocol, 0);
3774 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3775 if(mimefilter_test)
3776 CLEAR_CALLED(MimeFilter_Terminate);
3777 else
3778 CHECK_CALLED(Terminate);
3779
3780 if(filtered_protocol)
3781 IInternetProtocol_Release(filtered_protocol);
3782 IInternetBindInfo_Release(prot_bind_info);
3783 IInternetProtocolSink_Release(binding_sink);
3784 ref = IInternetProtocol_Release(protocol);
3785 ok(!ref, "ref=%u, expected 0\n", ref);
3786
3787 if(test_flags & TEST_EMULATEPROT) {
3788 hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, protocol_names[prot]);
3789 ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
3790 }
3791
3792 IInternetSession_Release(session);
3793 }
3794
3795 START_TEST(protocol)
3796 {
3797 HMODULE hurlmon;
3798
3799 hurlmon = GetModuleHandleA("urlmon.dll");
3800 pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
3801 pReleaseBindInfo = (void*) GetProcAddress(hurlmon, "ReleaseBindInfo");
3802 pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
3803
3804 if(!GetProcAddress(hurlmon, "CompareSecurityIds")) {
3805 win_skip("Various needed functions not present, too old IE\n");
3806 return;
3807 }
3808
3809 if(!pCreateUri)
3810 win_skip("CreateUri not supported\n");
3811
3812 OleInitialize(NULL);
3813
3814 event_complete = CreateEventW(NULL, FALSE, FALSE, NULL);
3815 event_complete2 = CreateEventW(NULL, FALSE, FALSE, NULL);
3816 event_continue = CreateEventW(NULL, FALSE, FALSE, NULL);
3817 event_continue_done = CreateEventW(NULL, FALSE, FALSE, NULL);
3818 thread_id = GetCurrentThreadId();
3819
3820 test_file_protocol();
3821 test_http_protocol();
3822 if(pCreateUri)
3823 test_https_protocol();
3824 else
3825 win_skip("Skipping https tests on too old platform\n");
3826 test_ftp_protocol();
3827 test_gopher_protocol();
3828 test_mk_protocol();
3829 test_CreateBinding();
3830
3831 bindf &= ~BINDF_FROMURLMON;
3832 trace("Testing file binding (mime verification, emulate prot)...\n");
3833 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
3834 trace("Testing http binding (mime verification, emulate prot)...\n");
3835 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
3836 trace("Testing its binding (mime verification, emulate prot)...\n");
3837 test_binding(ITS_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
3838 trace("Testing http binding (mime verification, emulate prot, short read, direct read)...\n");
3839 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_SHORT_READ|TEST_DIRECT_READ);
3840 trace("Testing file binding (mime verification, emulate prot, mime filter)...\n");
3841 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
3842 trace("Testing http binding (mime verification, emulate prot, mime filter)...\n");
3843 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
3844 trace("Testing http binding (mime verification, emulate prot, mime filter, no mime)...\n");
3845 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER|TEST_NOMIME);
3846 trace("Testing http binding (mime verification, emulate prot, direct read)...\n");
3847 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_DIRECT_READ);
3848 trace("Testing http binding (mime verification, emulate prot, abort)...\n");
3849 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_ABORT);
3850 if(pCreateUri) {
3851 trace("Testing file binding (use IUri, mime verification, emulate prot)...\n");
3852 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI);
3853 trace("Testing file binding (use IUri, impl StartEx, mime verification, emulate prot)...\n");
3854 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI|TEST_IMPLPROTEX);
3855 trace("Testing file binding (impl StartEx, mime verification, emulate prot)...\n");
3856 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_IMPLPROTEX);
3857 }
3858
3859 CloseHandle(event_complete);
3860 CloseHandle(event_complete2);
3861 CloseHandle(event_continue);
3862 CloseHandle(event_continue_done);
3863
3864 OleUninitialize();
3865 }