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