[URLMON_WINETEST] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / modules / 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 COBJMACROS
20 #define CONST_VTABLE
21
22 #include <wine/test.h>
23 #include <wine/heap.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "ole2.h"
30 #include "urlmon.h"
31 #include "wininet.h"
32
33 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD, IInternetSession **, DWORD);
34 static HRESULT (WINAPI *pReleaseBindInfo)(BINDINFO*);
35 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
36
37 #define DEFINE_EXPECT(func) \
38 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
39
40 #define SET_EXPECT(func) \
41 expect_ ## func = TRUE
42
43 #define CHECK_EXPECT2(func) \
44 do { \
45 ok(expect_ ##func, "unexpected call " #func "\n"); \
46 called_ ## func = TRUE; \
47 }while(0)
48
49 #define CHECK_EXPECT(func) \
50 do { \
51 CHECK_EXPECT2(func); \
52 expect_ ## func = FALSE; \
53 }while(0)
54
55 #define CHECK_CALLED(func) \
56 do { \
57 ok(called_ ## func, "expected " #func "\n"); \
58 expect_ ## func = called_ ## func = FALSE; \
59 }while(0)
60
61 #define CHECK_NOT_CALLED(func) \
62 do { \
63 ok(!called_ ## func, "unexpected " #func "\n"); \
64 expect_ ## func = called_ ## func = FALSE; \
65 }while(0)
66
67 #define CLEAR_CALLED(func) \
68 expect_ ## func = called_ ## func = FALSE
69
70 DEFINE_EXPECT(GetBindInfo);
71 DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
72 DEFINE_EXPECT(ReportProgress_DIRECTBIND);
73 DEFINE_EXPECT(ReportProgress_RAWMIMETYPE);
74 DEFINE_EXPECT(ReportProgress_FINDINGRESOURCE);
75 DEFINE_EXPECT(ReportProgress_CONNECTING);
76 DEFINE_EXPECT(ReportProgress_SENDINGREQUEST);
77 DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
78 DEFINE_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
79 DEFINE_EXPECT(ReportProgress_PROTOCOLCLASSID);
80 DEFINE_EXPECT(ReportProgress_COOKIE_SENT);
81 DEFINE_EXPECT(ReportProgress_REDIRECTING);
82 DEFINE_EXPECT(ReportProgress_ENCODING);
83 DEFINE_EXPECT(ReportProgress_ACCEPTRANGES);
84 DEFINE_EXPECT(ReportProgress_PROXYDETECTING);
85 DEFINE_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
86 DEFINE_EXPECT(ReportProgress_DECODING);
87 DEFINE_EXPECT(ReportData);
88 DEFINE_EXPECT(ReportData2);
89 DEFINE_EXPECT(ReportResult);
90 DEFINE_EXPECT(GetBindString_ACCEPT_MIMES);
91 DEFINE_EXPECT(GetBindString_USER_AGENT);
92 DEFINE_EXPECT(GetBindString_POST_COOKIE);
93 DEFINE_EXPECT(GetBindString_URL);
94 DEFINE_EXPECT(GetBindString_ROOTDOC_URL);
95 DEFINE_EXPECT(QueryService_HttpNegotiate);
96 DEFINE_EXPECT(QueryService_InternetProtocol);
97 DEFINE_EXPECT(QueryService_HttpSecurity);
98 DEFINE_EXPECT(QueryService_IBindCallbackRedirect);
99 DEFINE_EXPECT(QueryInterface_IWinInetInfo);
100 DEFINE_EXPECT(QueryInterface_IWinInetHttpInfo);
101 DEFINE_EXPECT(BeginningTransaction);
102 DEFINE_EXPECT(GetRootSecurityId);
103 DEFINE_EXPECT(OnResponse);
104 DEFINE_EXPECT(Switch);
105 DEFINE_EXPECT(Continue);
106 DEFINE_EXPECT(CreateInstance);
107 DEFINE_EXPECT(Start);
108 DEFINE_EXPECT(StartEx);
109 DEFINE_EXPECT(Terminate);
110 DEFINE_EXPECT(Read);
111 DEFINE_EXPECT(Read2);
112 DEFINE_EXPECT(SetPriority);
113 DEFINE_EXPECT(LockRequest);
114 DEFINE_EXPECT(UnlockRequest);
115 DEFINE_EXPECT(Abort);
116 DEFINE_EXPECT(MimeFilter_CreateInstance);
117 DEFINE_EXPECT(MimeFilter_Start);
118 DEFINE_EXPECT(MimeFilter_ReportData);
119 DEFINE_EXPECT(MimeFilter_ReportResult);
120 DEFINE_EXPECT(MimeFilter_Terminate);
121 DEFINE_EXPECT(MimeFilter_LockRequest);
122 DEFINE_EXPECT(MimeFilter_UnlockRequest);
123 DEFINE_EXPECT(MimeFilter_Read);
124 DEFINE_EXPECT(MimeFilter_Switch);
125 DEFINE_EXPECT(MimeFilter_Continue);
126 DEFINE_EXPECT(Stream_Seek);
127 DEFINE_EXPECT(Stream_Read);
128 DEFINE_EXPECT(Redirect);
129 DEFINE_EXPECT(outer_QI_test);
130 DEFINE_EXPECT(Protocol_destructor);
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, redirect_on_continue;
149 static int prot_state, read_report_data, post_stream_read;
150 static DWORD bindf, ex_priority , pi, bindinfo_options;
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, reuse_protocol_thread;
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 typedef struct {
181 IUnknown IUnknown_inner;
182 IInternetProtocolEx IInternetProtocolEx_iface;
183 IInternetPriority IInternetPriority_iface;
184 IUnknown *outer;
185 LONG inner_ref;
186 LONG outer_ref;
187 } Protocol;
188
189 static Protocol *protocol_emul;
190
191 static const WCHAR protocol_names[][10] = {
192 {'f','i','l','e',0},
193 {'h','t','t','p',0},
194 {'h','t','t','p','s',0},
195 {'f','t','p',0},
196 {'m','k',0},
197 {'i','t','s',0},
198 {'t','e','s','t',0}
199 };
200
201 static const WCHAR binding_urls[][130] = {
202 {'f','i','l','e',':','t','e','s','t','.','h','t','m','l',0},
203 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
204 'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0},
205 {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
206 '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0},
207 {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
208 '/','p','u','b','/','o','t','h','e','r',
209 '/','w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0},
210 {'m','k',':','t','e','s','t',0},
211 {'i','t','s',':','t','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0},
212 {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0}
213 };
214
215 static const CHAR post_data[] = "mode=Test";
216
217 static int strcmp_wa(LPCWSTR strw, const char *stra)
218 {
219 CHAR buf[512];
220 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
221 return lstrcmpA(stra, buf);
222 }
223
224 static const char *w2a(LPCWSTR str)
225 {
226 static char buf[INTERNET_MAX_URL_LENGTH];
227 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
228 return buf;
229 }
230
231 static HRESULT WINAPI HttpSecurity_QueryInterface(IHttpSecurity *iface, REFIID riid, void **ppv)
232 {
233 if(IsEqualGUID(&IID_IUnknown, riid)
234 || IsEqualGUID(&IID_IHttpSecurity, riid)) {
235 *ppv = iface;
236 return S_OK;
237 }
238
239 ok(0, "unexpected call\n");
240 return E_NOINTERFACE;
241 }
242
243 static ULONG WINAPI HttpSecurity_AddRef(IHttpSecurity *iface)
244 {
245 return 2;
246 }
247
248 static ULONG WINAPI HttpSecurity_Release(IHttpSecurity *iface)
249 {
250 return 1;
251 }
252
253 static HRESULT WINAPI HttpSecurity_GetWindow(IHttpSecurity* iface, REFGUID rguidReason, HWND *phwnd)
254 {
255 trace("HttpSecurity_GetWindow\n");
256
257 return S_FALSE;
258 }
259
260 static HRESULT WINAPI HttpSecurity_OnSecurityProblem(IHttpSecurity *iface, DWORD dwProblem)
261 {
262 win_skip("Security problem: %u\n", dwProblem);
263 ok(dwProblem == ERROR_INTERNET_SEC_CERT_REV_FAILED || dwProblem == ERROR_INTERNET_INVALID_CA,
264 "Expected got %u security problem\n", dwProblem);
265
266 /* Only retry once */
267 if (security_problem)
268 return E_ABORT;
269
270 security_problem = TRUE;
271 if(dwProblem == ERROR_INTERNET_INVALID_CA)
272 return E_ABORT;
273 SET_EXPECT(BeginningTransaction);
274
275 return RPC_E_RETRY;
276 }
277
278 static IHttpSecurityVtbl HttpSecurityVtbl = {
279 HttpSecurity_QueryInterface,
280 HttpSecurity_AddRef,
281 HttpSecurity_Release,
282 HttpSecurity_GetWindow,
283 HttpSecurity_OnSecurityProblem
284 };
285
286 static IHttpSecurity http_security = { &HttpSecurityVtbl };
287
288 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
289 {
290 if(IsEqualGUID(&IID_IUnknown, riid)
291 || IsEqualGUID(&IID_IHttpNegotiate, riid)
292 || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
293 *ppv = iface;
294 return S_OK;
295 }
296
297 ok(0, "unexpected call\n");
298 return E_NOINTERFACE;
299 }
300
301 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
302 {
303 return 2;
304 }
305
306 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
307 {
308 return 1;
309 }
310
311 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
312 LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
313 {
314 LPWSTR addl_headers;
315
316 static const WCHAR wszHeaders[] =
317 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
318 'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
319 'd','e','d','\r','\n',0};
320
321 CHECK_EXPECT(BeginningTransaction);
322
323 if(binding_test)
324 ok(!lstrcmpW(szURL, binding_urls[tested_protocol]), "szURL != http_url\n");
325 else
326 ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
327 ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
328 ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
329 if(pszAdditionalHeaders)
330 {
331 ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
332 if (http_post_test)
333 {
334 addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
335 memcpy(addl_headers, wszHeaders, sizeof(wszHeaders));
336 *pszAdditionalHeaders = addl_headers;
337 }
338 }
339
340 return S_OK;
341 }
342
343 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
344 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
345 {
346 CHECK_EXPECT(OnResponse);
347
348 ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
349 ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
350 ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
351 ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
352
353 return S_OK;
354 }
355
356 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
357 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
358 {
359 static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
360
361 CHECK_EXPECT(GetRootSecurityId);
362
363 ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
364 ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
365 ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
366
367 if(pcbSecurityId) {
368 ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
369 *pcbSecurityId = sizeof(sec_id);
370 }
371
372 if(pbSecurityId)
373 memcpy(pbSecurityId, sec_id, sizeof(sec_id));
374
375 return E_FAIL;
376 }
377
378 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
379 HttpNegotiate_QueryInterface,
380 HttpNegotiate_AddRef,
381 HttpNegotiate_Release,
382 HttpNegotiate_BeginningTransaction,
383 HttpNegotiate_OnResponse,
384 HttpNegotiate_GetRootSecurityId
385 };
386
387 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
388
389 static HRESULT WINAPI BindCallbackRedirect_QueryInterface(IBindCallbackRedirect *iface, REFIID riid, void **ppv)
390 {
391 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
392 *ppv = NULL;
393 return E_NOINTERFACE;
394 }
395
396 static ULONG WINAPI BindCallbackRedirect_AddRef(IBindCallbackRedirect *iface)
397 {
398 return 2;
399 }
400
401 static ULONG WINAPI BindCallbackRedirect_Release(IBindCallbackRedirect *iface)
402 {
403 return 1;
404 }
405
406 static HRESULT WINAPI BindCallbackRedirect_Redirect(IBindCallbackRedirect *iface, const WCHAR *url, VARIANT_BOOL *cancel)
407 {
408 CHECK_EXPECT(Redirect);
409 *cancel = VARIANT_FALSE;
410 return S_OK;
411 }
412
413 static const IBindCallbackRedirectVtbl BindCallbackRedirectVtbl = {
414 BindCallbackRedirect_QueryInterface,
415 BindCallbackRedirect_AddRef,
416 BindCallbackRedirect_Release,
417 BindCallbackRedirect_Redirect
418 };
419
420 static IBindCallbackRedirect redirect_callback = { &BindCallbackRedirectVtbl };
421
422 static HRESULT QueryInterface(REFIID,void**);
423
424 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
425 {
426 return QueryInterface(riid, ppv);
427 }
428
429 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
430 {
431 return 2;
432 }
433
434 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
435 {
436 return 1;
437 }
438
439 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
440 REFIID riid, void **ppv)
441 {
442 if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
443 CHECK_EXPECT2(QueryService_HttpNegotiate);
444 return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
445 }
446
447 if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
448 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
449 CHECK_EXPECT(QueryService_InternetProtocol);
450 return E_NOINTERFACE;
451 }
452
453 if(IsEqualGUID(&IID_IHttpSecurity, guidService)) {
454 ok(IsEqualGUID(&IID_IHttpSecurity, riid), "unexpected riid\n");
455 CHECK_EXPECT(QueryService_HttpSecurity);
456 return IHttpSecurity_QueryInterface(&http_security, riid, ppv);
457 }
458
459 if(IsEqualGUID(&IID_IBindCallbackRedirect, guidService)) {
460 CHECK_EXPECT(QueryService_IBindCallbackRedirect);
461 ok(IsEqualGUID(&IID_IBindCallbackRedirect, riid), "riid = %s\n", wine_dbgstr_guid(riid));
462 *ppv = &redirect_callback;
463 return S_OK;
464 }
465
466 if(IsEqualGUID(&IID_IGetBindHandle, guidService)) {
467 trace("QueryService(IID_IGetBindHandle)\n");
468 *ppv = NULL;
469 return E_NOINTERFACE;
470 }
471
472 if(IsEqualGUID(&IID_IWindowForBindingUI, guidService)) {
473 trace("QueryService(IID_IWindowForBindingUI)\n");
474 *ppv = NULL;
475 return E_NOINTERFACE;
476 }
477
478 ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService));
479 return E_FAIL;
480 }
481
482 static const IServiceProviderVtbl ServiceProviderVtbl = {
483 ServiceProvider_QueryInterface,
484 ServiceProvider_AddRef,
485 ServiceProvider_Release,
486 ServiceProvider_QueryService
487 };
488
489 static IServiceProvider service_provider = { &ServiceProviderVtbl };
490
491 static HRESULT WINAPI Stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
492 {
493 static const IID IID_strm_unknown = {0x2f68429a,0x199a,0x4043,{0x93,0x11,0xf2,0xfe,0x7c,0x13,0xcc,0xb9}};
494
495 if(!IsEqualGUID(&IID_strm_unknown, riid)) /* IE11 */
496 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
497
498 *ppv = NULL;
499 return E_NOINTERFACE;
500 }
501
502 static ULONG WINAPI Stream_AddRef(IStream *iface)
503 {
504 return 2;
505 }
506
507 static ULONG WINAPI Stream_Release(IStream *iface)
508 {
509 return 1;
510 }
511
512 static HRESULT WINAPI Stream_Read(IStream *iface, void *pv,
513 ULONG cb, ULONG *pcbRead)
514 {
515 CHECK_EXPECT2(Stream_Read);
516
517 ok(GetCurrentThreadId() != thread_id, "wrong thread %d\n", GetCurrentThreadId());
518
519 ok(pv != NULL, "pv == NULL\n");
520 ok(cb == 0x20000 || broken(cb == 0x2000), "cb = %d\n", cb);
521 ok(pcbRead != NULL, "pcbRead == NULL\n");
522
523 if(post_stream_read) {
524 *pcbRead = 0;
525 return S_FALSE;
526 }
527
528 memcpy(pv, post_data, sizeof(post_data)-1);
529 post_stream_read += *pcbRead = sizeof(post_data)-1;
530 return S_OK;
531 }
532
533 static HRESULT WINAPI Stream_Write(IStream *iface, const void *pv,
534 ULONG cb, ULONG *pcbWritten)
535 {
536 ok(0, "unexpected call\n");
537 return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
541 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
542 {
543 CHECK_EXPECT(Stream_Seek);
544
545 ok(!dlibMove.QuadPart, "dlibMove != 0\n");
546 ok(dwOrigin == STREAM_SEEK_SET, "dwOrigin = %d\n", dwOrigin);
547 ok(!plibNewPosition, "plibNewPosition == NULL\n");
548
549 return S_OK;
550 }
551
552 static HRESULT WINAPI Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
553 {
554 ok(0, "unexpected call\n");
555 return E_NOTIMPL;
556 }
557
558 static HRESULT WINAPI Stream_CopyTo(IStream *iface, IStream *pstm,
559 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
560 {
561 ok(0, "unexpected call\n");
562 return E_NOTIMPL;
563 }
564
565 static HRESULT WINAPI Stream_Commit(IStream *iface, DWORD grfCommitFlags)
566 {
567 ok(0, "unexpected call\n");
568 return E_NOTIMPL;
569 }
570
571 static HRESULT WINAPI Stream_Revert(IStream *iface)
572 {
573 ok(0, "unexpected call\n");
574 return E_NOTIMPL;
575 }
576
577 static HRESULT WINAPI Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
578 ULARGE_INTEGER cb, DWORD dwLockType)
579 {
580 ok(0, "unexpected call\n");
581 return E_NOTIMPL;
582 }
583
584 static HRESULT WINAPI Stream_UnlockRegion(IStream *iface,
585 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
586 {
587 ok(0, "unexpected call\n");
588 return E_NOTIMPL;
589 }
590
591 static HRESULT WINAPI Stream_Stat(IStream *iface, STATSTG *pstatstg,
592 DWORD dwStatFlag)
593 {
594 ok(0, "unexpected call\n");
595 return E_NOTIMPL;
596 }
597
598 static HRESULT WINAPI Stream_Clone(IStream *iface, IStream **ppstm)
599 {
600 ok(0, "unexpected call\n");
601 return E_NOTIMPL;
602 }
603
604 static const IStreamVtbl StreamVtbl = {
605 Stream_QueryInterface,
606 Stream_AddRef,
607 Stream_Release,
608 Stream_Read,
609 Stream_Write,
610 Stream_Seek,
611 Stream_SetSize,
612 Stream_CopyTo,
613 Stream_Commit,
614 Stream_Revert,
615 Stream_LockRegion,
616 Stream_UnlockRegion,
617 Stream_Stat,
618 Stream_Clone
619 };
620
621 static IStream Stream = { &StreamVtbl };
622
623 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
624 {
625 return QueryInterface(riid, ppv);
626 }
627
628 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
629 {
630 return 2;
631 }
632
633 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
634 {
635 return 1;
636 }
637
638 static void call_continue(PROTOCOLDATA *protocol_data)
639 {
640 HRESULT hres;
641
642 if (winetest_debug > 1)
643 trace("continue in state %d\n", state);
644
645 if(state == STATE_CONNECTING) {
646 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST) {
647 if (http_is_first){
648 CLEAR_CALLED(ReportProgress_FINDINGRESOURCE);
649 CLEAR_CALLED(ReportProgress_PROXYDETECTING);
650 }
651 CLEAR_CALLED(ReportProgress_CONNECTING);
652 }
653 if(tested_protocol == FTP_TEST)
654 todo_wine CHECK_CALLED(ReportProgress_SENDINGREQUEST);
655 else if (tested_protocol != HTTPS_TEST)
656 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
657 if(test_redirect && !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
658 CHECK_CALLED(ReportProgress_REDIRECTING);
659 state = test_async_req ? STATE_SENDINGREQUEST : STATE_STARTDOWNLOADING;
660 }
661
662 switch(state) {
663 case STATE_SENDINGREQUEST:
664 SET_EXPECT(Stream_Read);
665 SET_EXPECT(ReportProgress_SENDINGREQUEST);
666 break;
667 case STATE_STARTDOWNLOADING:
668 if((tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST)
669 && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))) {
670 SET_EXPECT(OnResponse);
671 if(tested_protocol == HTTPS_TEST || test_redirect || test_abort || empty_file)
672 SET_EXPECT(ReportProgress_ACCEPTRANGES);
673 SET_EXPECT(ReportProgress_ENCODING);
674 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
675 if(bindf & BINDF_NEEDFILE)
676 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
677 }
678 default:
679 break;
680 }
681
682 if(state != STATE_SENDINGREQUEST && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)))
683 SET_EXPECT(ReportData);
684 hres = IInternetProtocol_Continue(async_protocol, protocol_data);
685 ok(hres == S_OK, "Continue failed: %08x\n", hres);
686 if(tested_protocol == FTP_TEST || security_problem)
687 CLEAR_CALLED(ReportData);
688 else if(state != STATE_SENDINGREQUEST && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)))
689 CHECK_CALLED(ReportData);
690
691 switch(state) {
692 case STATE_SENDINGREQUEST:
693 CHECK_CALLED(Stream_Read);
694 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
695 state = STATE_STARTDOWNLOADING;
696 break;
697 case STATE_STARTDOWNLOADING:
698 if(!security_problem) {
699 state = STATE_DOWNLOADING;
700 if((tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST)
701 && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))) {
702 CHECK_CALLED(OnResponse);
703 if(tested_protocol == HTTPS_TEST || empty_file)
704 CHECK_CALLED(ReportProgress_ACCEPTRANGES);
705 else if(test_redirect || test_abort)
706 CLEAR_CALLED(ReportProgress_ACCEPTRANGES);
707 CLEAR_CALLED(ReportProgress_ENCODING);
708 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
709 if(bindf & BINDF_NEEDFILE)
710 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
711 }
712 }
713 else
714 {
715 security_problem = FALSE;
716 SET_EXPECT(ReportProgress_CONNECTING);
717 }
718 default:
719 break;
720 }
721 }
722
723 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
724 {
725 if(tested_protocol == FTP_TEST)
726 CHECK_EXPECT2(Switch);
727 else
728 CHECK_EXPECT(Switch);
729
730 ok(pProtocolData != NULL, "pProtocolData == NULL\n");
731 if(binding_test) {
732 ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
733 ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
734 pProtocolData->grfFlags, protocoldata.grfFlags );
735 ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
736 pProtocolData->dwState, protocoldata.dwState );
737 ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
738 pProtocolData->pData, protocoldata.pData );
739 ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
740 pProtocolData->cbData, protocoldata.cbData );
741 }
742
743 pdata = pProtocolData;
744
745 if(binding_test) {
746 SetEvent(event_complete);
747 ok( WaitForSingleObject(event_complete2, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
748 return S_OK;
749 }if(direct_read) {
750 continue_protdata = *pProtocolData;
751 SetEvent(event_continue);
752 ok( WaitForSingleObject(event_continue_done, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
753 }else {
754 call_continue(pProtocolData);
755 SetEvent(event_complete);
756 }
757
758 return S_OK;
759 }
760
761 static const char *status_names[] =
762 {
763 "0",
764 "FINDINGRESOURCE",
765 "CONNECTING",
766 "REDIRECTING",
767 "BEGINDOWNLOADDATA",
768 "DOWNLOADINGDATA",
769 "ENDDOWNLOADDATA",
770 "BEGINDOWNLOADCOMPONENTS",
771 "INSTALLINGCOMPONENTS",
772 "ENDDOWNLOADCOMPONENTS",
773 "USINGCACHEDCOPY",
774 "SENDINGREQUEST",
775 "CLASSIDAVAILABLE",
776 "MIMETYPEAVAILABLE",
777 "CACHEFILENAMEAVAILABLE",
778 "BEGINSYNCOPERATION",
779 "ENDSYNCOPERATION",
780 "BEGINUPLOADDATA",
781 "UPLOADINGDATA",
782 "ENDUPLOADINGDATA",
783 "PROTOCOLCLASSID",
784 "ENCODING",
785 "VERIFIEDMIMETYPEAVAILABLE",
786 "CLASSINSTALLLOCATION",
787 "DECODING",
788 "LOADINGMIMEHANDLER",
789 "CONTENTDISPOSITIONATTACH",
790 "FILTERREPORTMIMETYPE",
791 "CLSIDCANINSTANTIATE",
792 "IUNKNOWNAVAILABLE",
793 "DIRECTBIND",
794 "RAWMIMETYPE",
795 "PROXYDETECTING",
796 "ACCEPTRANGES",
797 "COOKIE_SENT",
798 "COMPACT_POLICY_RECEIVED",
799 "COOKIE_SUPPRESSED",
800 "COOKIE_STATE_UNKNOWN",
801 "COOKIE_STATE_ACCEPT",
802 "COOKIE_STATE_REJECT",
803 "COOKIE_STATE_PROMPT",
804 "COOKIE_STATE_LEASH",
805 "COOKIE_STATE_DOWNGRADE",
806 "POLICY_HREF",
807 "P3P_HEADER",
808 "SESSION_COOKIE_RECEIVED",
809 "PERSISTENT_COOKIE_RECEIVED",
810 "SESSION_COOKIES_ALLOWED",
811 "CACHECONTROL",
812 "CONTENTDISPOSITIONFILENAME",
813 "MIMETEXTPLAINMISMATCH",
814 "PUBLISHERAVAILABLE",
815 "DISPLAYNAMEAVAILABLE"
816 };
817
818 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
819 LPCWSTR szStatusText)
820 {
821 static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
822 '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
823 static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
824
825 if (winetest_debug > 1)
826 {
827 if (ulStatusCode < ARRAY_SIZE(status_names))
828 trace( "progress: %s %s\n", status_names[ulStatusCode], wine_dbgstr_w(szStatusText) );
829 else
830 trace( "progress: %u %s\n", ulStatusCode, wine_dbgstr_w(szStatusText) );
831 }
832
833 switch(ulStatusCode) {
834 case BINDSTATUS_MIMETYPEAVAILABLE:
835 CHECK_EXPECT2(ReportProgress_MIMETYPEAVAILABLE);
836 if(tested_protocol != FILE_TEST && tested_protocol != ITS_TEST && !mimefilter_test && (pi & PI_MIMEVERIFICATION)) {
837 if(!short_read || !direct_read)
838 CHECK_CALLED(Read); /* set in Continue */
839 else if(short_read)
840 CHECK_CALLED(Read2); /* set in Read */
841 }
842 ok(szStatusText != NULL, "szStatusText == NULL\n");
843 if(szStatusText) {
844 if(tested_protocol == BIND_TEST)
845 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText %s\n", wine_dbgstr_w(szStatusText));
846 else if (http_post_test)
847 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
848 !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
849 "szStatusText != text/plain\n");
850 else if(empty_file)
851 ok(!strcmp_wa(szStatusText, "application/javascript"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
852 else if((pi & PI_MIMEVERIFICATION) && emulate_prot && !mimefilter_test
853 && tested_protocol==HTTP_TEST && !short_read)
854 ok(lstrlenW(gifW) <= lstrlenW(szStatusText) &&
855 !memcmp(szStatusText, gifW, lstrlenW(gifW)*sizeof(WCHAR)),
856 "szStatusText != image/gif\n");
857 else if(!mimefilter_test)
858 ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) &&
859 !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
860 "szStatusText != text/html\n");
861 }
862 break;
863 case BINDSTATUS_DIRECTBIND:
864 CHECK_EXPECT2(ReportProgress_DIRECTBIND);
865 ok(szStatusText == NULL, "szStatusText != NULL\n");
866 break;
867 case BINDSTATUS_RAWMIMETYPE:
868 CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
869 ok(szStatusText != NULL, "szStatusText == NULL\n");
870 if(szStatusText)
871 ok(lstrlenW(szStatusText) < lstrlenW(text_htmlW) ||
872 !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
873 "szStatusText != text/html\n");
874 break;
875 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
876 CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
877 ok(szStatusText != NULL, "szStatusText == NULL\n");
878 if(szStatusText) {
879 if(binding_test)
880 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText\n");
881 else if(tested_protocol == FILE_TEST)
882 ok(!lstrcmpW(szStatusText, file_name), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
883 else
884 ok(szStatusText != NULL, "szStatusText == NULL\n");
885 }
886 break;
887 case BINDSTATUS_FINDINGRESOURCE:
888 CHECK_EXPECT2(ReportProgress_FINDINGRESOURCE);
889 ok(szStatusText != NULL, "szStatusText == NULL\n");
890 break;
891 case BINDSTATUS_CONNECTING:
892 CHECK_EXPECT2(ReportProgress_CONNECTING);
893 ok(szStatusText != NULL, "szStatusText == NULL\n");
894 break;
895 case BINDSTATUS_SENDINGREQUEST:
896 CHECK_EXPECT2(ReportProgress_SENDINGREQUEST);
897 if(tested_protocol == FILE_TEST || tested_protocol == ITS_TEST) {
898 ok(szStatusText != NULL, "szStatusText == NULL\n");
899 if(szStatusText)
900 ok(!*szStatusText, "wrong szStatusText\n");
901 }
902 break;
903 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
904 CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
905 ok(szStatusText != NULL, "szStatusText == NULL\n");
906 if(szStatusText)
907 ok(!strcmp_wa(szStatusText, "text/html"), "szStatusText != text/html\n");
908 break;
909 case BINDSTATUS_PROTOCOLCLASSID:
910 CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
911 ok(szStatusText != NULL, "szStatusText == NULL\n");
912 ok(!lstrcmpW(szStatusText, null_guid), "unexpected classid %s\n", wine_dbgstr_w(szStatusText));
913 break;
914 case BINDSTATUS_COOKIE_SENT:
915 CHECK_EXPECT2(ReportProgress_COOKIE_SENT);
916 ok(szStatusText == NULL, "szStatusText != NULL\n");
917 break;
918 case BINDSTATUS_REDIRECTING:
919 CHECK_EXPECT(ReportProgress_REDIRECTING);
920 if(test_redirect)
921 ok(!strcmp_wa(szStatusText, "http://test.winehq.org/tests/hello.html"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
922 else
923 ok(szStatusText == NULL, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
924 break;
925 case BINDSTATUS_ENCODING:
926 CHECK_EXPECT(ReportProgress_ENCODING);
927 ok(!strcmp_wa(szStatusText, "gzip"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
928 break;
929 case BINDSTATUS_ACCEPTRANGES:
930 CHECK_EXPECT(ReportProgress_ACCEPTRANGES);
931 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
932 break;
933 case BINDSTATUS_PROXYDETECTING:
934 if(!called_ReportProgress_PROXYDETECTING)
935 SET_EXPECT(ReportProgress_CONNECTING);
936 CHECK_EXPECT2(ReportProgress_PROXYDETECTING);
937 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
938 break;
939 case BINDSTATUS_LOADINGMIMEHANDLER:
940 CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
941 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
942 break;
943 case BINDSTATUS_DECODING:
944 CHECK_EXPECT(ReportProgress_DECODING);
945 ok(!lstrcmpW(szStatusText, pjpegW), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
946 break;
947 case BINDSTATUS_RESERVED_7:
948 trace("BINDSTATUS_RESERVED_7\n");
949 break;
950 case BINDSTATUS_RESERVED_8:
951 trace("BINDSTATUS_RESERVED_8\n");
952 break;
953 default:
954 ok(0, "Unexpected status %d (%d)\n", ulStatusCode, ulStatusCode-BINDSTATUS_LAST);
955 };
956
957 return S_OK;
958 }
959
960 static void test_http_info(IInternetProtocol *protocol)
961 {
962 IWinInetHttpInfo *info;
963 char buf[1024];
964 DWORD size, len;
965 HRESULT hres;
966
967 static const WCHAR connectionW[] = {'c','o','n','n','e','c','t','i','o','n',0};
968
969 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&info);
970 ok(hres == S_OK, "Could not get IWinInterHttpInfo iface: %08x\n", hres);
971
972 size = sizeof(buf);
973 strcpy(buf, "connection");
974 hres = IWinInetHttpInfo_QueryInfo(info, HTTP_QUERY_CUSTOM, buf, &size, NULL, NULL);
975 if(tested_protocol != FTP_TEST) {
976 ok(hres == S_OK, "QueryInfo failed: %08x\n", hres);
977
978 ok(!strcmp(buf, "Keep-Alive"), "buf = %s\n", buf);
979 len = strlen(buf);
980 ok(size == len, "size = %u, expected %u\n", size, len);
981
982 size = sizeof(buf);
983 memcpy(buf, connectionW, sizeof(connectionW));
984 hres = IWinInetHttpInfo_QueryInfo(info, HTTP_QUERY_CUSTOM, buf, &size, NULL, NULL);
985 ok(hres == S_FALSE, "QueryInfo returned %08x\n", hres);
986 }else {
987 ok(hres == S_FALSE, "QueryInfo failed: %08x\n", hres);
988 }
989
990 IWinInetHttpInfo_Release(info);
991 }
992
993 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
994 ULONG ulProgress, ULONG ulProgressMax)
995 {
996 HRESULT hres;
997
998 static int rec_depth;
999 rec_depth++;
1000
1001 if(!mimefilter_test && (tested_protocol == FILE_TEST || tested_protocol == ITS_TEST)) {
1002 CHECK_EXPECT2(ReportData);
1003
1004 ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
1005 ulProgress, ulProgressMax);
1006 if(!file_with_hash)
1007 ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
1008 /* BSCF_SKIPDRAINDATAFORFILEURLS added in IE8 */
1009 if(tested_protocol == FILE_TEST)
1010 ok((grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION)) ||
1011 (grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_SKIPDRAINDATAFORFILEURLS)),
1012 "grcfBSCF = %08x\n", grfBSCF);
1013 else
1014 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
1015 }else if(bind_from_cache) {
1016 CHECK_EXPECT(ReportData);
1017
1018 ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
1019 ok(ulProgress == 1000, "ulProgress = %u\n", ulProgress);
1020 ok(!ulProgressMax, "ulProgressMax = %u\n", ulProgressMax);
1021 }else if(direct_read) {
1022 BYTE buf[14096];
1023 ULONG read;
1024
1025 if(!read_report_data && rec_depth == 1) {
1026 BOOL reported_all_data = called_ReportData2;
1027
1028 CHECK_EXPECT2(ReportData);
1029
1030 if(short_read) {
1031 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE)
1032 || grfBSCF == BSCF_FIRSTDATANOTIFICATION, /* < IE8 */
1033 "grcfBSCF = %08x\n", grfBSCF);
1034 CHECK_CALLED(Read); /* Set in Continue */
1035 first_data_notif = FALSE;
1036 }else if(first_data_notif) {
1037 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
1038 first_data_notif = FALSE;
1039 }else if(reported_all_data) {
1040 ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION),
1041 "grcfBSCF = %08x\n", grfBSCF);
1042 }else if(!direct_read) {
1043 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
1044 }
1045
1046 do {
1047 read = 0;
1048 if(emulate_prot)
1049 SET_EXPECT(Read);
1050 else
1051 SET_EXPECT(ReportData2);
1052 SET_EXPECT(ReportResult);
1053 if(!emulate_prot)
1054 SET_EXPECT(Switch);
1055 hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
1056 ok(hres == E_PENDING || hres == S_FALSE || hres == S_OK, "Read failed: %08x\n", hres);
1057 if(hres == S_OK)
1058 ok(read, "read == 0\n");
1059 if(reported_all_data)
1060 ok(hres == S_FALSE, "Read failed: %08x, expected S_FALSE\n", hres);
1061 if(!emulate_prot && hres != E_PENDING)
1062 CHECK_NOT_CALLED(Switch); /* otherwise checked in wait_for_switch loop */
1063 if(emulate_prot)
1064 CHECK_CALLED(Read);
1065 if(!reported_all_data && called_ReportData2) {
1066 if(!emulate_prot)
1067 CHECK_CALLED(ReportData2);
1068 CHECK_CALLED(ReportResult);
1069 reported_all_data = TRUE;
1070 }else {
1071 if(!emulate_prot)
1072 CHECK_NOT_CALLED(ReportData2);
1073 CHECK_NOT_CALLED(ReportResult);
1074 }
1075 }while(hres == S_OK);
1076 if(hres == S_FALSE)
1077 wait_for_switch = FALSE;
1078 }else {
1079 CHECK_EXPECT(ReportData2);
1080
1081 ok(grfBSCF & BSCF_LASTDATANOTIFICATION, "grfBSCF = %08x\n", grfBSCF);
1082
1083 read = 0xdeadbeef;
1084 if(emulate_prot)
1085 SET_EXPECT(Read2);
1086 hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
1087 if(emulate_prot)
1088 CHECK_CALLED(Read2);
1089 ok(hres == S_FALSE, "Read returned: %08x, expected E_FALSE\n", hres);
1090 ok(!read, "read = %d\n", read);
1091 }
1092 }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST
1093 || tested_protocol == FTP_TEST)) {
1094 if(empty_file)
1095 CHECK_EXPECT2(ReportData);
1096 else if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
1097 CHECK_EXPECT(ReportData);
1098 else if (http_post_test)
1099 ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
1100
1101 if(empty_file) {
1102 ok(!ulProgress, "ulProgress = %d\n", ulProgress);
1103 ok(!ulProgressMax, "ulProgressMax = %d\n", ulProgressMax);
1104 }else {
1105 ok(ulProgress, "ulProgress == 0\n");
1106 }
1107
1108 if(empty_file) {
1109 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION),
1110 "grcfBSCF = %08x\n", grfBSCF);
1111 first_data_notif = FALSE;
1112 }else if(first_data_notif) {
1113 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
1114 || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
1115 "grcfBSCF = %08x\n", grfBSCF);
1116 first_data_notif = FALSE;
1117 } else {
1118 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
1119 || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
1120 || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
1121 "grcfBSCF = %08x\n", grfBSCF);
1122 }
1123
1124 if((grfBSCF & BSCF_FIRSTDATANOTIFICATION) && !binding_test)
1125 test_http_info(async_protocol);
1126
1127 if(!(bindf & BINDF_FROMURLMON) &&
1128 !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
1129 if(state == STATE_CONNECTING) {
1130 state = STATE_DOWNLOADING;
1131 if(http_is_first) {
1132 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1133 CHECK_CALLED(ReportProgress_CONNECTING);
1134 }
1135 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1136 CHECK_CALLED(OnResponse);
1137 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
1138 }
1139 SetEvent(event_complete);
1140 }
1141 }else if(!read_report_data) {
1142 BYTE buf[1000];
1143 ULONG read;
1144 HRESULT hres;
1145
1146 CHECK_EXPECT(ReportData);
1147
1148 if(tested_protocol != BIND_TEST) {
1149 do {
1150 if(mimefilter_test)
1151 SET_EXPECT(MimeFilter_Read);
1152 else if(rec_depth > 1)
1153 SET_EXPECT(Read2);
1154 else
1155 SET_EXPECT(Read);
1156 hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
1157 if(mimefilter_test)
1158 CHECK_CALLED(MimeFilter_Read);
1159 else if(rec_depth > 1)
1160 CHECK_CALLED(Read2);
1161 else
1162 CHECK_CALLED(Read);
1163 }while(hres == S_OK);
1164 }
1165 }
1166
1167 rec_depth--;
1168 return S_OK;
1169 }
1170
1171 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1172 DWORD dwError, LPCWSTR szResult)
1173 {
1174 CHECK_EXPECT(ReportResult);
1175
1176 if(security_problem)
1177 return S_OK;
1178
1179 if(tested_protocol == FTP_TEST)
1180 ok(hrResult == E_PENDING || hrResult == S_OK, "hrResult = %08x, expected E_PENDING or S_OK\n", hrResult);
1181 else
1182 ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
1183 hrResult, expect_hrResult);
1184 #ifdef __REACTOS__
1185 if(!winetest_interactive && tested_protocol != FTP_TEST && hrResult != expect_hrResult) {
1186 skip("CORE-10360/ROSTESTS-192: Test might hang, skipping the rest!\n");
1187 exit(1);
1188 }
1189 #endif
1190 if(SUCCEEDED(hrResult) || tested_protocol == FTP_TEST || test_abort || hrResult == INET_E_REDIRECT_FAILED)
1191 ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
1192 else
1193 ok(dwError != ERROR_SUCCESS ||
1194 broken(tested_protocol == MK_TEST), /* WinME and NT4 */
1195 "dwError == ERROR_SUCCESS\n");
1196
1197 if(hrResult == INET_E_REDIRECT_FAILED)
1198 ok(!strcmp_wa(szResult, "http://test.winehq.org/tests/hello.html"), "szResult = %s\n", wine_dbgstr_w(szResult));
1199 else
1200 ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1201
1202 if(direct_read)
1203 SET_EXPECT(ReportData); /* checked after main loop */
1204
1205 return S_OK;
1206 }
1207
1208 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
1209 ProtocolSink_QueryInterface,
1210 ProtocolSink_AddRef,
1211 ProtocolSink_Release,
1212 ProtocolSink_Switch,
1213 ProtocolSink_ReportProgress,
1214 ProtocolSink_ReportData,
1215 ProtocolSink_ReportResult
1216 };
1217
1218 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
1219
1220 static HRESULT WINAPI MimeProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
1221 {
1222 if(IsEqualGUID(&IID_IUnknown, riid)
1223 || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
1224 *ppv = iface;
1225 return S_OK;
1226 }
1227
1228 ok(0, "unexpected call\n");
1229 return E_NOTIMPL;
1230 }
1231
1232 static ULONG WINAPI MimeProtocolSink_AddRef(IInternetProtocolSink *iface)
1233 {
1234 return 2;
1235 }
1236
1237 static ULONG WINAPI MimeProtocolSink_Release(IInternetProtocolSink *iface)
1238 {
1239 return 1;
1240 }
1241
1242 static HRESULT WINAPI MimeProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
1243 {
1244 HRESULT hres;
1245
1246 CHECK_EXPECT(MimeFilter_Switch);
1247
1248 SET_EXPECT(Switch);
1249 hres = IInternetProtocolSink_Switch(filtered_sink, pProtocolData);
1250 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1251 CHECK_CALLED(Switch);
1252
1253 return S_OK;
1254 }
1255
1256 static HRESULT WINAPI MimeProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
1257 LPCWSTR szStatusText)
1258 {
1259 switch(ulStatusCode) {
1260 case BINDSTATUS_LOADINGMIMEHANDLER:
1261 /*
1262 * IE9 for some reason (bug?) calls this on mime handler's protocol sink instead of the
1263 * main protocol sink. We check ReportProgress_LOADINGMIMEHANDLER both here and in
1264 * ProtocolSink_ReportProgress to workaround it.
1265 */
1266 CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1267 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
1268 break;
1269 default:
1270 ok(0, "Unexpected status code %d\n", ulStatusCode);
1271 }
1272
1273 return S_OK;
1274 }
1275
1276 static HRESULT WINAPI MimeProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
1277 ULONG ulProgress, ULONG ulProgressMax)
1278 {
1279 DWORD read = 0;
1280 BYTE buf[8192];
1281 HRESULT hres;
1282 BOOL report_mime = FALSE;
1283
1284 CHECK_EXPECT(MimeFilter_ReportData);
1285
1286 if(!filter_state && !no_mime) {
1287 SET_EXPECT(Read);
1288 hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
1289 if(tested_protocol == HTTP_TEST)
1290 ok(hres == S_OK || hres == E_PENDING || hres == S_FALSE, "Read failed: %08x\n", hres);
1291 else
1292 ok(hres == S_OK, "Read failed: %08x\n", hres);
1293 CHECK_CALLED(Read);
1294
1295 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1296 hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, text_htmlW);
1297 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1298 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1299
1300 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1301 hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW);
1302 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1303 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1304
1305 /* FIXME: test BINDSTATUS_CACHEFILENAMEAVAILABLE */
1306 }
1307
1308 if(no_mime && prot_read<200) {
1309 SET_EXPECT(Read);
1310 }else if(no_mime && prot_read<300) {
1311 report_mime = TRUE;
1312 SET_EXPECT(Read);
1313 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1314 SET_EXPECT(ReportData);
1315 }else if(!read_report_data) {
1316 SET_EXPECT(ReportData);
1317 }
1318 hres = IInternetProtocolSink_ReportData(filtered_sink, grfBSCF, ulProgress, ulProgressMax);
1319 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1320 if(no_mime && prot_read<=200) {
1321 CHECK_CALLED(Read);
1322 }else if(report_mime) {
1323 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1324 CHECK_CALLED(ReportData);
1325 }else if(!read_report_data) {
1326 CHECK_CALLED(ReportData);
1327 }
1328
1329 if(!filter_state)
1330 filter_state = 1;
1331
1332 return S_OK;
1333 }
1334
1335 static HRESULT WINAPI MimeProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1336 DWORD dwError, LPCWSTR szResult)
1337 {
1338 HRESULT hres;
1339
1340 CHECK_EXPECT(MimeFilter_ReportResult);
1341
1342 ok(hrResult == S_OK, "hrResult = %08x\n", hrResult);
1343 ok(dwError == ERROR_SUCCESS, "dwError = %u\n", dwError);
1344 ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1345
1346 SET_EXPECT(ReportResult);
1347 hres = IInternetProtocolSink_ReportResult(filtered_sink, hrResult, dwError, szResult);
1348 ok(SUCCEEDED(hres), "ReportResult failed: %08x\n", hres);
1349 CHECK_CALLED(ReportResult);
1350
1351 return S_OK;
1352 }
1353
1354 static IInternetProtocolSinkVtbl mime_protocol_sink_vtbl = {
1355 MimeProtocolSink_QueryInterface,
1356 MimeProtocolSink_AddRef,
1357 MimeProtocolSink_Release,
1358 MimeProtocolSink_Switch,
1359 MimeProtocolSink_ReportProgress,
1360 MimeProtocolSink_ReportData,
1361 MimeProtocolSink_ReportResult
1362 };
1363
1364 static IInternetProtocolSink mime_protocol_sink = { &mime_protocol_sink_vtbl };
1365
1366 static HRESULT QueryInterface(REFIID riid, void **ppv)
1367 {
1368 static const IID IID_undocumented = {0x58DFC7D0,0x5381,0x43E5,{0x9D,0x72,0x4C,0xDD,0xE4,0xCB,0x0F,0x1A}};
1369 static const IID IID_undocumentedIE10 = {0xc28722e5,0xbc1a,0x4c55,{0xa6,0x8d,0x33,0x21,0x9f,0x69,0x89,0x10}};
1370
1371 *ppv = NULL;
1372
1373 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
1374 *ppv = &protocol_sink;
1375 if(IsEqualGUID(&IID_IServiceProvider, riid))
1376 *ppv = &service_provider;
1377 if(IsEqualGUID(&IID_IUriContainer, riid))
1378 return E_NOINTERFACE; /* TODO */
1379
1380 /* NOTE: IE8 queries for undocumented {58DFC7D0-5381-43E5-9D72-4CDDE4CB0F1A} interface. */
1381 if(IsEqualGUID(&IID_undocumented, riid))
1382 return E_NOINTERFACE;
1383 /* NOTE: IE10 queries for undocumented {c28722e5-bc1a-4c55-a68d-33219f698910} interface. */
1384 if(IsEqualGUID(&IID_undocumentedIE10, riid))
1385 return E_NOINTERFACE;
1386
1387 if(*ppv)
1388 return S_OK;
1389
1390 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
1391 return E_NOINTERFACE;
1392 }
1393
1394 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
1395 {
1396 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
1397 *ppv = iface;
1398 return S_OK;
1399 }
1400 return E_NOINTERFACE;
1401 }
1402
1403 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
1404 {
1405 return 2;
1406 }
1407
1408 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
1409 {
1410 return 1;
1411 }
1412
1413 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
1414 {
1415 DWORD cbSize;
1416
1417 CHECK_EXPECT(GetBindInfo);
1418
1419 ok(grfBINDF != NULL, "grfBINDF == NULL\n");
1420 ok(pbindinfo != NULL, "pbindinfo == NULL\n");
1421 ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
1422
1423 *grfBINDF = bindf;
1424 if(binding_test)
1425 *grfBINDF |= BINDF_FROMURLMON;
1426 cbSize = pbindinfo->cbSize;
1427 memset(pbindinfo, 0, cbSize);
1428 pbindinfo->cbSize = cbSize;
1429 pbindinfo->dwOptions = bindinfo_options;
1430
1431 if(http_post_test)
1432 {
1433 pbindinfo->cbstgmedData = sizeof(post_data)-1;
1434 pbindinfo->dwBindVerb = BINDVERB_POST;
1435 pbindinfo->stgmedData.tymed = http_post_test;
1436
1437 if(http_post_test == TYMED_HGLOBAL) {
1438 HGLOBAL data;
1439
1440 /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly */
1441 data = GlobalAlloc(GPTR, sizeof(post_data));
1442 memcpy(data, post_data, sizeof(post_data));
1443 U(pbindinfo->stgmedData).hGlobal = data;
1444 }else {
1445 U(pbindinfo->stgmedData).pstm = &Stream;
1446 }
1447 }
1448
1449 return S_OK;
1450 }
1451
1452 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
1453 LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1454 {
1455 ok(ppwzStr != NULL, "ppwzStr == NULL\n");
1456 ok(pcElFetched != NULL, "pcElFetched == NULL\n");
1457
1458 switch(ulStringType) {
1459 case BINDSTRING_ACCEPT_MIMES:
1460 CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
1461 ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
1462 if(pcElFetched) {
1463 ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
1464 *pcElFetched = 1;
1465 }
1466 if(ppwzStr) {
1467 *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
1468 memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
1469 }
1470 return S_OK;
1471 case BINDSTRING_USER_AGENT:
1472 CHECK_EXPECT(GetBindString_USER_AGENT);
1473 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1474 if(pcElFetched) {
1475 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1476 *pcElFetched = 1;
1477 }
1478 if(ppwzStr) {
1479 *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
1480 memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
1481 }
1482 return S_OK;
1483 case BINDSTRING_POST_COOKIE:
1484 CHECK_EXPECT(GetBindString_POST_COOKIE);
1485 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1486 if(pcElFetched)
1487 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1488 return S_OK;
1489 case BINDSTRING_URL: {
1490 DWORD size;
1491
1492 CHECK_EXPECT(GetBindString_URL);
1493 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1494 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1495 *pcElFetched = 1;
1496
1497 size = (lstrlenW(binding_urls[tested_protocol])+1)*sizeof(WCHAR);
1498 *ppwzStr = CoTaskMemAlloc(size);
1499 memcpy(*ppwzStr, binding_urls[tested_protocol], size);
1500 return S_OK;
1501 }
1502 case BINDSTRING_ROOTDOC_URL:
1503 CHECK_EXPECT(GetBindString_ROOTDOC_URL);
1504 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1505 return E_NOTIMPL;
1506 case BINDSTRING_ENTERPRISE_ID:
1507 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1508 return E_NOTIMPL;
1509 default:
1510 ok(0, "unexpected ulStringType %d\n", ulStringType);
1511 }
1512
1513 return E_NOTIMPL;
1514 }
1515
1516 static IInternetBindInfoVtbl bind_info_vtbl = {
1517 BindInfo_QueryInterface,
1518 BindInfo_AddRef,
1519 BindInfo_Release,
1520 BindInfo_GetBindInfo,
1521 BindInfo_GetBindString
1522 };
1523
1524 static IInternetBindInfo bind_info = { &bind_info_vtbl };
1525
1526 static Protocol *impl_from_IInternetPriority(IInternetPriority *iface)
1527 {
1528 return CONTAINING_RECORD(iface, Protocol, IInternetPriority_iface);
1529 }
1530
1531 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1532 REFIID riid, void **ppv)
1533 {
1534 ok(0, "unexpected call\n");
1535 return E_NOINTERFACE;
1536 }
1537
1538 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1539 {
1540 Protocol *This = impl_from_IInternetPriority(iface);
1541 This->outer_ref++;
1542 return IUnknown_AddRef(This->outer);
1543 }
1544
1545 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1546 {
1547 Protocol *This = impl_from_IInternetPriority(iface);
1548 This->outer_ref--;
1549 return IUnknown_Release(This->outer);
1550 }
1551
1552 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1553 {
1554 CHECK_EXPECT(SetPriority);
1555 ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
1556 return S_OK;
1557 }
1558
1559 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1560 {
1561 ok(0, "unexpected call\n");
1562 return E_NOTIMPL;
1563 }
1564
1565
1566 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1567 InternetPriority_QueryInterface,
1568 InternetPriority_AddRef,
1569 InternetPriority_Release,
1570 InternetPriority_SetPriority,
1571 InternetPriority_GetPriority
1572 };
1573
1574 static ULONG WINAPI Protocol_AddRef(IInternetProtocolEx *iface)
1575 {
1576 return 2;
1577 }
1578
1579 static ULONG WINAPI Protocol_Release(IInternetProtocolEx *iface)
1580 {
1581 return 1;
1582 }
1583
1584 static HRESULT WINAPI Protocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
1585 DWORD dwOptions)
1586 {
1587 HRESULT hres;
1588
1589 CHECK_EXPECT(Abort);
1590
1591 SET_EXPECT(ReportResult);
1592 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1593 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1594 CHECK_CALLED(ReportResult);
1595
1596 return S_OK;
1597 }
1598
1599 static HRESULT WINAPI Protocol_Suspend(IInternetProtocolEx *iface)
1600 {
1601 ok(0, "unexpected call\n");
1602 return E_NOTIMPL;
1603 }
1604
1605 static HRESULT WINAPI Protocol_Resume(IInternetProtocolEx *iface)
1606 {
1607 ok(0, "unexpected call\n");
1608 return E_NOTIMPL;
1609 }
1610
1611 static HRESULT WINAPI Protocol_Seek(IInternetProtocolEx *iface,
1612 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1613 {
1614 ok(0, "unexpected call\n");
1615 return E_NOTIMPL;
1616 }
1617
1618 static Protocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
1619 {
1620 return CONTAINING_RECORD(iface, Protocol, IInternetProtocolEx_iface);
1621 }
1622
1623 static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
1624 {
1625 Protocol *This = impl_from_IInternetProtocolEx(iface);
1626
1627 static const IID unknown_iid = {0x7daf9908,0x8415,0x4005,{0x95,0xae, 0xbd,0x27,0xf6,0xe3,0xdc,0x00}};
1628 static const IID unknown_iid2 = {0x5b7ebc0c,0xf630,0x4cea,{0x89,0xd3,0x5a,0xf0,0x38,0xed,0x05,0x5c}};
1629
1630 /* FIXME: Why is it calling here instead of outer IUnknown? */
1631 if(IsEqualGUID(riid, &IID_IInternetPriority)) {
1632 *ppv = &This->IInternetPriority_iface;
1633 IInternetPriority_AddRef(&This->IInternetPriority_iface);
1634 return S_OK;
1635 }
1636 if(!IsEqualGUID(riid, &unknown_iid) && !IsEqualGUID(riid, &unknown_iid2)) /* IE10 */
1637 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
1638 *ppv = NULL;
1639 return E_NOINTERFACE;
1640 }
1641
1642 static ULONG WINAPI ProtocolEmul_AddRef(IInternetProtocolEx *iface)
1643 {
1644 Protocol *This = impl_from_IInternetProtocolEx(iface);
1645 This->outer_ref++;
1646 return IUnknown_AddRef(This->outer);
1647 }
1648
1649 static ULONG WINAPI ProtocolEmul_Release(IInternetProtocolEx *iface)
1650 {
1651 Protocol *This = impl_from_IInternetProtocolEx(iface);
1652 This->outer_ref--;
1653 return IUnknown_Release(This->outer);
1654 }
1655
1656 static DWORD WINAPI thread_proc(PVOID arg)
1657 {
1658 BOOL redirect = redirect_on_continue;
1659 HRESULT hres;
1660
1661 memset(&protocoldata, -1, sizeof(protocoldata));
1662
1663 while(1) {
1664 prot_state = 0;
1665
1666 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1667 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1668 BINDSTATUS_FINDINGRESOURCE, hostW);
1669 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1670 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1671
1672 SET_EXPECT(ReportProgress_CONNECTING);
1673 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1674 BINDSTATUS_CONNECTING, winehq_ipW);
1675 CHECK_CALLED(ReportProgress_CONNECTING);
1676 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1677
1678 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1679 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1680 BINDSTATUS_SENDINGREQUEST, NULL);
1681 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1682 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1683
1684 prot_state = 1;
1685 SET_EXPECT(Switch);
1686 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1687 CHECK_CALLED(Switch);
1688 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1689
1690 if(!redirect)
1691 break;
1692 redirect = FALSE;
1693 }
1694
1695 if(!short_read) {
1696 prot_state = 2;
1697 if(mimefilter_test)
1698 SET_EXPECT(MimeFilter_Switch);
1699 else
1700 SET_EXPECT(Switch);
1701 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1702 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1703 if(mimefilter_test)
1704 CHECK_CALLED(MimeFilter_Switch);
1705 else
1706 CHECK_CALLED(Switch);
1707
1708 if(test_abort) {
1709 SetEvent(event_complete);
1710 return 0;
1711 }
1712
1713 prot_state = 2;
1714 if(mimefilter_test)
1715 SET_EXPECT(MimeFilter_Switch);
1716 else
1717 SET_EXPECT(Switch);
1718 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1719 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1720 if(mimefilter_test)
1721 CHECK_CALLED(MimeFilter_Switch);
1722 else
1723 CHECK_CALLED(Switch);
1724
1725 prot_state = 3;
1726 if(mimefilter_test)
1727 SET_EXPECT(MimeFilter_Switch);
1728 else
1729 SET_EXPECT(Switch);
1730 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1731 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1732 if(mimefilter_test)
1733 CHECK_CALLED(MimeFilter_Switch);
1734 else
1735 CHECK_CALLED(Switch);
1736 }
1737
1738 SetEvent(event_complete);
1739
1740 return 0;
1741 }
1742
1743 static void protocol_start(IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD pi)
1744 {
1745 BINDINFO bindinfo, exp_bindinfo;
1746 DWORD cbindf = 0;
1747 HRESULT hres;
1748
1749 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
1750 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
1751 ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
1752 ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
1753 ok(!pi, "pi = %x\n", pi);
1754
1755 if(binding_test)
1756 ok(pOIProtSink == binding_sink, "pOIProtSink != binding_sink\n");
1757
1758 memset(&bindinfo, 0, sizeof(bindinfo));
1759 bindinfo.cbSize = sizeof(bindinfo);
1760 memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
1761 if(test_redirect)
1762 exp_bindinfo.dwOptions = bindinfo_options;
1763 SET_EXPECT(GetBindInfo);
1764 if(redirect_on_continue && (bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
1765 SET_EXPECT(QueryService_IBindCallbackRedirect);
1766 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
1767 if(redirect_on_continue && (bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
1768 CHECK_CALLED(QueryService_IBindCallbackRedirect);
1769 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
1770 CHECK_CALLED(GetBindInfo);
1771 ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
1772 cbindf, (bindf|BINDF_FROMURLMON));
1773 ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
1774 pReleaseBindInfo(&bindinfo);
1775
1776 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1777 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
1778 ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
1779 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1780
1781 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
1782 IServiceProvider *service_provider;
1783 IHttpNegotiate *http_negotiate;
1784 IHttpNegotiate2 *http_negotiate2;
1785 LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
1786 LPWSTR additional_headers = NULL;
1787 BYTE sec_id[100];
1788 DWORD fetched = 0, size = 100;
1789 DWORD tid;
1790
1791 SET_EXPECT(GetBindString_USER_AGENT);
1792 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
1793 &ua, 1, &fetched);
1794 CHECK_CALLED(GetBindString_USER_AGENT);
1795 ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
1796 ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
1797 ok(ua != NULL, "ua = %p\n", ua);
1798 ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", wine_dbgstr_w(ua));
1799 CoTaskMemFree(ua);
1800
1801 fetched = 256;
1802 SET_EXPECT(GetBindString_ACCEPT_MIMES);
1803 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
1804 accept_mimes, 256, &fetched);
1805 CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1806
1807 ok(hres == S_OK,
1808 "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
1809 ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
1810 ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", wine_dbgstr_w(accept_mimes[0]));
1811 CoTaskMemFree(accept_mimes[0]);
1812
1813 hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
1814 (void**)&service_provider);
1815 ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
1816
1817 SET_EXPECT(QueryService_HttpNegotiate);
1818 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1819 &IID_IHttpNegotiate, (void**)&http_negotiate);
1820 CHECK_CALLED(QueryService_HttpNegotiate);
1821 ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1822
1823 SET_EXPECT(BeginningTransaction);
1824 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
1825 NULL, 0, &additional_headers);
1826 CHECK_CALLED(BeginningTransaction);
1827 IHttpNegotiate_Release(http_negotiate);
1828 ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
1829 ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
1830
1831 SET_EXPECT(QueryService_HttpNegotiate);
1832 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
1833 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
1834 CHECK_CALLED(QueryService_HttpNegotiate);
1835 ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1836
1837 size = 512;
1838 SET_EXPECT(GetRootSecurityId);
1839 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
1840 CHECK_CALLED(GetRootSecurityId);
1841 IHttpNegotiate2_Release(http_negotiate2);
1842 ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
1843 ok(size == 13, "size=%d\n", size);
1844
1845 IServiceProvider_Release(service_provider);
1846
1847 if(!reuse_protocol_thread)
1848 CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
1849 return;
1850 }
1851
1852 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1853 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
1854 BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1855 ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1856 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1857
1858 if(mimefilter_test) {
1859 SET_EXPECT(MimeFilter_CreateInstance);
1860 SET_EXPECT(MimeFilter_Start);
1861 SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1862 }
1863 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1864 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
1865 mimefilter_test ? pjpegW : (expect_wsz = text_htmlW));
1866 ok(hres == S_OK,
1867 "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
1868 if(mimefilter_test) {
1869 CHECK_CALLED(MimeFilter_CreateInstance);
1870 CHECK_CALLED(MimeFilter_Start);
1871 CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1872 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1873 }else {
1874 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1875 }
1876
1877 if(mimefilter_test)
1878 SET_EXPECT(MimeFilter_ReportData);
1879 else
1880 SET_EXPECT(ReportData);
1881 hres = IInternetProtocolSink_ReportData(pOIProtSink,
1882 BSCF_FIRSTDATANOTIFICATION | (tested_protocol == ITS_TEST ? BSCF_DATAFULLYAVAILABLE : BSCF_LASTDATANOTIFICATION),
1883 13, 13);
1884 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1885 if(mimefilter_test)
1886 CHECK_CALLED(MimeFilter_ReportData);
1887 else
1888 CHECK_CALLED(ReportData);
1889
1890 if(tested_protocol == ITS_TEST) {
1891 SET_EXPECT(ReportData);
1892 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
1893 ok(hres == S_OK, "ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres);
1894 CHECK_CALLED(ReportData);
1895 }
1896
1897 if(tested_protocol == BIND_TEST) {
1898 hres = IInternetProtocol_Terminate(binding_protocol, 0);
1899 ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
1900 }
1901
1902 if(mimefilter_test)
1903 SET_EXPECT(MimeFilter_ReportResult);
1904 else
1905 SET_EXPECT(ReportResult);
1906 hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
1907 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1908 if(mimefilter_test)
1909 CHECK_CALLED(MimeFilter_ReportResult);
1910 else
1911 CHECK_CALLED(ReportResult);
1912 }
1913
1914 static HRESULT WINAPI ProtocolEmul_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
1915 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1916 DWORD grfPI, HANDLE_PTR dwReserved)
1917 {
1918 CHECK_EXPECT(Start);
1919
1920 ok(!dwReserved, "dwReserved = %lx\n", dwReserved);
1921 protocol_start(pOIProtSink, pOIBindInfo, grfPI);
1922 return S_OK;
1923 }
1924
1925 static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocolEx *iface,
1926 PROTOCOLDATA *pProtocolData)
1927 {
1928 DWORD bscf = 0, pr;
1929 HRESULT hres;
1930
1931 CHECK_EXPECT(Continue);
1932
1933 ok(pProtocolData != NULL, "pProtocolData == NULL\n");
1934 if(!pProtocolData || tested_protocol == BIND_TEST)
1935 return S_OK;
1936 if(binding_test) {
1937 ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
1938 ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
1939 pProtocolData->grfFlags, protocoldata.grfFlags );
1940 ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
1941 pProtocolData->dwState, protocoldata.dwState );
1942 ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
1943 pProtocolData->pData, protocoldata.pData );
1944 ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
1945 pProtocolData->cbData, protocoldata.cbData );
1946 }
1947
1948 switch(prot_state) {
1949 case 1: {
1950 IServiceProvider *service_provider;
1951 IHttpNegotiate *http_negotiate;
1952 static const WCHAR header[] = {'?',0};
1953 static const WCHAR redirect_urlW[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',
1954 '/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
1955
1956 if(redirect_on_continue) {
1957 redirect_on_continue = FALSE;
1958 reuse_protocol_thread = TRUE;
1959
1960 if(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)
1961 SET_EXPECT(Redirect);
1962 SET_EXPECT(ReportProgress_REDIRECTING);
1963 SET_EXPECT(Terminate);
1964 SET_EXPECT(Protocol_destructor);
1965 SET_EXPECT(QueryService_InternetProtocol);
1966 SET_EXPECT(CreateInstance);
1967 SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
1968 SET_EXPECT(SetPriority);
1969 SET_EXPECT(Start);
1970 hres = IInternetProtocolSink_ReportResult(binding_sink, INET_E_REDIRECT_FAILED, ERROR_SUCCESS, redirect_urlW);
1971 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1972 if(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)
1973 CHECK_CALLED(Redirect);
1974 CHECK_CALLED(ReportProgress_REDIRECTING);
1975 CHECK_CALLED(Terminate);
1976 CHECK_CALLED(Protocol_destructor);
1977 CHECK_CALLED(QueryService_InternetProtocol);
1978 CHECK_CALLED(CreateInstance);
1979 CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
1980 todo_wine CHECK_NOT_CALLED(SetPriority);
1981 CHECK_CALLED(Start);
1982
1983 return S_OK;
1984 }
1985
1986 hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
1987 (void**)&service_provider);
1988 ok(hres == S_OK, "Could not get IServiceProvicder\n");
1989
1990 SET_EXPECT(QueryService_HttpNegotiate);
1991 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1992 &IID_IHttpNegotiate, (void**)&http_negotiate);
1993 IServiceProvider_Release(service_provider);
1994 CHECK_CALLED(QueryService_HttpNegotiate);
1995 ok(hres == S_OK, "Could not get IHttpNegotiate\n");
1996
1997 SET_EXPECT(OnResponse);
1998 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
1999 IHttpNegotiate_Release(http_negotiate);
2000 CHECK_CALLED(OnResponse);
2001 IHttpNegotiate_Release(http_negotiate);
2002 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
2003
2004 if(mimefilter_test) {
2005 SET_EXPECT(MimeFilter_CreateInstance);
2006 SET_EXPECT(MimeFilter_Start);
2007 SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
2008 }else if(!(pi & PI_MIMEVERIFICATION)) {
2009 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2010 }
2011 hres = IInternetProtocolSink_ReportProgress(binding_sink,
2012 BINDSTATUS_MIMETYPEAVAILABLE, mimefilter_test ? pjpegW : text_htmlW);
2013 if(mimefilter_test) {
2014 CHECK_CALLED(MimeFilter_CreateInstance);
2015 CHECK_CALLED(MimeFilter_Start);
2016 CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
2017 }else if(!(pi & PI_MIMEVERIFICATION)) {
2018 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2019 }
2020 ok(hres == S_OK,
2021 "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
2022
2023 bscf |= BSCF_FIRSTDATANOTIFICATION;
2024 break;
2025 }
2026 case 2:
2027 case 3:
2028 bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
2029 break;
2030 }
2031
2032 pr = prot_read;
2033 if(mimefilter_test)
2034 SET_EXPECT(MimeFilter_ReportData);
2035 if((!mimefilter_test || no_mime) && (pi & PI_MIMEVERIFICATION)) {
2036 if(pr < 200)
2037 SET_EXPECT(Read); /* checked in ReportData for short_read */
2038 if(pr == 200) {
2039 if(!mimefilter_test)
2040 SET_EXPECT(Read); /* checked in BINDSTATUS_MIMETYPEAVAILABLE or ReportData */
2041 SET_EXPECT(GetBindInfo);
2042 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2043 }
2044 if(pr >= 200)
2045 SET_EXPECT(ReportData);
2046 }else {
2047 SET_EXPECT(ReportData);
2048 }
2049
2050 hres = IInternetProtocolSink_ReportData(binding_sink, bscf, pr, 400);
2051 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2052
2053 if(mimefilter_test) {
2054 SET_EXPECT(MimeFilter_ReportData);
2055 }else if(pi & PI_MIMEVERIFICATION) {
2056 if(!short_read && pr < 200)
2057 CHECK_CALLED(Read);
2058 if(pr == 200) {
2059 CLEAR_CALLED(GetBindInfo); /* IE9 */
2060 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2061 }
2062 }else {
2063 CHECK_CALLED(ReportData);
2064 }
2065
2066 if(prot_state == 3)
2067 prot_state = 4;
2068
2069 return S_OK;
2070 }
2071
2072 static HRESULT WINAPI ProtocolEmul_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2073 {
2074 CHECK_EXPECT(Terminate);
2075 ok(!dwOptions, "dwOptions=%d\n", dwOptions);
2076 return S_OK;
2077 }
2078
2079 static HRESULT WINAPI ProtocolEmul_Read(IInternetProtocolEx *iface, void *pv,
2080 ULONG cb, ULONG *pcbRead)
2081 {
2082 if(read_report_data)
2083 CHECK_EXPECT2(Read2);
2084
2085 if(mimefilter_test || short_read) {
2086 if(!read_report_data)
2087 CHECK_EXPECT2(Read);
2088 }else if((pi & PI_MIMEVERIFICATION)) {
2089 if(!read_report_data)
2090 CHECK_EXPECT2(Read);
2091
2092 if(prot_read < 300) {
2093 ok(pv != expect_pv, "pv == expect_pv\n");
2094 if(prot_read < 300)
2095 ok(cb == 2048-prot_read, "cb=%d\n", cb);
2096 else
2097 ok(cb == 700, "cb=%d\n", cb);
2098 }else {
2099 ok(expect_pv <= pv && (BYTE*)pv < (BYTE*)expect_pv + cb, "pv != expect_pv\n");
2100 }
2101 }else {
2102 if(!read_report_data)
2103 CHECK_EXPECT(Read);
2104
2105 ok(pv == expect_pv, "pv != expect_pv\n");
2106 ok(cb == 1000, "cb=%d\n", cb);
2107 ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
2108 }
2109 ok(pcbRead != NULL, "pcbRead == NULL\n");
2110
2111 if(prot_state == 3 || (short_read && prot_state != 4)) {
2112 HRESULT hres;
2113
2114 prot_state = 4;
2115 if(short_read) {
2116 SET_EXPECT(Read2); /* checked in BINDSTATUS_MIMETYPEAVAILABLE */
2117 SET_EXPECT(GetBindInfo);
2118 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2119 }
2120 if(mimefilter_test)
2121 SET_EXPECT(MimeFilter_ReportData);
2122 else if(direct_read)
2123 SET_EXPECT(ReportData2);
2124 read_report_data++;
2125 hres = IInternetProtocolSink_ReportData(binding_sink,
2126 BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION, 0, 0);
2127 read_report_data--;
2128 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2129 if(short_read) {
2130 CLEAR_CALLED(GetBindInfo); /* IE9 */
2131 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2132 }
2133 if(mimefilter_test)
2134 CHECK_CALLED(MimeFilter_ReportData);
2135 else if(direct_read)
2136 CHECK_CALLED(ReportData2);
2137
2138 if(mimefilter_test)
2139 SET_EXPECT(MimeFilter_ReportResult);
2140 else
2141 SET_EXPECT(ReportResult);
2142 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
2143 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
2144 if(mimefilter_test)
2145 CHECK_CALLED(MimeFilter_ReportResult);
2146 else
2147 CHECK_CALLED(ReportResult);
2148
2149 if(cb > 100)
2150 cb = 100;
2151 memset(pv, 'x', cb);
2152 if(cb>6)
2153 memcpy(pv, "gif87a", 6);
2154 prot_read += *pcbRead = cb;
2155 return S_OK;
2156 }
2157
2158 if(prot_state == 4) {
2159 *pcbRead = 0;
2160 return S_FALSE;
2161 }
2162
2163 if((async_read_pending = !async_read_pending)) {
2164 *pcbRead = 0;
2165 return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
2166 }
2167
2168 if(cb > 100)
2169 cb = 100;
2170 memset(pv, 'x', cb);
2171 if(cb>6)
2172 memcpy(pv, "gif87a", 6);
2173 prot_read += *pcbRead = cb;
2174 return S_OK;
2175 }
2176
2177 static HRESULT WINAPI ProtocolEmul_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2178 {
2179 CHECK_EXPECT(LockRequest);
2180 ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
2181 return S_OK;
2182 }
2183
2184 static HRESULT WINAPI ProtocolEmul_UnlockRequest(IInternetProtocolEx *iface)
2185 {
2186 CHECK_EXPECT(UnlockRequest);
2187 return S_OK;
2188 }
2189
2190 static HRESULT WINAPI ProtocolEmul_StartEx(IInternetProtocolEx *iface, IUri *pUri,
2191 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2192 DWORD grfPI, HANDLE *dwReserved)
2193 {
2194 CHECK_EXPECT(StartEx);
2195 ok(!dwReserved, "dwReserved = %p\n", dwReserved);
2196 protocol_start(pOIProtSink, pOIBindInfo, grfPI);
2197 return S_OK;
2198 }
2199
2200 static const IInternetProtocolExVtbl ProtocolVtbl = {
2201 ProtocolEmul_QueryInterface,
2202 ProtocolEmul_AddRef,
2203 ProtocolEmul_Release,
2204 ProtocolEmul_Start,
2205 ProtocolEmul_Continue,
2206 Protocol_Abort,
2207 ProtocolEmul_Terminate,
2208 Protocol_Suspend,
2209 Protocol_Resume,
2210 ProtocolEmul_Read,
2211 Protocol_Seek,
2212 ProtocolEmul_LockRequest,
2213 ProtocolEmul_UnlockRequest,
2214 ProtocolEmul_StartEx
2215 };
2216
2217 static Protocol *impl_from_IUnknown(IUnknown *iface)
2218 {
2219 return CONTAINING_RECORD(iface, Protocol, IUnknown_inner);
2220 }
2221
2222 static HRESULT WINAPI ProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2223 {
2224 Protocol *This = impl_from_IUnknown(iface);
2225
2226 if(IsEqualGUID(&IID_IUnknown, riid)) {
2227 trace("QI(IUnknown)\n");
2228 *ppv = &This->IUnknown_inner;
2229 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
2230 trace("QI(InternetProtocol)\n");
2231 *ppv = &This->IInternetProtocolEx_iface;
2232 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
2233 trace("QI(InternetProtocolEx)\n");
2234 if(!impl_protex) {
2235 *ppv = NULL;
2236 return E_NOINTERFACE;
2237 }
2238 *ppv = &This->IInternetProtocolEx_iface;
2239 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
2240 trace("QI(InternetPriority)\n");
2241 *ppv = &This->IInternetPriority_iface;
2242 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
2243 trace("QI(IWinInetInfo)\n");
2244 CHECK_EXPECT(QueryInterface_IWinInetInfo);
2245 *ppv = NULL;
2246 return E_NOINTERFACE;
2247 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
2248 trace("QI(IWinInetHttpInfo)\n");
2249 CHECK_EXPECT(QueryInterface_IWinInetHttpInfo);
2250 *ppv = NULL;
2251 return E_NOINTERFACE;
2252 }else {
2253 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
2254 *ppv = NULL;
2255 return E_NOINTERFACE;
2256 }
2257
2258 IUnknown_AddRef((IUnknown*)*ppv);
2259 return S_OK;
2260 }
2261
2262 static ULONG WINAPI ProtocolUnk_AddRef(IUnknown *iface)
2263 {
2264 Protocol *This = impl_from_IUnknown(iface);
2265 return ++This->inner_ref;
2266 }
2267
2268 static ULONG WINAPI ProtocolUnk_Release(IUnknown *iface)
2269 {
2270 Protocol *This = impl_from_IUnknown(iface);
2271 LONG ref = --This->inner_ref;
2272 if(!ref) {
2273 /* IE9 is broken on redirects. It will cause -1 outer_ref on original protocol handler
2274 * and 1 on redirected handler. */
2275 ok(!This->outer_ref
2276 || broken(test_redirect && (This->outer_ref == -1 || This->outer_ref == 1)),
2277 "outer_ref = %d\n", This->outer_ref);
2278 if(This->outer_ref)
2279 trace("outer_ref %d\n", This->outer_ref);
2280 CHECK_EXPECT(Protocol_destructor);
2281 heap_free(This);
2282 }
2283 return ref;
2284 }
2285
2286 static const IUnknownVtbl ProtocolUnkVtbl = {
2287 ProtocolUnk_QueryInterface,
2288 ProtocolUnk_AddRef,
2289 ProtocolUnk_Release
2290 };
2291
2292 static HRESULT WINAPI MimeProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
2293 {
2294 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
2295 *ppv = iface;
2296 return S_OK;
2297 }
2298
2299 if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
2300 *ppv = &mime_protocol_sink;
2301 return S_OK;
2302 }
2303
2304 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
2305 *ppv = NULL;
2306 return E_NOINTERFACE;
2307 }
2308
2309 static HRESULT WINAPI MimeProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
2310 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2311 DWORD grfPI, HANDLE_PTR dwReserved)
2312 {
2313 PROTOCOLFILTERDATA *data;
2314 LPOLESTR url_str = NULL;
2315 DWORD fetched = 0;
2316 BINDINFO bindinfo;
2317 DWORD cbindf = 0;
2318 HRESULT hres;
2319
2320 CHECK_EXPECT(MimeFilter_Start);
2321
2322 ok(!lstrcmpW(szUrl, pjpegW), "wrong url %s\n", wine_dbgstr_w(szUrl));
2323 ok(grfPI == (PI_FILTER_MODE|PI_FORCE_ASYNC), "grfPI=%x, expected PI_FILTER_MODE|PI_FORCE_ASYNC\n", grfPI);
2324 ok(dwReserved, "dwReserved == 0\n");
2325 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
2326 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
2327
2328 if(binding_test) {
2329 ok(pOIProtSink != binding_sink, "pOIProtSink == protocol_sink\n");
2330 ok(pOIBindInfo == prot_bind_info, "pOIBindInfo != bind_info\n");
2331 }else {
2332 ok(pOIProtSink == &protocol_sink, "pOIProtSink != protocol_sink\n");
2333 ok(pOIBindInfo == &bind_info, "pOIBindInfo != bind_info\n");
2334 }
2335
2336 data = (void*)dwReserved;
2337 ok(data->cbSize == sizeof(*data), "data->cbSize = %d\n", data->cbSize);
2338 ok(!data->pProtocolSink, "data->pProtocolSink != NULL\n");
2339 ok(data->pProtocol != NULL, "data->pProtocol == NULL\n");
2340 ok(!data->pUnk, "data->pUnk != NULL\n");
2341 ok(!data->dwFilterFlags, "data->dwProtocolFlags = %x\n", data->dwFilterFlags);
2342 if(binding_test) {
2343 IInternetProtocolSink *prot_sink;
2344
2345 IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocolSink, (void**)&prot_sink);
2346 ok(prot_sink == pOIProtSink, "QI(data->pProtocol, IID_IInternetProtocolSink) != pOIProtSink\n");
2347 IInternetProtocolSink_Release(prot_sink);
2348
2349 ok(data->pProtocol != binding_protocol, "data->pProtocol == binding_protocol\n");
2350
2351 filtered_protocol = data->pProtocol;
2352 IInternetProtocol_AddRef(filtered_protocol);
2353 }else {
2354 IInternetProtocol *prot;
2355
2356 IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocol, (void**)&prot);
2357 ok(prot == async_protocol, "QI(data->pProtocol, IID_IInternetProtocol) != async_protocol\n");
2358 IInternetProtocol_Release(prot);
2359
2360 ok(data->pProtocol != async_protocol, "data->pProtocol == async_protocol\n");
2361 }
2362
2363 filtered_sink = pOIProtSink;
2364
2365 SET_EXPECT(ReportProgress_DECODING);
2366 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DECODING, pjpegW);
2367 ok(hres == S_OK, "ReportProgress(BINDSTATUS_DECODING) failed: %08x\n", hres);
2368 CHECK_CALLED(ReportProgress_DECODING);
2369
2370 SET_EXPECT(GetBindInfo);
2371 memset(&bindinfo, 0, sizeof(bindinfo));
2372 bindinfo.cbSize = sizeof(bindinfo);
2373 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
2374 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
2375 ok(cbindf == (bindf|BINDF_FROMURLMON), "cbindf = %x, expected %x\n", cbindf, bindf);
2376 CHECK_CALLED(GetBindInfo);
2377
2378 SET_EXPECT(GetBindString_URL);
2379 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_URL, &url_str, 1, &fetched);
2380 ok(hres == S_OK, "GetBindString(BINDSTRING_URL) failed: %08x\n", hres);
2381 ok(fetched == 1, "fetched = %d\n", fetched);
2382 ok(!lstrcmpW(url_str, binding_urls[tested_protocol]), "wrong url_str %s\n", wine_dbgstr_w(url_str));
2383 CoTaskMemFree(url_str);
2384 CHECK_CALLED(GetBindString_URL);
2385
2386 return S_OK;
2387 }
2388
2389 static HRESULT WINAPI Protocol_Continue(IInternetProtocolEx *iface,
2390 PROTOCOLDATA *pProtocolData)
2391 {
2392 CHECK_EXPECT(MimeFilter_Continue);
2393 return E_NOTIMPL;
2394 }
2395
2396 static HRESULT WINAPI MimeProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2397 {
2398 HRESULT hres;
2399
2400 CHECK_EXPECT(MimeFilter_Terminate);
2401
2402 ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2403
2404 SET_EXPECT(Terminate);
2405 hres = IInternetProtocol_Terminate(filtered_protocol, dwOptions);
2406 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2407 CHECK_CALLED(Terminate);
2408
2409 return S_OK;
2410 }
2411
2412 static HRESULT WINAPI MimeProtocol_Read(IInternetProtocolEx *iface, void *pv,
2413 ULONG cb, ULONG *pcbRead)
2414 {
2415 BYTE buf[2096];
2416 DWORD read = 0;
2417 HRESULT hres;
2418
2419 CHECK_EXPECT(MimeFilter_Read);
2420
2421 ok(pv != NULL, "pv == NULL\n");
2422 ok(cb != 0, "cb == 0\n");
2423 ok(pcbRead != NULL, "pcbRead == NULL\n");
2424
2425 if(read_report_data)
2426 SET_EXPECT(Read2);
2427 else
2428 SET_EXPECT(Read);
2429 hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
2430 ok(hres == S_OK || hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
2431 if(read_report_data)
2432 CHECK_CALLED(Read2);
2433 else
2434 CHECK_CALLED(Read);
2435
2436 if(pcbRead) {
2437 ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
2438 *pcbRead = read;
2439 }
2440
2441 memset(pv, 'x', read);
2442 return hres;
2443 }
2444
2445 static HRESULT WINAPI MimeProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2446 {
2447 HRESULT hres;
2448
2449 CHECK_EXPECT(MimeFilter_LockRequest);
2450
2451 ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2452
2453 SET_EXPECT(LockRequest);
2454 hres = IInternetProtocol_LockRequest(filtered_protocol, dwOptions);
2455 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2456 CHECK_CALLED(LockRequest);
2457
2458 return S_OK;
2459 }
2460
2461 static HRESULT WINAPI MimeProtocol_UnlockRequest(IInternetProtocolEx *iface)
2462 {
2463 HRESULT hres;
2464
2465 CHECK_EXPECT(MimeFilter_UnlockRequest);
2466
2467 SET_EXPECT(UnlockRequest);
2468 hres = IInternetProtocol_UnlockRequest(filtered_protocol);
2469 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2470 CHECK_CALLED(UnlockRequest);
2471
2472 return S_OK;
2473 }
2474
2475 static const IInternetProtocolExVtbl MimeProtocolVtbl = {
2476 MimeProtocol_QueryInterface,
2477 Protocol_AddRef,
2478 Protocol_Release,
2479 MimeProtocol_Start,
2480 Protocol_Continue,
2481 Protocol_Abort,
2482 MimeProtocol_Terminate,
2483 Protocol_Suspend,
2484 Protocol_Resume,
2485 MimeProtocol_Read,
2486 Protocol_Seek,
2487 MimeProtocol_LockRequest,
2488 MimeProtocol_UnlockRequest
2489 };
2490
2491 static IInternetProtocolEx MimeProtocol = { &MimeProtocolVtbl };
2492
2493 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
2494 {
2495 ok(0, "unexpected call\n");
2496 return E_NOINTERFACE;
2497 }
2498
2499 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
2500 {
2501 return 2;
2502 }
2503
2504 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
2505 {
2506 return 1;
2507 }
2508
2509 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
2510 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
2511 DWORD *pcchResult, DWORD dwReserved)
2512 {
2513 ok(0, "unexpected call %d\n", ParseAction);
2514 return E_NOTIMPL;
2515 }
2516
2517 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
2518 LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
2519 LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
2520 {
2521 ok(0, "unexpected call\n");
2522 return E_NOTIMPL;
2523 }
2524
2525 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
2526 LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
2527 {
2528 ok(0, "unexpected call\n");
2529 return E_NOTIMPL;
2530 }
2531
2532 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
2533 LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
2534 DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
2535 {
2536 ok(0, "unexpected call\n");
2537 return E_NOTIMPL;
2538 }
2539
2540 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
2541 InternetProtocolInfo_QueryInterface,
2542 InternetProtocolInfo_AddRef,
2543 InternetProtocolInfo_Release,
2544 InternetProtocolInfo_ParseUrl,
2545 InternetProtocolInfo_CombineUrl,
2546 InternetProtocolInfo_CompareUrl,
2547 InternetProtocolInfo_QueryInfo
2548 };
2549
2550 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
2551
2552 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2553 {
2554 if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
2555 *ppv = &protocol_info;
2556 return S_OK;
2557 }
2558
2559 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
2560 return E_NOINTERFACE;
2561 }
2562
2563 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
2564 {
2565 return 2;
2566 }
2567
2568 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
2569 {
2570 return 1;
2571 }
2572
2573 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
2574 REFIID riid, void **ppv)
2575 {
2576 Protocol *ret;
2577
2578 CHECK_EXPECT(CreateInstance);
2579
2580 ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
2581 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2582 ok(ppv != NULL, "ppv == NULL\n");
2583
2584 ret = heap_alloc(sizeof(*ret));
2585 ret->IUnknown_inner.lpVtbl = &ProtocolUnkVtbl;
2586 ret->IInternetProtocolEx_iface.lpVtbl = &ProtocolVtbl;
2587 ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
2588 ret->outer = pOuter;
2589 ret->inner_ref = 1;
2590 ret->outer_ref = 0;
2591
2592 protocol_emul = ret;
2593 *ppv = &ret->IUnknown_inner;
2594 return S_OK;
2595 }
2596
2597 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
2598 {
2599 ok(0, "unexpected call\n");
2600 return S_OK;
2601 }
2602
2603 static const IClassFactoryVtbl ClassFactoryVtbl = {
2604 ClassFactory_QueryInterface,
2605 ClassFactory_AddRef,
2606 ClassFactory_Release,
2607 ClassFactory_CreateInstance,
2608 ClassFactory_LockServer
2609 };
2610
2611 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
2612
2613 static HRESULT WINAPI MimeFilter_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
2614 {
2615 CHECK_EXPECT(MimeFilter_CreateInstance);
2616
2617 ok(!outer, "outer = %p\n", outer);
2618 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2619
2620 *ppv = &MimeProtocol;
2621 return S_OK;
2622 }
2623
2624 static const IClassFactoryVtbl MimeFilterCFVtbl = {
2625 ClassFactory_QueryInterface,
2626 ClassFactory_AddRef,
2627 ClassFactory_Release,
2628 MimeFilter_CreateInstance,
2629 ClassFactory_LockServer
2630 };
2631
2632 static IClassFactory mimefilter_cf = { &MimeFilterCFVtbl };
2633
2634 #define TEST_BINDING 0x0001
2635 #define TEST_FILTER 0x0002
2636 #define TEST_FIRST_HTTP 0x0004
2637 #define TEST_DIRECT_READ 0x0008
2638 #define TEST_POST 0x0010
2639 #define TEST_EMULATEPROT 0x0020
2640 #define TEST_SHORT_READ 0x0040
2641 #define TEST_REDIRECT 0x0080
2642 #define TEST_ABORT 0x0100
2643 #define TEST_ASYNCREQ 0x0200
2644 #define TEST_USEIURI 0x0400
2645 #define TEST_IMPLPROTEX 0x0800
2646 #define TEST_EMPTY 0x1000
2647 #define TEST_NOMIME 0x2000
2648 #define TEST_FROMCACHE 0x4000
2649 #define TEST_DISABLEAUTOREDIRECT 0x8000
2650
2651 static void register_filter(BOOL do_register)
2652 {
2653 IInternetSession *session;
2654 HRESULT hres;
2655
2656 hres = pCoInternetGetSession(0, &session, 0);
2657 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2658
2659 if(do_register) {
2660 hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, pjpegW);
2661 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2662 hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, gifW);
2663 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2664 }else {
2665 hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, pjpegW);
2666 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2667 hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, gifW);
2668 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2669 }
2670
2671 IInternetSession_Release(session);
2672 }
2673
2674 static void init_test(int prot, DWORD flags)
2675 {
2676 tested_protocol = prot;
2677 binding_test = (flags & TEST_BINDING) != 0;
2678 first_data_notif = TRUE;
2679 prot_read = 0;
2680 prot_state = 0;
2681 async_read_pending = TRUE;
2682 mimefilter_test = (flags & TEST_FILTER) != 0;
2683 no_mime = (flags & TEST_NOMIME) != 0;
2684 filter_state = 0;
2685 post_stream_read = 0;
2686 ResetEvent(event_complete);
2687 ResetEvent(event_complete2);
2688 ResetEvent(event_continue);
2689 ResetEvent(event_continue_done);
2690 async_protocol = binding_protocol = filtered_protocol = NULL;
2691 filtered_sink = NULL;
2692 http_is_first = (flags & TEST_FIRST_HTTP) != 0;
2693 first_data_notif = TRUE;
2694 state = STATE_CONNECTING;
2695 test_async_req = (flags & TEST_ASYNCREQ) != 0;
2696 direct_read = (flags & TEST_DIRECT_READ) != 0;
2697 emulate_prot = (flags & TEST_EMULATEPROT) != 0;
2698 wait_for_switch = TRUE;
2699 short_read = (flags & TEST_SHORT_READ) != 0;
2700 http_post_test = TYMED_NULL;
2701 redirect_on_continue = test_redirect = (flags & TEST_REDIRECT) != 0;
2702 test_abort = (flags & TEST_ABORT) != 0;
2703 impl_protex = (flags & TEST_IMPLPROTEX) != 0;
2704 empty_file = (flags & TEST_EMPTY) != 0;
2705 bind_from_cache = (flags & TEST_FROMCACHE) != 0;
2706 file_with_hash = FALSE;
2707 security_problem = FALSE;
2708 reuse_protocol_thread = FALSE;
2709
2710 bindinfo_options = 0;
2711 if(flags & TEST_DISABLEAUTOREDIRECT)
2712 bindinfo_options |= BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS;
2713
2714 register_filter(mimefilter_test);
2715 }
2716
2717 static void test_priority(IInternetProtocol *protocol)
2718 {
2719 IInternetPriority *priority;
2720 LONG pr;
2721 HRESULT hres;
2722
2723 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
2724 (void**)&priority);
2725 ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
2726 if(FAILED(hres))
2727 return;
2728
2729 hres = IInternetPriority_GetPriority(priority, &pr);
2730 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2731 ok(pr == 0, "pr=%d, expected 0\n", pr);
2732
2733 hres = IInternetPriority_SetPriority(priority, 1);
2734 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2735
2736 hres = IInternetPriority_GetPriority(priority, &pr);
2737 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2738 ok(pr == 1, "pr=%d, expected 1\n", pr);
2739
2740 IInternetPriority_Release(priority);
2741 }
2742
2743 static void test_early_abort(const CLSID *clsid)
2744 {
2745 IInternetProtocol *protocol;
2746 HRESULT hres;
2747
2748 hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2749 &IID_IInternetProtocol, (void**)&protocol);
2750 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2751
2752 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
2753 ok(hres == S_OK, "Abort failed: %08x\n", hres);
2754
2755 hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
2756 ok(hres == S_OK, "Abort failed: %08x\n", hres);
2757
2758 IInternetProtocol_Release(protocol);
2759 }
2760
2761 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url,
2762 IInternetProtocolEx *protocolex, IUri *uri, BOOL is_first)
2763 {
2764 HRESULT hres;
2765
2766 SET_EXPECT(GetBindInfo);
2767 if(!(bindf & BINDF_FROMURLMON))
2768 SET_EXPECT(ReportProgress_DIRECTBIND);
2769 if(is_first) {
2770 SET_EXPECT(ReportProgress_SENDINGREQUEST);
2771 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
2772 if(bindf & BINDF_FROMURLMON)
2773 SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2774 else
2775 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2776 }
2777 SET_EXPECT(ReportData);
2778 if(is_first)
2779 SET_EXPECT(ReportResult);
2780
2781 expect_hrResult = S_OK;
2782
2783 if(protocolex) {
2784 hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
2785 ok(hres == S_OK, "StartEx failed: %08x\n", hres);
2786 }else {
2787 hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
2788 if(hres == INET_E_RESOURCE_NOT_FOUND) {
2789 win_skip("Start failed\n");
2790 return FALSE;
2791 }
2792 ok(hres == S_OK, "Start failed: %08x\n", hres);
2793 }
2794
2795 CHECK_CALLED(GetBindInfo);
2796 if(!(bindf & BINDF_FROMURLMON))
2797 CLEAR_CALLED(ReportProgress_DIRECTBIND); /* Not called by IE10 */
2798 if(is_first) {
2799 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2800 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
2801 if(bindf & BINDF_FROMURLMON)
2802 CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2803 else
2804 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2805 }
2806 CHECK_CALLED(ReportData);
2807 if(is_first)
2808 CHECK_CALLED(ReportResult);
2809
2810 return TRUE;
2811 }
2812
2813 static void test_file_protocol_url(LPCWSTR url)
2814 {
2815 IInternetProtocolInfo *protocol_info;
2816 IUnknown *unk;
2817 IClassFactory *factory;
2818 IInternetProtocol *protocol;
2819 BYTE buf[512];
2820 ULONG cb;
2821 HRESULT hres;
2822
2823 hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
2824 &IID_IUnknown, (void**)&unk);
2825 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2826 if(FAILED(hres))
2827 return;
2828
2829 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2830 ok(hres == E_NOINTERFACE,
2831 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
2832
2833 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2834 ok(hres == S_OK, "Could not get IClassFactory interface\n");
2835 IUnknown_Release(unk);
2836 if(FAILED(hres))
2837 return;
2838
2839 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2840 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2841
2842 if(SUCCEEDED(hres)) {
2843 if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2844 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2845 ok(hres == S_OK, "Read failed: %08x\n", hres);
2846 ok(cb == 2, "cb=%u expected 2\n", cb);
2847 buf[2] = 0;
2848 ok(!memcmp(buf, file_with_hash ? "XX" : "<H", 2), "Unexpected data %s\n&q