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