makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / urlmon / tests / protocol.c
blob6fc864f7777dbc6716cd0fe37ae0242a5b9c0da0
1 /*
2 * Copyright 2005-2011 Jacek Caban for CodeWeavers
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.
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.
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
19 #define COBJMACROS
20 #define CONST_VTABLE
22 #include <wine/test.h>
23 #include <wine/heap.h>
24 #include <stdarg.h>
25 #include <stdio.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "ole2.h"
30 #include "urlmon.h"
31 #include "wininet.h"
33 static HRESULT (WINAPI *pCoInternetGetSession)(DWORD, IInternetSession **, DWORD);
34 static HRESULT (WINAPI *pReleaseBindInfo)(BINDINFO*);
35 static HRESULT (WINAPI *pCreateUri)(LPCWSTR, DWORD, DWORD_PTR, IUri**);
37 #define DEFINE_EXPECT(func) \
38 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
40 #define SET_EXPECT(func) \
41 expect_ ## func = TRUE
43 #define CHECK_EXPECT2(func) \
44 do { \
45 ok(expect_ ##func, "unexpected call " #func "\n"); \
46 called_ ## func = TRUE; \
47 }while(0)
49 #define CHECK_EXPECT(func) \
50 do { \
51 CHECK_EXPECT2(func); \
52 expect_ ## func = FALSE; \
53 }while(0)
55 #define CHECK_CALLED(func) \
56 do { \
57 ok(called_ ## func, "expected " #func "\n"); \
58 expect_ ## func = called_ ## func = FALSE; \
59 }while(0)
61 #define CHECK_NOT_CALLED(func) \
62 do { \
63 ok(!called_ ## func, "unexpected " #func "\n"); \
64 expect_ ## func = called_ ## func = FALSE; \
65 }while(0)
67 #define CLEAR_CALLED(func) \
68 expect_ ## func = called_ ## func = FALSE
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(GetBindString_SAMESITE_COOKIE_LEVEL);
96 DEFINE_EXPECT(QueryService_HttpNegotiate);
97 DEFINE_EXPECT(QueryService_InternetProtocol);
98 DEFINE_EXPECT(QueryService_HttpSecurity);
99 DEFINE_EXPECT(QueryService_IBindCallbackRedirect);
100 DEFINE_EXPECT(QueryInterface_IWinInetInfo);
101 DEFINE_EXPECT(QueryInterface_IWinInetHttpInfo);
102 DEFINE_EXPECT(BeginningTransaction);
103 DEFINE_EXPECT(GetRootSecurityId);
104 DEFINE_EXPECT(OnResponse);
105 DEFINE_EXPECT(Switch);
106 DEFINE_EXPECT(Continue);
107 DEFINE_EXPECT(CreateInstance);
108 DEFINE_EXPECT(CreateInstance_no_aggregation);
109 DEFINE_EXPECT(Start);
110 DEFINE_EXPECT(StartEx);
111 DEFINE_EXPECT(Terminate);
112 DEFINE_EXPECT(Read);
113 DEFINE_EXPECT(Read2);
114 DEFINE_EXPECT(SetPriority);
115 DEFINE_EXPECT(LockRequest);
116 DEFINE_EXPECT(UnlockRequest);
117 DEFINE_EXPECT(Abort);
118 DEFINE_EXPECT(MimeFilter_CreateInstance);
119 DEFINE_EXPECT(MimeFilter_Start);
120 DEFINE_EXPECT(MimeFilter_ReportData);
121 DEFINE_EXPECT(MimeFilter_ReportResult);
122 DEFINE_EXPECT(MimeFilter_Terminate);
123 DEFINE_EXPECT(MimeFilter_LockRequest);
124 DEFINE_EXPECT(MimeFilter_UnlockRequest);
125 DEFINE_EXPECT(MimeFilter_Read);
126 DEFINE_EXPECT(MimeFilter_Switch);
127 DEFINE_EXPECT(MimeFilter_Continue);
128 DEFINE_EXPECT(Stream_Seek);
129 DEFINE_EXPECT(Stream_Read);
130 DEFINE_EXPECT(Redirect);
131 DEFINE_EXPECT(outer_QI_test);
132 DEFINE_EXPECT(Protocol_destructor);
134 static const WCHAR wszIndexHtml[] = {'i','n','d','e','x','.','h','t','m','l',0};
135 static const WCHAR index_url[] =
136 {'f','i','l','e',':','i','n','d','e','x','.','h','t','m','l',0};
138 static const WCHAR acc_mimeW[] = {'*','/','*',0};
139 static const WCHAR user_agentW[] = {'W','i','n','e',0};
140 static const WCHAR text_htmlW[] = {'t','e','x','t','/','h','t','m','l',0};
141 static const WCHAR hostW[] = {'w','w','w','.','w','i','n','e','h','q','.','o','r','g',0};
142 static const WCHAR winehq_ipW[] = {'2','0','9','.','4','6','.','2','5','.','1','3','4',0};
143 static const WCHAR emptyW[] = {0};
144 static const WCHAR pjpegW[] = {'i','m','a','g','e','/','p','j','p','e','g',0};
145 static const WCHAR gifW[] = {'i','m','a','g','e','/','g','i','f',0};
147 static HRESULT expect_hrResult;
148 static LPCWSTR file_name, http_url, expect_wsz;
149 static IInternetProtocol *async_protocol = NULL;
150 static BOOL first_data_notif, http_is_first, test_redirect, redirect_on_continue;
151 static int prot_state, read_report_data, post_stream_read;
152 static DWORD bindf, ex_priority , pi, bindinfo_options;
153 static IInternetProtocol *binding_protocol, *filtered_protocol;
154 static IInternetBindInfo *prot_bind_info;
155 static IInternetProtocolSink *binding_sink, *filtered_sink;
156 static void *expect_pv;
157 static HANDLE event_complete, event_complete2, event_continue, event_continue_done;
158 static BOOL binding_test;
159 static PROTOCOLDATA protocoldata, *pdata, continue_protdata;
160 static DWORD prot_read, filter_state, http_post_test, thread_id;
161 static BOOL security_problem, test_async_req, impl_protex;
162 static BOOL async_read_pending, mimefilter_test, direct_read, wait_for_switch, emulate_prot, short_read, test_abort;
163 static BOOL empty_file, no_mime, bind_from_cache, file_with_hash, reuse_protocol_thread;
164 static BOOL no_aggregation;
166 enum {
167 STATE_CONNECTING,
168 STATE_SENDINGREQUEST,
169 STATE_STARTDOWNLOADING,
170 STATE_DOWNLOADING
171 } state;
173 static enum {
174 FILE_TEST,
175 HTTP_TEST,
176 HTTPS_TEST,
177 FTP_TEST,
178 MK_TEST,
179 ITS_TEST,
180 BIND_TEST
181 } tested_protocol;
183 typedef struct {
184 IUnknown IUnknown_inner;
185 IInternetProtocolEx IInternetProtocolEx_iface;
186 IInternetPriority IInternetPriority_iface;
187 IUnknown *outer;
188 LONG inner_ref;
189 LONG outer_ref;
190 } Protocol;
192 static Protocol *protocol_emul;
194 static const WCHAR protocol_names[][10] = {
195 {'f','i','l','e',0},
196 {'h','t','t','p',0},
197 {'h','t','t','p','s',0},
198 {'f','t','p',0},
199 {'m','k',0},
200 {'i','t','s',0},
201 {'t','e','s','t',0}
204 static const WCHAR binding_urls[][130] = {
205 {'f','i','l','e',':','t','e','s','t','.','h','t','m','l',0},
206 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.',
207 'o','r','g','/','s','i','t','e','/','a','b','o','u','t',0},
208 {'h','t','t','p','s',':','/','/','w','w','w','.','c','o','d','e','w','e','a','v','e','r','s',
209 '.','c','o','m','/','t','e','s','t','.','h','t','m','l',0},
210 {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
211 '/','p','u','b','/','o','t','h','e','r',
212 '/','w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0},
213 {'m','k',':','t','e','s','t',0},
214 {'i','t','s',':','t','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l',0},
215 {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0}
218 static const CHAR post_data[] = "mode=Test";
220 static LONG obj_refcount(void *obj)
222 IUnknown_AddRef((IUnknown *)obj);
223 return IUnknown_Release((IUnknown *)obj);
226 static const char *w2a(LPCWSTR str)
228 static char buf[INTERNET_MAX_URL_LENGTH];
229 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
230 return buf;
233 static HRESULT WINAPI HttpSecurity_QueryInterface(IHttpSecurity *iface, REFIID riid, void **ppv)
235 if(IsEqualGUID(&IID_IUnknown, riid)
236 || IsEqualGUID(&IID_IHttpSecurity, riid)) {
237 *ppv = iface;
238 return S_OK;
241 ok(0, "unexpected call\n");
242 return E_NOINTERFACE;
245 static ULONG WINAPI HttpSecurity_AddRef(IHttpSecurity *iface)
247 return 2;
250 static ULONG WINAPI HttpSecurity_Release(IHttpSecurity *iface)
252 return 1;
255 static HRESULT WINAPI HttpSecurity_GetWindow(IHttpSecurity* iface, REFGUID rguidReason, HWND *phwnd)
257 trace("HttpSecurity_GetWindow\n");
259 return S_FALSE;
262 static HRESULT WINAPI HttpSecurity_OnSecurityProblem(IHttpSecurity *iface, DWORD dwProblem)
264 win_skip("Security problem: %u\n", dwProblem);
265 ok(dwProblem == ERROR_INTERNET_SEC_CERT_REV_FAILED || dwProblem == ERROR_INTERNET_INVALID_CA,
266 "Expected got %u security problem\n", dwProblem);
268 /* Only retry once */
269 if (security_problem)
270 return E_ABORT;
272 security_problem = TRUE;
273 if(dwProblem == ERROR_INTERNET_INVALID_CA)
274 return E_ABORT;
275 SET_EXPECT(BeginningTransaction);
277 return RPC_E_RETRY;
280 static IHttpSecurityVtbl HttpSecurityVtbl = {
281 HttpSecurity_QueryInterface,
282 HttpSecurity_AddRef,
283 HttpSecurity_Release,
284 HttpSecurity_GetWindow,
285 HttpSecurity_OnSecurityProblem
288 static IHttpSecurity http_security = { &HttpSecurityVtbl };
290 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, REFIID riid, void **ppv)
292 if(IsEqualGUID(&IID_IUnknown, riid)
293 || IsEqualGUID(&IID_IHttpNegotiate, riid)
294 || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
295 *ppv = iface;
296 return S_OK;
299 ok(0, "unexpected call\n");
300 return E_NOINTERFACE;
303 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
305 return 2;
308 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
310 return 1;
313 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, LPCWSTR szURL,
314 LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
316 LPWSTR addl_headers;
318 static const WCHAR wszHeaders[] =
319 {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ','a','p','p','l','i','c','a','t',
320 'i','o','n','/','x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o',
321 'd','e','d','\r','\n',0};
323 CHECK_EXPECT(BeginningTransaction);
325 if(binding_test)
326 ok(!lstrcmpW(szURL, binding_urls[tested_protocol]), "szURL != http_url\n");
327 else
328 ok(!lstrcmpW(szURL, http_url), "szURL != http_url\n");
329 ok(!dwReserved, "dwReserved=%d, expected 0\n", dwReserved);
330 ok(pszAdditionalHeaders != NULL, "pszAdditionalHeaders == NULL\n");
331 if(pszAdditionalHeaders)
333 ok(*pszAdditionalHeaders == NULL, "*pszAdditionalHeaders != NULL\n");
334 if (http_post_test)
336 addl_headers = CoTaskMemAlloc(sizeof(wszHeaders));
337 memcpy(addl_headers, wszHeaders, sizeof(wszHeaders));
338 *pszAdditionalHeaders = addl_headers;
342 return S_OK;
345 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
346 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
348 CHECK_EXPECT(OnResponse);
350 ok(dwResponseCode == 200, "dwResponseCode=%d, expected 200\n", dwResponseCode);
351 ok(szResponseHeaders != NULL, "szResponseHeaders == NULL\n");
352 ok(szRequestHeaders == NULL, "szRequestHeaders != NULL\n");
353 ok(pszAdditionalRequestHeaders == NULL, "pszAdditionalHeaders != NULL\n");
355 return S_OK;
358 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
359 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
361 static const BYTE sec_id[] = {'h','t','t','p',':','t','e','s','t',1,0,0,0};
363 CHECK_EXPECT(GetRootSecurityId);
365 ok(!dwReserved, "dwReserved=%ld, expected 0\n", dwReserved);
366 ok(pbSecurityId != NULL, "pbSecurityId == NULL\n");
367 ok(pcbSecurityId != NULL, "pcbSecurityId == NULL\n");
369 if(pcbSecurityId) {
370 ok(*pcbSecurityId == 512, "*pcbSecurityId=%d, expected 512\n", *pcbSecurityId);
371 *pcbSecurityId = sizeof(sec_id);
374 if(pbSecurityId)
375 memcpy(pbSecurityId, sec_id, sizeof(sec_id));
377 return E_FAIL;
380 static IHttpNegotiate2Vtbl HttpNegotiateVtbl = {
381 HttpNegotiate_QueryInterface,
382 HttpNegotiate_AddRef,
383 HttpNegotiate_Release,
384 HttpNegotiate_BeginningTransaction,
385 HttpNegotiate_OnResponse,
386 HttpNegotiate_GetRootSecurityId
389 static IHttpNegotiate2 http_negotiate = { &HttpNegotiateVtbl };
391 static HRESULT WINAPI BindCallbackRedirect_QueryInterface(IBindCallbackRedirect *iface, REFIID riid, void **ppv)
393 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
394 *ppv = NULL;
395 return E_NOINTERFACE;
398 static ULONG WINAPI BindCallbackRedirect_AddRef(IBindCallbackRedirect *iface)
400 return 2;
403 static ULONG WINAPI BindCallbackRedirect_Release(IBindCallbackRedirect *iface)
405 return 1;
408 static HRESULT WINAPI BindCallbackRedirect_Redirect(IBindCallbackRedirect *iface, const WCHAR *url, VARIANT_BOOL *cancel)
410 CHECK_EXPECT(Redirect);
411 *cancel = VARIANT_FALSE;
412 return S_OK;
415 static const IBindCallbackRedirectVtbl BindCallbackRedirectVtbl = {
416 BindCallbackRedirect_QueryInterface,
417 BindCallbackRedirect_AddRef,
418 BindCallbackRedirect_Release,
419 BindCallbackRedirect_Redirect
422 static IBindCallbackRedirect redirect_callback = { &BindCallbackRedirectVtbl };
424 static HRESULT QueryInterface(REFIID,void**);
426 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
428 return QueryInterface(riid, ppv);
431 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
433 return 2;
436 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
438 return 1;
441 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID guidService,
442 REFIID riid, void **ppv)
444 if(IsEqualGUID(&IID_IHttpNegotiate, guidService) || IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
445 CHECK_EXPECT2(QueryService_HttpNegotiate);
446 return IHttpNegotiate2_QueryInterface(&http_negotiate, riid, ppv);
449 if(IsEqualGUID(&IID_IInternetProtocol, guidService)) {
450 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid\n");
451 CHECK_EXPECT(QueryService_InternetProtocol);
452 return E_NOINTERFACE;
455 if(IsEqualGUID(&IID_IHttpSecurity, guidService)) {
456 ok(IsEqualGUID(&IID_IHttpSecurity, riid), "unexpected riid\n");
457 CHECK_EXPECT(QueryService_HttpSecurity);
458 return IHttpSecurity_QueryInterface(&http_security, riid, ppv);
461 if(IsEqualGUID(&IID_IBindCallbackRedirect, guidService)) {
462 CHECK_EXPECT(QueryService_IBindCallbackRedirect);
463 ok(IsEqualGUID(&IID_IBindCallbackRedirect, riid), "riid = %s\n", wine_dbgstr_guid(riid));
464 *ppv = &redirect_callback;
465 return S_OK;
468 if(IsEqualGUID(&IID_IGetBindHandle, guidService)) {
469 trace("QueryService(IID_IGetBindHandle)\n");
470 *ppv = NULL;
471 return E_NOINTERFACE;
474 if(IsEqualGUID(&IID_IWindowForBindingUI, guidService)) {
475 trace("QueryService(IID_IWindowForBindingUI)\n");
476 *ppv = NULL;
477 return E_NOINTERFACE;
480 ok(0, "unexpected service %s\n", wine_dbgstr_guid(guidService));
481 return E_FAIL;
484 static const IServiceProviderVtbl ServiceProviderVtbl = {
485 ServiceProvider_QueryInterface,
486 ServiceProvider_AddRef,
487 ServiceProvider_Release,
488 ServiceProvider_QueryService
491 static IServiceProvider service_provider = { &ServiceProviderVtbl };
493 static HRESULT WINAPI Stream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
495 static const IID IID_strm_unknown = {0x2f68429a,0x199a,0x4043,{0x93,0x11,0xf2,0xfe,0x7c,0x13,0xcc,0xb9}};
497 if(!IsEqualGUID(&IID_strm_unknown, riid)) /* IE11 */
498 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
500 *ppv = NULL;
501 return E_NOINTERFACE;
504 static ULONG WINAPI Stream_AddRef(IStream *iface)
506 return 2;
509 static ULONG WINAPI Stream_Release(IStream *iface)
511 return 1;
514 static HRESULT WINAPI Stream_Read(IStream *iface, void *pv,
515 ULONG cb, ULONG *pcbRead)
517 CHECK_EXPECT2(Stream_Read);
519 ok(GetCurrentThreadId() != thread_id, "wrong thread %d\n", GetCurrentThreadId());
521 ok(pv != NULL, "pv == NULL\n");
522 ok(cb == 0x20000 || broken(cb == 0x2000), "cb = %d\n", cb);
523 ok(pcbRead != NULL, "pcbRead == NULL\n");
525 if(post_stream_read) {
526 *pcbRead = 0;
527 return S_FALSE;
530 memcpy(pv, post_data, sizeof(post_data)-1);
531 post_stream_read += *pcbRead = sizeof(post_data)-1;
532 return S_OK;
535 static HRESULT WINAPI Stream_Write(IStream *iface, const void *pv,
536 ULONG cb, ULONG *pcbWritten)
538 ok(0, "unexpected call\n");
539 return E_NOTIMPL;
542 static HRESULT WINAPI Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
543 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
545 CHECK_EXPECT(Stream_Seek);
547 ok(!dlibMove.QuadPart, "dlibMove != 0\n");
548 ok(dwOrigin == STREAM_SEEK_SET, "dwOrigin = %d\n", dwOrigin);
549 ok(!plibNewPosition, "plibNewPosition == NULL\n");
551 return S_OK;
554 static HRESULT WINAPI Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
556 ok(0, "unexpected call\n");
557 return E_NOTIMPL;
560 static HRESULT WINAPI Stream_CopyTo(IStream *iface, IStream *pstm,
561 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
563 ok(0, "unexpected call\n");
564 return E_NOTIMPL;
567 static HRESULT WINAPI Stream_Commit(IStream *iface, DWORD grfCommitFlags)
569 ok(0, "unexpected call\n");
570 return E_NOTIMPL;
573 static HRESULT WINAPI Stream_Revert(IStream *iface)
575 ok(0, "unexpected call\n");
576 return E_NOTIMPL;
579 static HRESULT WINAPI Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
580 ULARGE_INTEGER cb, DWORD dwLockType)
582 ok(0, "unexpected call\n");
583 return E_NOTIMPL;
586 static HRESULT WINAPI Stream_UnlockRegion(IStream *iface,
587 ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
589 ok(0, "unexpected call\n");
590 return E_NOTIMPL;
593 static HRESULT WINAPI Stream_Stat(IStream *iface, STATSTG *pstatstg,
594 DWORD dwStatFlag)
596 ok(0, "unexpected call\n");
597 return E_NOTIMPL;
600 static HRESULT WINAPI Stream_Clone(IStream *iface, IStream **ppstm)
602 ok(0, "unexpected call\n");
603 return E_NOTIMPL;
606 static const IStreamVtbl StreamVtbl = {
607 Stream_QueryInterface,
608 Stream_AddRef,
609 Stream_Release,
610 Stream_Read,
611 Stream_Write,
612 Stream_Seek,
613 Stream_SetSize,
614 Stream_CopyTo,
615 Stream_Commit,
616 Stream_Revert,
617 Stream_LockRegion,
618 Stream_UnlockRegion,
619 Stream_Stat,
620 Stream_Clone
623 static IStream Stream = { &StreamVtbl };
625 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
627 return QueryInterface(riid, ppv);
630 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
632 return 2;
635 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
637 return 1;
640 static void call_continue(PROTOCOLDATA *protocol_data)
642 HRESULT hres;
644 if (winetest_debug > 1)
645 trace("continue in state %d\n", state);
647 if(state == STATE_CONNECTING) {
648 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST || tested_protocol == FTP_TEST) {
649 if (http_is_first){
650 CLEAR_CALLED(ReportProgress_FINDINGRESOURCE);
651 CLEAR_CALLED(ReportProgress_PROXYDETECTING);
653 CLEAR_CALLED(ReportProgress_CONNECTING);
655 if(tested_protocol == FTP_TEST)
656 todo_wine CHECK_CALLED(ReportProgress_SENDINGREQUEST);
657 else if (tested_protocol != HTTPS_TEST)
658 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
659 if(test_redirect && !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)) {
660 CHECK_CALLED(ReportProgress_REDIRECTING);
661 CLEAR_CALLED(GetBindString_SAMESITE_COOKIE_LEVEL); /* New in IE11 */
663 state = test_async_req ? STATE_SENDINGREQUEST : STATE_STARTDOWNLOADING;
666 switch(state) {
667 case STATE_SENDINGREQUEST:
668 SET_EXPECT(Stream_Read);
669 SET_EXPECT(ReportProgress_SENDINGREQUEST);
670 break;
671 case STATE_STARTDOWNLOADING:
672 if((tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST)
673 && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))) {
674 SET_EXPECT(OnResponse);
675 if(tested_protocol == HTTPS_TEST || test_redirect || test_abort || empty_file)
676 SET_EXPECT(ReportProgress_ACCEPTRANGES);
677 SET_EXPECT(ReportProgress_ENCODING);
678 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
679 if(bindf & BINDF_NEEDFILE)
680 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
682 default:
683 break;
686 if(state != STATE_SENDINGREQUEST && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)))
687 SET_EXPECT(ReportData);
688 hres = IInternetProtocol_Continue(async_protocol, protocol_data);
689 ok(hres == S_OK, "Continue failed: %08x\n", hres);
690 if(tested_protocol == FTP_TEST || security_problem)
691 CLEAR_CALLED(ReportData);
692 else if(state != STATE_SENDINGREQUEST && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)))
693 CHECK_CALLED(ReportData);
695 switch(state) {
696 case STATE_SENDINGREQUEST:
697 CHECK_CALLED(Stream_Read);
698 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
699 state = STATE_STARTDOWNLOADING;
700 break;
701 case STATE_STARTDOWNLOADING:
702 if(!security_problem) {
703 state = STATE_DOWNLOADING;
704 if((tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST)
705 && (!test_redirect || !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))) {
706 CHECK_CALLED(OnResponse);
707 if(tested_protocol == HTTPS_TEST || empty_file)
708 CHECK_CALLED(ReportProgress_ACCEPTRANGES);
709 else if(test_redirect || test_abort)
710 CLEAR_CALLED(ReportProgress_ACCEPTRANGES);
711 CLEAR_CALLED(ReportProgress_ENCODING);
712 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
713 if(bindf & BINDF_NEEDFILE)
714 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
717 else
719 security_problem = FALSE;
720 SET_EXPECT(ReportProgress_CONNECTING);
722 default:
723 break;
727 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
729 if(tested_protocol == FTP_TEST)
730 CHECK_EXPECT2(Switch);
731 else
732 CHECK_EXPECT(Switch);
734 ok(pProtocolData != NULL, "pProtocolData == NULL\n");
735 if(binding_test) {
736 ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
737 ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
738 pProtocolData->grfFlags, protocoldata.grfFlags );
739 ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
740 pProtocolData->dwState, protocoldata.dwState );
741 ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
742 pProtocolData->pData, protocoldata.pData );
743 ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
744 pProtocolData->cbData, protocoldata.cbData );
747 pdata = pProtocolData;
749 if(binding_test) {
750 SetEvent(event_complete);
751 ok( WaitForSingleObject(event_complete2, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
752 return S_OK;
753 }if(direct_read) {
754 continue_protdata = *pProtocolData;
755 SetEvent(event_continue);
756 ok( WaitForSingleObject(event_continue_done, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
757 }else {
758 call_continue(pProtocolData);
759 SetEvent(event_complete);
762 return S_OK;
765 static const char *status_names[] =
767 "0",
768 "FINDINGRESOURCE",
769 "CONNECTING",
770 "REDIRECTING",
771 "BEGINDOWNLOADDATA",
772 "DOWNLOADINGDATA",
773 "ENDDOWNLOADDATA",
774 "BEGINDOWNLOADCOMPONENTS",
775 "INSTALLINGCOMPONENTS",
776 "ENDDOWNLOADCOMPONENTS",
777 "USINGCACHEDCOPY",
778 "SENDINGREQUEST",
779 "CLASSIDAVAILABLE",
780 "MIMETYPEAVAILABLE",
781 "CACHEFILENAMEAVAILABLE",
782 "BEGINSYNCOPERATION",
783 "ENDSYNCOPERATION",
784 "BEGINUPLOADDATA",
785 "UPLOADINGDATA",
786 "ENDUPLOADINGDATA",
787 "PROTOCOLCLASSID",
788 "ENCODING",
789 "VERIFIEDMIMETYPEAVAILABLE",
790 "CLASSINSTALLLOCATION",
791 "DECODING",
792 "LOADINGMIMEHANDLER",
793 "CONTENTDISPOSITIONATTACH",
794 "FILTERREPORTMIMETYPE",
795 "CLSIDCANINSTANTIATE",
796 "IUNKNOWNAVAILABLE",
797 "DIRECTBIND",
798 "RAWMIMETYPE",
799 "PROXYDETECTING",
800 "ACCEPTRANGES",
801 "COOKIE_SENT",
802 "COMPACT_POLICY_RECEIVED",
803 "COOKIE_SUPPRESSED",
804 "COOKIE_STATE_UNKNOWN",
805 "COOKIE_STATE_ACCEPT",
806 "COOKIE_STATE_REJECT",
807 "COOKIE_STATE_PROMPT",
808 "COOKIE_STATE_LEASH",
809 "COOKIE_STATE_DOWNGRADE",
810 "POLICY_HREF",
811 "P3P_HEADER",
812 "SESSION_COOKIE_RECEIVED",
813 "PERSISTENT_COOKIE_RECEIVED",
814 "SESSION_COOKIES_ALLOWED",
815 "CACHECONTROL",
816 "CONTENTDISPOSITIONFILENAME",
817 "MIMETEXTPLAINMISMATCH",
818 "PUBLISHERAVAILABLE",
819 "DISPLAYNAMEAVAILABLE"
822 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
823 LPCWSTR szStatusText)
825 static const WCHAR null_guid[] = {'{','0','0','0','0','0','0','0','0','-','0','0','0','0','-',
826 '0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0','0','0','0','0','}',0};
827 static const WCHAR text_plain[] = {'t','e','x','t','/','p','l','a','i','n',0};
829 if (winetest_debug > 1)
831 if (ulStatusCode < ARRAY_SIZE(status_names))
832 trace( "progress: %s %s\n", status_names[ulStatusCode], wine_dbgstr_w(szStatusText) );
833 else
834 trace( "progress: %u %s\n", ulStatusCode, wine_dbgstr_w(szStatusText) );
837 switch(ulStatusCode) {
838 case BINDSTATUS_MIMETYPEAVAILABLE:
839 CHECK_EXPECT2(ReportProgress_MIMETYPEAVAILABLE);
840 if(tested_protocol != FILE_TEST && tested_protocol != ITS_TEST && !mimefilter_test && (pi & PI_MIMEVERIFICATION)) {
841 if(!short_read || !direct_read)
842 CHECK_CALLED(Read); /* set in Continue */
843 else if(short_read)
844 CHECK_CALLED(Read2); /* set in Read */
846 ok(szStatusText != NULL, "szStatusText == NULL\n");
847 if(szStatusText) {
848 if(tested_protocol == BIND_TEST)
849 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText %s\n", wine_dbgstr_w(szStatusText));
850 else if (http_post_test)
851 ok(lstrlenW(text_plain) <= lstrlenW(szStatusText) &&
852 !memcmp(szStatusText, text_plain, lstrlenW(text_plain)*sizeof(WCHAR)),
853 "szStatusText != text/plain\n");
854 else if(empty_file)
855 ok(!lstrcmpW(szStatusText, L"application/javascript"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
856 else if((pi & PI_MIMEVERIFICATION) && emulate_prot && !mimefilter_test
857 && tested_protocol==HTTP_TEST && !short_read)
858 ok(lstrlenW(gifW) <= lstrlenW(szStatusText) &&
859 !memcmp(szStatusText, gifW, lstrlenW(gifW)*sizeof(WCHAR)),
860 "szStatusText != image/gif\n");
861 else if(!mimefilter_test)
862 ok(lstrlenW(text_htmlW) <= lstrlenW(szStatusText) &&
863 !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
864 "szStatusText != text/html\n");
866 break;
867 case BINDSTATUS_DIRECTBIND:
868 CHECK_EXPECT2(ReportProgress_DIRECTBIND);
869 ok(szStatusText == NULL, "szStatusText != NULL\n");
870 break;
871 case BINDSTATUS_RAWMIMETYPE:
872 CHECK_EXPECT2(ReportProgress_RAWMIMETYPE);
873 ok(szStatusText != NULL, "szStatusText == NULL\n");
874 if(szStatusText)
875 ok(lstrlenW(szStatusText) < lstrlenW(text_htmlW) ||
876 !memcmp(szStatusText, text_htmlW, lstrlenW(text_htmlW)*sizeof(WCHAR)),
877 "szStatusText != text/html\n");
878 break;
879 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
880 CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
881 ok(szStatusText != NULL, "szStatusText == NULL\n");
882 if(szStatusText) {
883 if(binding_test)
884 ok(!lstrcmpW(szStatusText, expect_wsz), "unexpected szStatusText\n");
885 else if(tested_protocol == FILE_TEST)
886 ok(!lstrcmpW(szStatusText, file_name), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
887 else
888 ok(szStatusText != NULL, "szStatusText == NULL\n");
890 break;
891 case BINDSTATUS_FINDINGRESOURCE:
892 CHECK_EXPECT2(ReportProgress_FINDINGRESOURCE);
893 ok(szStatusText != NULL, "szStatusText == NULL\n");
894 break;
895 case BINDSTATUS_CONNECTING:
896 CHECK_EXPECT2(ReportProgress_CONNECTING);
897 ok(szStatusText != NULL, "szStatusText == NULL\n");
898 break;
899 case BINDSTATUS_SENDINGREQUEST:
900 CHECK_EXPECT2(ReportProgress_SENDINGREQUEST);
901 if(tested_protocol == FILE_TEST || tested_protocol == ITS_TEST) {
902 ok(szStatusText != NULL, "szStatusText == NULL\n");
903 if(szStatusText)
904 ok(!*szStatusText, "wrong szStatusText\n");
906 break;
907 case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE:
908 CHECK_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
909 ok(szStatusText != NULL, "szStatusText == NULL\n");
910 if(szStatusText)
911 ok(!lstrcmpW(szStatusText, L"text/html"), "szStatusText != text/html\n");
912 break;
913 case BINDSTATUS_PROTOCOLCLASSID:
914 CHECK_EXPECT(ReportProgress_PROTOCOLCLASSID);
915 ok(szStatusText != NULL, "szStatusText == NULL\n");
916 ok(!lstrcmpW(szStatusText, null_guid), "unexpected classid %s\n", wine_dbgstr_w(szStatusText));
917 break;
918 case BINDSTATUS_COOKIE_SENT:
919 CHECK_EXPECT2(ReportProgress_COOKIE_SENT);
920 ok(szStatusText == NULL, "szStatusText != NULL\n");
921 break;
922 case BINDSTATUS_REDIRECTING:
923 CHECK_EXPECT(ReportProgress_REDIRECTING);
924 if(test_redirect)
925 ok(!lstrcmpW(szStatusText, L"http://test.winehq.org/tests/hello.html"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
926 else
927 ok(szStatusText == NULL, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
928 break;
929 case BINDSTATUS_ENCODING:
930 CHECK_EXPECT(ReportProgress_ENCODING);
931 ok(!lstrcmpW(szStatusText, L"gzip"), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
932 break;
933 case BINDSTATUS_ACCEPTRANGES:
934 CHECK_EXPECT(ReportProgress_ACCEPTRANGES);
935 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
936 break;
937 case BINDSTATUS_PROXYDETECTING:
938 if(!called_ReportProgress_PROXYDETECTING)
939 SET_EXPECT(ReportProgress_CONNECTING);
940 CHECK_EXPECT2(ReportProgress_PROXYDETECTING);
941 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
942 break;
943 case BINDSTATUS_LOADINGMIMEHANDLER:
944 CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
945 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
946 break;
947 case BINDSTATUS_DECODING:
948 CHECK_EXPECT(ReportProgress_DECODING);
949 ok(!lstrcmpW(szStatusText, pjpegW), "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
950 break;
951 case BINDSTATUS_RESERVED_7:
952 trace("BINDSTATUS_RESERVED_7\n");
953 break;
954 case BINDSTATUS_RESERVED_8:
955 trace("BINDSTATUS_RESERVED_8\n");
956 break;
957 default:
958 ok(0, "Unexpected status %d (%d)\n", ulStatusCode, ulStatusCode-BINDSTATUS_LAST);
961 return S_OK;
964 static void test_http_info(IInternetProtocol *protocol)
966 IWinInetHttpInfo *info;
967 char buf[1024];
968 DWORD size, len;
969 HRESULT hres;
971 static const WCHAR connectionW[] = {'c','o','n','n','e','c','t','i','o','n',0};
973 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&info);
974 ok(hres == S_OK, "Could not get IWinInterHttpInfo iface: %08x\n", hres);
976 size = sizeof(buf);
977 strcpy(buf, "connection");
978 hres = IWinInetHttpInfo_QueryInfo(info, HTTP_QUERY_CUSTOM, buf, &size, NULL, NULL);
979 if(tested_protocol != FTP_TEST) {
980 ok(hres == S_OK, "QueryInfo failed: %08x\n", hres);
982 ok(!strcmp(buf, "Keep-Alive"), "buf = %s\n", buf);
983 len = strlen(buf);
984 ok(size == len, "size = %u, expected %u\n", size, len);
986 size = sizeof(buf);
987 memcpy(buf, connectionW, sizeof(connectionW));
988 hres = IWinInetHttpInfo_QueryInfo(info, HTTP_QUERY_CUSTOM, buf, &size, NULL, NULL);
989 ok(hres == S_FALSE, "QueryInfo returned %08x\n", hres);
990 }else {
991 ok(hres == S_FALSE, "QueryInfo failed: %08x\n", hres);
994 IWinInetHttpInfo_Release(info);
997 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
998 ULONG ulProgress, ULONG ulProgressMax)
1000 HRESULT hres;
1002 static int rec_depth;
1003 rec_depth++;
1005 if(!mimefilter_test && (tested_protocol == FILE_TEST || tested_protocol == ITS_TEST)) {
1006 CHECK_EXPECT2(ReportData);
1008 ok(ulProgress == ulProgressMax, "ulProgress (%d) != ulProgressMax (%d)\n",
1009 ulProgress, ulProgressMax);
1010 if(!file_with_hash)
1011 ok(ulProgressMax == 13, "ulProgressMax=%d, expected 13\n", ulProgressMax);
1012 /* BSCF_SKIPDRAINDATAFORFILEURLS added in IE8 */
1013 if(tested_protocol == FILE_TEST)
1014 ok((grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION)) ||
1015 (grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_SKIPDRAINDATAFORFILEURLS)),
1016 "grcfBSCF = %08x\n", grfBSCF);
1017 else
1018 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
1019 }else if(bind_from_cache) {
1020 CHECK_EXPECT(ReportData);
1022 ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE), "grcfBSCF = %08x\n", grfBSCF);
1023 ok(ulProgress == 1000, "ulProgress = %u\n", ulProgress);
1024 ok(!ulProgressMax, "ulProgressMax = %u\n", ulProgressMax);
1025 }else if(direct_read) {
1026 BYTE buf[14096];
1027 ULONG read;
1029 if(!read_report_data && rec_depth == 1) {
1030 BOOL reported_all_data = called_ReportData2;
1032 CHECK_EXPECT2(ReportData);
1034 if(short_read) {
1035 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE)
1036 || grfBSCF == BSCF_FIRSTDATANOTIFICATION, /* < IE8 */
1037 "grcfBSCF = %08x\n", grfBSCF);
1038 CHECK_CALLED(Read); /* Set in Continue */
1039 first_data_notif = FALSE;
1040 }else if(first_data_notif) {
1041 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
1042 first_data_notif = FALSE;
1043 }else if(reported_all_data) {
1044 ok(grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION),
1045 "grcfBSCF = %08x\n", grfBSCF);
1046 }else if(!direct_read) {
1047 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION, "grcfBSCF = %08x\n", grfBSCF);
1050 do {
1051 read = 0;
1052 if(emulate_prot)
1053 SET_EXPECT(Read);
1054 else
1055 SET_EXPECT(ReportData2);
1056 SET_EXPECT(ReportResult);
1057 if(!emulate_prot)
1058 SET_EXPECT(Switch);
1059 hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
1060 ok(hres == E_PENDING || hres == S_FALSE || hres == S_OK, "Read failed: %08x\n", hres);
1061 if(hres == S_OK)
1062 ok(read, "read == 0\n");
1063 if(reported_all_data)
1064 ok(hres == S_FALSE, "Read failed: %08x, expected S_FALSE\n", hres);
1065 if(!emulate_prot && hres != E_PENDING)
1066 CHECK_NOT_CALLED(Switch); /* otherwise checked in wait_for_switch loop */
1067 if(emulate_prot)
1068 CHECK_CALLED(Read);
1069 if(!reported_all_data && called_ReportData2) {
1070 if(!emulate_prot)
1071 CHECK_CALLED(ReportData2);
1072 CHECK_CALLED(ReportResult);
1073 reported_all_data = TRUE;
1074 }else {
1075 if(!emulate_prot)
1076 CHECK_NOT_CALLED(ReportData2);
1077 CHECK_NOT_CALLED(ReportResult);
1079 }while(hres == S_OK);
1080 if(hres == S_FALSE)
1081 wait_for_switch = FALSE;
1082 }else {
1083 CHECK_EXPECT(ReportData2);
1085 ok(grfBSCF & BSCF_LASTDATANOTIFICATION, "grfBSCF = %08x\n", grfBSCF);
1087 read = 0xdeadbeef;
1088 if(emulate_prot)
1089 SET_EXPECT(Read2);
1090 hres = IInternetProtocol_Read(binding_test ? binding_protocol : async_protocol, expect_pv = buf, sizeof(buf), &read);
1091 if(emulate_prot)
1092 CHECK_CALLED(Read2);
1093 ok(hres == S_FALSE, "Read returned: %08x, expected E_FALSE\n", hres);
1094 ok(!read, "read = %d\n", read);
1096 }else if(!binding_test && (tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST
1097 || tested_protocol == FTP_TEST)) {
1098 if(empty_file)
1099 CHECK_EXPECT2(ReportData);
1100 else if(!(grfBSCF & BSCF_LASTDATANOTIFICATION) || (grfBSCF & BSCF_DATAFULLYAVAILABLE))
1101 CHECK_EXPECT(ReportData);
1102 else if (http_post_test)
1103 ok(ulProgress == 13, "Read %u bytes instead of 13\n", ulProgress);
1105 if(empty_file) {
1106 ok(!ulProgress, "ulProgress = %d\n", ulProgress);
1107 ok(!ulProgressMax, "ulProgressMax = %d\n", ulProgressMax);
1108 }else {
1109 ok(ulProgress, "ulProgress == 0\n");
1112 if(empty_file) {
1113 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION),
1114 "grcfBSCF = %08x\n", grfBSCF);
1115 first_data_notif = FALSE;
1116 }else if(first_data_notif) {
1117 ok(grfBSCF == BSCF_FIRSTDATANOTIFICATION
1118 || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE),
1119 "grcfBSCF = %08x\n", grfBSCF);
1120 first_data_notif = FALSE;
1121 } else {
1122 ok(grfBSCF == BSCF_INTERMEDIATEDATANOTIFICATION
1123 || grfBSCF == (BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION)
1124 || broken(grfBSCF == (BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION)),
1125 "grcfBSCF = %08x\n", grfBSCF);
1128 if((grfBSCF & BSCF_FIRSTDATANOTIFICATION) && !binding_test)
1129 test_http_info(async_protocol);
1131 if(!(bindf & BINDF_FROMURLMON) &&
1132 !(grfBSCF & BSCF_LASTDATANOTIFICATION)) {
1133 if(state == STATE_CONNECTING) {
1134 state = STATE_DOWNLOADING;
1135 if(http_is_first) {
1136 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1137 CHECK_CALLED(ReportProgress_CONNECTING);
1139 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1140 CHECK_CALLED(OnResponse);
1141 CHECK_CALLED(ReportProgress_RAWMIMETYPE);
1143 SetEvent(event_complete);
1145 }else if(!read_report_data) {
1146 BYTE buf[1000];
1147 ULONG read;
1148 HRESULT hres;
1150 CHECK_EXPECT(ReportData);
1152 if(tested_protocol != BIND_TEST) {
1153 do {
1154 if(mimefilter_test)
1155 SET_EXPECT(MimeFilter_Read);
1156 else if(rec_depth > 1)
1157 SET_EXPECT(Read2);
1158 else
1159 SET_EXPECT(Read);
1160 hres = IInternetProtocol_Read(binding_protocol, expect_pv=buf, sizeof(buf), &read);
1161 if(mimefilter_test)
1162 CHECK_CALLED(MimeFilter_Read);
1163 else if(rec_depth > 1)
1164 CHECK_CALLED(Read2);
1165 else
1166 CHECK_CALLED(Read);
1167 }while(hres == S_OK);
1171 rec_depth--;
1172 return S_OK;
1175 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1176 DWORD dwError, LPCWSTR szResult)
1178 CHECK_EXPECT(ReportResult);
1180 if(security_problem)
1181 return S_OK;
1183 if(tested_protocol == FTP_TEST)
1184 ok(hrResult == E_PENDING || hrResult == S_OK, "hrResult = %08x, expected E_PENDING or S_OK\n", hrResult);
1185 else
1186 ok(hrResult == expect_hrResult, "hrResult = %08x, expected: %08x\n",
1187 hrResult, expect_hrResult);
1188 if(SUCCEEDED(hrResult) || tested_protocol == FTP_TEST || test_abort || hrResult == INET_E_REDIRECT_FAILED)
1189 ok(dwError == ERROR_SUCCESS, "dwError = %d, expected ERROR_SUCCESS\n", dwError);
1190 else
1191 ok(dwError != ERROR_SUCCESS ||
1192 broken(tested_protocol == MK_TEST), /* WinME and NT4 */
1193 "dwError == ERROR_SUCCESS\n");
1195 if(hrResult == INET_E_REDIRECT_FAILED)
1196 ok(!lstrcmpW(szResult, L"http://test.winehq.org/tests/hello.html"), "szResult = %s\n", wine_dbgstr_w(szResult));
1197 else
1198 ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1200 if(direct_read)
1201 SET_EXPECT(ReportData); /* checked after main loop */
1203 return S_OK;
1206 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
1207 ProtocolSink_QueryInterface,
1208 ProtocolSink_AddRef,
1209 ProtocolSink_Release,
1210 ProtocolSink_Switch,
1211 ProtocolSink_ReportProgress,
1212 ProtocolSink_ReportData,
1213 ProtocolSink_ReportResult
1216 static IInternetProtocolSink protocol_sink = { &protocol_sink_vtbl };
1218 static HRESULT WINAPI MimeProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
1220 if(IsEqualGUID(&IID_IUnknown, riid)
1221 || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
1222 *ppv = iface;
1223 return S_OK;
1226 ok(0, "unexpected call\n");
1227 return E_NOTIMPL;
1230 static ULONG WINAPI MimeProtocolSink_AddRef(IInternetProtocolSink *iface)
1232 return 2;
1235 static ULONG WINAPI MimeProtocolSink_Release(IInternetProtocolSink *iface)
1237 return 1;
1240 static HRESULT WINAPI MimeProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
1242 HRESULT hres;
1244 CHECK_EXPECT(MimeFilter_Switch);
1246 SET_EXPECT(Switch);
1247 hres = IInternetProtocolSink_Switch(filtered_sink, pProtocolData);
1248 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1249 CHECK_CALLED(Switch);
1251 return S_OK;
1254 static HRESULT WINAPI MimeProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
1255 LPCWSTR szStatusText)
1257 switch(ulStatusCode) {
1258 case BINDSTATUS_LOADINGMIMEHANDLER:
1260 * IE9 for some reason (bug?) calls this on mime handler's protocol sink instead of the
1261 * main protocol sink. We check ReportProgress_LOADINGMIMEHANDLER both here and in
1262 * ProtocolSink_ReportProgress to workaround it.
1264 CHECK_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1265 ok(!szStatusText, "szStatusText = %s\n", wine_dbgstr_w(szStatusText));
1266 break;
1267 default:
1268 ok(0, "Unexpected status code %d\n", ulStatusCode);
1271 return S_OK;
1274 static HRESULT WINAPI MimeProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF,
1275 ULONG ulProgress, ULONG ulProgressMax)
1277 DWORD read = 0;
1278 BYTE buf[8192];
1279 HRESULT hres;
1280 BOOL report_mime = FALSE;
1282 CHECK_EXPECT(MimeFilter_ReportData);
1284 if(!filter_state && !no_mime) {
1285 SET_EXPECT(Read);
1286 hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
1287 if(tested_protocol == HTTP_TEST)
1288 ok(hres == S_OK || hres == E_PENDING || hres == S_FALSE, "Read failed: %08x\n", hres);
1289 else
1290 ok(hres == S_OK, "Read failed: %08x\n", hres);
1291 CHECK_CALLED(Read);
1293 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1294 hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE, text_htmlW);
1295 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1296 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1298 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1299 hres = IInternetProtocolSink_ReportProgress(filtered_sink, BINDSTATUS_MIMETYPEAVAILABLE, text_htmlW);
1300 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1301 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1303 /* FIXME: test BINDSTATUS_CACHEFILENAMEAVAILABLE */
1306 if(no_mime && prot_read<200) {
1307 SET_EXPECT(Read);
1308 }else if(no_mime && prot_read<300) {
1309 report_mime = TRUE;
1310 SET_EXPECT(Read);
1311 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1312 SET_EXPECT(ReportData);
1313 }else if(!read_report_data) {
1314 SET_EXPECT(ReportData);
1316 hres = IInternetProtocolSink_ReportData(filtered_sink, grfBSCF, ulProgress, ulProgressMax);
1317 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1318 if(no_mime && prot_read<=200) {
1319 CHECK_CALLED(Read);
1320 }else if(report_mime) {
1321 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1322 CHECK_CALLED(ReportData);
1323 }else if(!read_report_data) {
1324 CHECK_CALLED(ReportData);
1327 if(!filter_state)
1328 filter_state = 1;
1330 return S_OK;
1333 static HRESULT WINAPI MimeProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
1334 DWORD dwError, LPCWSTR szResult)
1336 HRESULT hres;
1338 CHECK_EXPECT(MimeFilter_ReportResult);
1340 ok(hrResult == S_OK, "hrResult = %08x\n", hrResult);
1341 ok(dwError == ERROR_SUCCESS, "dwError = %u\n", dwError);
1342 ok(!szResult, "szResult = %s\n", wine_dbgstr_w(szResult));
1344 SET_EXPECT(ReportResult);
1345 hres = IInternetProtocolSink_ReportResult(filtered_sink, hrResult, dwError, szResult);
1346 ok(SUCCEEDED(hres), "ReportResult failed: %08x\n", hres);
1347 CHECK_CALLED(ReportResult);
1349 return S_OK;
1352 static IInternetProtocolSinkVtbl mime_protocol_sink_vtbl = {
1353 MimeProtocolSink_QueryInterface,
1354 MimeProtocolSink_AddRef,
1355 MimeProtocolSink_Release,
1356 MimeProtocolSink_Switch,
1357 MimeProtocolSink_ReportProgress,
1358 MimeProtocolSink_ReportData,
1359 MimeProtocolSink_ReportResult
1362 static IInternetProtocolSink mime_protocol_sink = { &mime_protocol_sink_vtbl };
1364 static HRESULT QueryInterface(REFIID riid, void **ppv)
1366 static const IID IID_undocumented = {0x58DFC7D0,0x5381,0x43E5,{0x9D,0x72,0x4C,0xDD,0xE4,0xCB,0x0F,0x1A}};
1367 static const IID IID_undocumentedIE10 = {0xc28722e5,0xbc1a,0x4c55,{0xa6,0x8d,0x33,0x21,0x9f,0x69,0x89,0x10}};
1369 *ppv = NULL;
1371 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid))
1372 *ppv = &protocol_sink;
1373 if(IsEqualGUID(&IID_IServiceProvider, riid))
1374 *ppv = &service_provider;
1375 if(IsEqualGUID(&IID_IUriContainer, riid))
1376 return E_NOINTERFACE; /* TODO */
1378 /* NOTE: IE8 queries for undocumented {58DFC7D0-5381-43E5-9D72-4CDDE4CB0F1A} interface. */
1379 if(IsEqualGUID(&IID_undocumented, riid))
1380 return E_NOINTERFACE;
1381 /* NOTE: IE10 queries for undocumented {c28722e5-bc1a-4c55-a68d-33219f698910} interface. */
1382 if(IsEqualGUID(&IID_undocumentedIE10, riid))
1383 return E_NOINTERFACE;
1385 if(*ppv)
1386 return S_OK;
1388 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
1389 return E_NOINTERFACE;
1392 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
1394 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
1395 *ppv = iface;
1396 return S_OK;
1398 return E_NOINTERFACE;
1401 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
1403 return 2;
1406 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
1408 return 1;
1411 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
1413 DWORD cbSize;
1415 CHECK_EXPECT(GetBindInfo);
1417 ok(grfBINDF != NULL, "grfBINDF == NULL\n");
1418 ok(pbindinfo != NULL, "pbindinfo == NULL\n");
1419 ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
1421 *grfBINDF = bindf;
1422 if(binding_test)
1423 *grfBINDF |= BINDF_FROMURLMON;
1424 cbSize = pbindinfo->cbSize;
1425 memset(pbindinfo, 0, cbSize);
1426 pbindinfo->cbSize = cbSize;
1427 pbindinfo->dwOptions = bindinfo_options;
1429 if(http_post_test)
1431 pbindinfo->cbstgmedData = sizeof(post_data)-1;
1432 pbindinfo->dwBindVerb = BINDVERB_POST;
1433 pbindinfo->stgmedData.tymed = http_post_test;
1435 if(http_post_test == TYMED_HGLOBAL) {
1436 HGLOBAL data;
1438 /* Must be GMEM_FIXED, GMEM_MOVABLE does not work properly */
1439 data = GlobalAlloc(GPTR, sizeof(post_data));
1440 memcpy(data, post_data, sizeof(post_data));
1441 U(pbindinfo->stgmedData).hGlobal = data;
1442 }else {
1443 U(pbindinfo->stgmedData).pstm = &Stream;
1447 return S_OK;
1450 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType,
1451 LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
1453 ok(ppwzStr != NULL, "ppwzStr == NULL\n");
1454 ok(pcElFetched != NULL, "pcElFetched == NULL\n");
1456 switch(ulStringType) {
1457 case BINDSTRING_ACCEPT_MIMES:
1458 CHECK_EXPECT(GetBindString_ACCEPT_MIMES);
1459 ok(cEl == 256, "cEl=%d, expected 256\n", cEl);
1460 if(pcElFetched) {
1461 ok(*pcElFetched == 256, "*pcElFetched=%d, expected 256\n", *pcElFetched);
1462 *pcElFetched = 1;
1464 if(ppwzStr) {
1465 *ppwzStr = CoTaskMemAlloc(sizeof(acc_mimeW));
1466 memcpy(*ppwzStr, acc_mimeW, sizeof(acc_mimeW));
1468 return S_OK;
1469 case BINDSTRING_USER_AGENT:
1470 CHECK_EXPECT(GetBindString_USER_AGENT);
1471 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1472 if(pcElFetched) {
1473 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1474 *pcElFetched = 1;
1476 if(ppwzStr) {
1477 *ppwzStr = CoTaskMemAlloc(sizeof(user_agentW));
1478 memcpy(*ppwzStr, user_agentW, sizeof(user_agentW));
1480 return S_OK;
1481 case BINDSTRING_POST_COOKIE:
1482 CHECK_EXPECT(GetBindString_POST_COOKIE);
1483 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1484 if(pcElFetched)
1485 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1486 return S_OK;
1487 case BINDSTRING_URL: {
1488 DWORD size;
1490 CHECK_EXPECT(GetBindString_URL);
1491 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1492 ok(*pcElFetched == 0, "*pcElFetch=%d, expected 0\n", *pcElFetched);
1493 *pcElFetched = 1;
1495 size = (lstrlenW(binding_urls[tested_protocol])+1)*sizeof(WCHAR);
1496 *ppwzStr = CoTaskMemAlloc(size);
1497 memcpy(*ppwzStr, binding_urls[tested_protocol], size);
1498 return S_OK;
1500 case BINDSTRING_ROOTDOC_URL:
1501 CHECK_EXPECT(GetBindString_ROOTDOC_URL);
1502 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1503 return E_NOTIMPL;
1504 case BINDSTRING_ENTERPRISE_ID:
1505 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1506 return E_NOTIMPL;
1507 case BINDSTRING_SAMESITE_COOKIE_LEVEL:
1508 CHECK_EXPECT(GetBindString_SAMESITE_COOKIE_LEVEL);
1509 ok(cEl == 1, "cEl=%d, expected 1\n", cEl);
1510 return E_NOTIMPL;
1511 default:
1512 ok(0, "unexpected ulStringType %d\n", ulStringType);
1515 return E_NOTIMPL;
1518 static IInternetBindInfoVtbl bind_info_vtbl = {
1519 BindInfo_QueryInterface,
1520 BindInfo_AddRef,
1521 BindInfo_Release,
1522 BindInfo_GetBindInfo,
1523 BindInfo_GetBindString
1526 static IInternetBindInfo bind_info = { &bind_info_vtbl };
1528 static Protocol *impl_from_IInternetPriority(IInternetPriority *iface)
1530 return CONTAINING_RECORD(iface, Protocol, IInternetPriority_iface);
1533 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
1534 REFIID riid, void **ppv)
1536 ok(0, "unexpected call\n");
1537 return E_NOINTERFACE;
1540 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
1542 Protocol *This = impl_from_IInternetPriority(iface);
1543 if (This->outer)
1545 This->outer_ref++;
1546 return IUnknown_AddRef(This->outer);
1548 return IUnknown_AddRef(&This->IUnknown_inner);
1551 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
1553 Protocol *This = impl_from_IInternetPriority(iface);
1554 if (This->outer)
1556 This->outer_ref--;
1557 return IUnknown_Release(This->outer);
1559 return IUnknown_Release(&This->IUnknown_inner);
1562 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
1564 CHECK_EXPECT(SetPriority);
1565 ok(nPriority == ex_priority, "nPriority=%d\n", nPriority);
1566 return S_OK;
1569 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
1571 ok(0, "unexpected call\n");
1572 return E_NOTIMPL;
1576 static const IInternetPriorityVtbl InternetPriorityVtbl = {
1577 InternetPriority_QueryInterface,
1578 InternetPriority_AddRef,
1579 InternetPriority_Release,
1580 InternetPriority_SetPriority,
1581 InternetPriority_GetPriority
1584 static ULONG WINAPI Protocol_AddRef(IInternetProtocolEx *iface)
1586 return 2;
1589 static ULONG WINAPI Protocol_Release(IInternetProtocolEx *iface)
1591 return 1;
1594 static HRESULT WINAPI Protocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
1595 DWORD dwOptions)
1597 HRESULT hres;
1599 CHECK_EXPECT(Abort);
1601 SET_EXPECT(ReportResult);
1602 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
1603 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1604 CHECK_CALLED(ReportResult);
1606 return S_OK;
1609 static HRESULT WINAPI Protocol_Suspend(IInternetProtocolEx *iface)
1611 ok(0, "unexpected call\n");
1612 return E_NOTIMPL;
1615 static HRESULT WINAPI Protocol_Resume(IInternetProtocolEx *iface)
1617 ok(0, "unexpected call\n");
1618 return E_NOTIMPL;
1621 static HRESULT WINAPI Protocol_Seek(IInternetProtocolEx *iface,
1622 LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
1624 ok(0, "unexpected call\n");
1625 return E_NOTIMPL;
1628 static Protocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
1630 return CONTAINING_RECORD(iface, Protocol, IInternetProtocolEx_iface);
1633 static HRESULT WINAPI ProtocolEmul_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
1635 Protocol *This = impl_from_IInternetProtocolEx(iface);
1637 static const IID unknown_iid = {0x7daf9908,0x8415,0x4005,{0x95,0xae, 0xbd,0x27,0xf6,0xe3,0xdc,0x00}};
1638 static const IID unknown_iid2 = {0x5b7ebc0c,0xf630,0x4cea,{0x89,0xd3,0x5a,0xf0,0x38,0xed,0x05,0x5c}};
1640 if(IsEqualGUID(riid, &IID_IInternetProtocolEx)) {
1641 *ppv = &This->IInternetProtocolEx_iface;
1642 IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
1643 return S_OK;
1646 /* FIXME: Why is it calling here instead of outer IUnknown? */
1647 if(IsEqualGUID(riid, &IID_IInternetPriority)) {
1648 *ppv = &This->IInternetPriority_iface;
1649 IInternetPriority_AddRef(&This->IInternetPriority_iface);
1650 return S_OK;
1652 if(!IsEqualGUID(riid, &unknown_iid) && !IsEqualGUID(riid, &unknown_iid2)) /* IE10 */
1653 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
1654 *ppv = NULL;
1655 return E_NOINTERFACE;
1658 static ULONG WINAPI ProtocolEmul_AddRef(IInternetProtocolEx *iface)
1660 Protocol *This = impl_from_IInternetProtocolEx(iface);
1661 if (This->outer)
1663 This->outer_ref++;
1664 return IUnknown_AddRef(This->outer);
1666 return IUnknown_AddRef(&This->IUnknown_inner);
1669 static ULONG WINAPI ProtocolEmul_Release(IInternetProtocolEx *iface)
1671 Protocol *This = impl_from_IInternetProtocolEx(iface);
1672 if (This->outer)
1674 This->outer_ref--;
1675 return IUnknown_Release(This->outer);
1677 return IUnknown_Release(&This->IUnknown_inner);
1680 static DWORD WINAPI thread_proc(PVOID arg)
1682 BOOL redirect = redirect_on_continue;
1683 HRESULT hres;
1685 memset(&protocoldata, -1, sizeof(protocoldata));
1687 while(1) {
1688 prot_state = 0;
1690 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
1691 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1692 BINDSTATUS_FINDINGRESOURCE, hostW);
1693 CHECK_CALLED(ReportProgress_FINDINGRESOURCE);
1694 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1696 SET_EXPECT(ReportProgress_CONNECTING);
1697 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1698 BINDSTATUS_CONNECTING, winehq_ipW);
1699 CHECK_CALLED(ReportProgress_CONNECTING);
1700 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1702 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1703 hres = IInternetProtocolSink_ReportProgress(binding_sink,
1704 BINDSTATUS_SENDINGREQUEST, NULL);
1705 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1706 ok(hres == S_OK, "ReportProgress failed: %08x\n", hres);
1708 prot_state = 1;
1709 SET_EXPECT(Switch);
1710 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1711 CHECK_CALLED(Switch);
1712 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1714 if(!redirect)
1715 break;
1716 redirect = FALSE;
1719 if(!short_read) {
1720 prot_state = 2;
1721 if(mimefilter_test)
1722 SET_EXPECT(MimeFilter_Switch);
1723 else
1724 SET_EXPECT(Switch);
1725 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1726 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1727 if(mimefilter_test)
1728 CHECK_CALLED(MimeFilter_Switch);
1729 else
1730 CHECK_CALLED(Switch);
1732 if(test_abort) {
1733 SetEvent(event_complete);
1734 return 0;
1737 prot_state = 2;
1738 if(mimefilter_test)
1739 SET_EXPECT(MimeFilter_Switch);
1740 else
1741 SET_EXPECT(Switch);
1742 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1743 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1744 if(mimefilter_test)
1745 CHECK_CALLED(MimeFilter_Switch);
1746 else
1747 CHECK_CALLED(Switch);
1749 prot_state = 3;
1750 if(mimefilter_test)
1751 SET_EXPECT(MimeFilter_Switch);
1752 else
1753 SET_EXPECT(Switch);
1754 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
1755 ok(hres == S_OK, "Switch failed: %08x\n", hres);
1756 if(mimefilter_test)
1757 CHECK_CALLED(MimeFilter_Switch);
1758 else
1759 CHECK_CALLED(Switch);
1762 SetEvent(event_complete);
1764 return 0;
1767 static void protocol_start(IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD pi)
1769 BINDINFO bindinfo, exp_bindinfo;
1770 DWORD cbindf = 0;
1771 HRESULT hres;
1773 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
1774 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
1775 ok(pOIProtSink != &protocol_sink, "unexpected pOIProtSink\n");
1776 ok(pOIBindInfo != &bind_info, "unexpected pOIBindInfo\n");
1777 ok(!pi, "pi = %x\n", pi);
1779 if(binding_test)
1780 ok(pOIProtSink == binding_sink, "pOIProtSink != binding_sink\n");
1782 memset(&bindinfo, 0, sizeof(bindinfo));
1783 bindinfo.cbSize = sizeof(bindinfo);
1784 memcpy(&exp_bindinfo, &bindinfo, sizeof(bindinfo));
1785 if(test_redirect)
1786 exp_bindinfo.dwOptions = bindinfo_options;
1787 SET_EXPECT(GetBindInfo);
1788 if(redirect_on_continue && (bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
1789 SET_EXPECT(QueryService_IBindCallbackRedirect);
1790 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
1791 if(redirect_on_continue && (bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS))
1792 CHECK_CALLED(QueryService_IBindCallbackRedirect);
1793 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
1794 CHECK_CALLED(GetBindInfo);
1795 ok(cbindf == (bindf|BINDF_FROMURLMON), "bindf = %x, expected %x\n",
1796 cbindf, (bindf|BINDF_FROMURLMON));
1797 ok(!memcmp(&exp_bindinfo, &bindinfo, sizeof(bindinfo)), "unexpected bindinfo\n");
1798 pReleaseBindInfo(&bindinfo);
1800 SET_EXPECT(ReportProgress_SENDINGREQUEST);
1801 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, emptyW);
1802 ok(hres == S_OK, "ReportProgress(BINDSTATUS_SENDINGREQUEST) failed: %08x\n", hres);
1803 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
1805 if(tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST) {
1806 IServiceProvider *service_provider;
1807 IHttpNegotiate *http_negotiate;
1808 IHttpNegotiate2 *http_negotiate2;
1809 LPWSTR ua = (LPWSTR)0xdeadbeef, accept_mimes[256];
1810 LPWSTR additional_headers = NULL;
1811 BYTE sec_id[100];
1812 DWORD fetched = 0, size = 100;
1813 DWORD tid;
1815 SET_EXPECT(GetBindString_USER_AGENT);
1816 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT,
1817 &ua, 1, &fetched);
1818 CHECK_CALLED(GetBindString_USER_AGENT);
1819 ok(hres == S_OK, "GetBindString(BINDSTRING_USER_AGETNT) failed: %08x\n", hres);
1820 ok(fetched == 1, "fetched = %d, expected 254\n", fetched);
1821 ok(ua != NULL, "ua = %p\n", ua);
1822 ok(!lstrcmpW(ua, user_agentW), "unexpected user agent %s\n", wine_dbgstr_w(ua));
1823 CoTaskMemFree(ua);
1825 fetched = 256;
1826 SET_EXPECT(GetBindString_ACCEPT_MIMES);
1827 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES,
1828 accept_mimes, 256, &fetched);
1829 CHECK_CALLED(GetBindString_ACCEPT_MIMES);
1831 ok(hres == S_OK,
1832 "GetBindString(BINDSTRING_ACCEPT_MIMES) failed: %08x\n", hres);
1833 ok(fetched == 1, "fetched = %d, expected 1\n", fetched);
1834 ok(!lstrcmpW(acc_mimeW, accept_mimes[0]), "unexpected mimes %s\n", wine_dbgstr_w(accept_mimes[0]));
1835 CoTaskMemFree(accept_mimes[0]);
1837 hres = IInternetBindInfo_QueryInterface(pOIBindInfo, &IID_IServiceProvider,
1838 (void**)&service_provider);
1839 ok(hres == S_OK, "QueryInterface failed: %08x\n", hres);
1841 SET_EXPECT(QueryService_HttpNegotiate);
1842 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
1843 &IID_IHttpNegotiate, (void**)&http_negotiate);
1844 CHECK_CALLED(QueryService_HttpNegotiate);
1845 ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1847 SET_EXPECT(BeginningTransaction);
1848 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, binding_urls[tested_protocol],
1849 NULL, 0, &additional_headers);
1850 CHECK_CALLED(BeginningTransaction);
1851 IHttpNegotiate_Release(http_negotiate);
1852 ok(hres == S_OK, "BeginningTransction failed: %08x\n", hres);
1853 ok(additional_headers == NULL, "additional_headers=%p\n", additional_headers);
1855 SET_EXPECT(QueryService_HttpNegotiate);
1856 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
1857 &IID_IHttpNegotiate2, (void**)&http_negotiate2);
1858 CHECK_CALLED(QueryService_HttpNegotiate);
1859 ok(hres == S_OK, "QueryService failed: %08x\n", hres);
1861 size = 512;
1862 SET_EXPECT(GetRootSecurityId);
1863 hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, sec_id, &size, 0);
1864 CHECK_CALLED(GetRootSecurityId);
1865 IHttpNegotiate2_Release(http_negotiate2);
1866 ok(hres == E_FAIL, "GetRootSecurityId failed: %08x, expected E_FAIL\n", hres);
1867 ok(size == 13, "size=%d\n", size);
1869 IServiceProvider_Release(service_provider);
1871 if(!reuse_protocol_thread)
1872 CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
1873 return;
1876 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
1877 hres = IInternetProtocolSink_ReportProgress(pOIProtSink,
1878 BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
1879 ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
1880 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
1882 if(mimefilter_test) {
1883 SET_EXPECT(MimeFilter_CreateInstance);
1884 SET_EXPECT(MimeFilter_Start);
1885 SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
1887 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
1888 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
1889 mimefilter_test ? pjpegW : (expect_wsz = text_htmlW));
1890 ok(hres == S_OK,
1891 "ReportProgress(BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE) failed: %08x\n", hres);
1892 if(mimefilter_test) {
1893 CHECK_CALLED(MimeFilter_CreateInstance);
1894 CHECK_CALLED(MimeFilter_Start);
1895 CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
1896 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1897 }else {
1898 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
1901 if(mimefilter_test)
1902 SET_EXPECT(MimeFilter_ReportData);
1903 else
1904 SET_EXPECT(ReportData);
1905 hres = IInternetProtocolSink_ReportData(pOIProtSink,
1906 BSCF_FIRSTDATANOTIFICATION | (tested_protocol == ITS_TEST ? BSCF_DATAFULLYAVAILABLE : BSCF_LASTDATANOTIFICATION),
1907 13, 13);
1908 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
1909 if(mimefilter_test)
1910 CHECK_CALLED(MimeFilter_ReportData);
1911 else
1912 CHECK_CALLED(ReportData);
1914 if(tested_protocol == ITS_TEST) {
1915 SET_EXPECT(ReportData);
1916 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
1917 ok(hres == S_OK, "ReportProgress(BINDSTATUS_BEGINDOWNLOADDATA) failed: %08x\n", hres);
1918 CHECK_CALLED(ReportData);
1921 if(tested_protocol == BIND_TEST) {
1922 hres = IInternetProtocol_Terminate(binding_protocol, 0);
1923 ok(hres == E_FAIL, "Termiante failed: %08x\n", hres);
1926 if(mimefilter_test)
1927 SET_EXPECT(MimeFilter_ReportResult);
1928 else
1929 SET_EXPECT(ReportResult);
1930 hres = IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
1931 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1932 if(mimefilter_test)
1933 CHECK_CALLED(MimeFilter_ReportResult);
1934 else
1935 CHECK_CALLED(ReportResult);
1938 static HRESULT WINAPI ProtocolEmul_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
1939 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
1940 DWORD grfPI, HANDLE_PTR dwReserved)
1942 CHECK_EXPECT(Start);
1944 ok(!dwReserved, "dwReserved = %lx\n", dwReserved);
1945 protocol_start(pOIProtSink, pOIBindInfo, grfPI);
1946 return S_OK;
1949 static HRESULT WINAPI ProtocolEmul_Continue(IInternetProtocolEx *iface,
1950 PROTOCOLDATA *pProtocolData)
1952 DWORD bscf = 0, pr;
1953 HRESULT hres;
1955 CHECK_EXPECT(Continue);
1957 ok(pProtocolData != NULL, "pProtocolData == NULL\n");
1958 if(!pProtocolData || tested_protocol == BIND_TEST)
1959 return S_OK;
1960 if(binding_test) {
1961 ok(pProtocolData != &protocoldata, "pProtocolData == &protocoldata\n");
1962 ok(pProtocolData->grfFlags == protocoldata.grfFlags, "grfFlags wrong %x/%x\n",
1963 pProtocolData->grfFlags, protocoldata.grfFlags );
1964 ok(pProtocolData->dwState == protocoldata.dwState, "dwState wrong %x/%x\n",
1965 pProtocolData->dwState, protocoldata.dwState );
1966 ok(pProtocolData->pData == protocoldata.pData, "pData wrong %p/%p\n",
1967 pProtocolData->pData, protocoldata.pData );
1968 ok(pProtocolData->cbData == protocoldata.cbData, "cbData wrong %x/%x\n",
1969 pProtocolData->cbData, protocoldata.cbData );
1972 switch(prot_state) {
1973 case 1: {
1974 IServiceProvider *service_provider;
1975 IHttpNegotiate *http_negotiate;
1976 static const WCHAR header[] = {'?',0};
1977 static const WCHAR redirect_urlW[] = {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',
1978 '/','t','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
1980 if(redirect_on_continue) {
1981 redirect_on_continue = FALSE;
1982 reuse_protocol_thread = TRUE;
1984 if(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)
1985 SET_EXPECT(Redirect);
1986 SET_EXPECT(ReportProgress_REDIRECTING);
1987 SET_EXPECT(Terminate);
1988 SET_EXPECT(Protocol_destructor);
1989 SET_EXPECT(QueryService_InternetProtocol);
1990 SET_EXPECT(CreateInstance);
1991 SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
1992 SET_EXPECT(SetPriority);
1993 SET_EXPECT(Start);
1994 hres = IInternetProtocolSink_ReportResult(binding_sink, INET_E_REDIRECT_FAILED, ERROR_SUCCESS, redirect_urlW);
1995 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
1996 if(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)
1997 CHECK_CALLED(Redirect);
1998 CHECK_CALLED(ReportProgress_REDIRECTING);
1999 CHECK_CALLED(Terminate);
2000 CHECK_CALLED(Protocol_destructor);
2001 CHECK_CALLED(QueryService_InternetProtocol);
2002 CHECK_CALLED(CreateInstance);
2003 CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
2004 todo_wine CHECK_NOT_CALLED(SetPriority);
2005 CHECK_CALLED(Start);
2007 return S_OK;
2010 hres = IInternetProtocolSink_QueryInterface(binding_sink, &IID_IServiceProvider,
2011 (void**)&service_provider);
2012 ok(hres == S_OK, "Could not get IServiceProvicder\n");
2014 SET_EXPECT(QueryService_HttpNegotiate);
2015 hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate,
2016 &IID_IHttpNegotiate, (void**)&http_negotiate);
2017 IServiceProvider_Release(service_provider);
2018 CHECK_CALLED(QueryService_HttpNegotiate);
2019 ok(hres == S_OK, "Could not get IHttpNegotiate\n");
2021 SET_EXPECT(OnResponse);
2022 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, header, NULL, NULL);
2023 IHttpNegotiate_Release(http_negotiate);
2024 CHECK_CALLED(OnResponse);
2025 IHttpNegotiate_Release(http_negotiate);
2026 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
2028 if(mimefilter_test) {
2029 SET_EXPECT(MimeFilter_CreateInstance);
2030 SET_EXPECT(MimeFilter_Start);
2031 SET_EXPECT(ReportProgress_LOADINGMIMEHANDLER);
2032 }else if(!(pi & PI_MIMEVERIFICATION)) {
2033 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2035 hres = IInternetProtocolSink_ReportProgress(binding_sink,
2036 BINDSTATUS_MIMETYPEAVAILABLE, mimefilter_test ? pjpegW : text_htmlW);
2037 if(mimefilter_test) {
2038 CHECK_CALLED(MimeFilter_CreateInstance);
2039 CHECK_CALLED(MimeFilter_Start);
2040 CHECK_CALLED(ReportProgress_LOADINGMIMEHANDLER);
2041 }else if(!(pi & PI_MIMEVERIFICATION)) {
2042 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2044 ok(hres == S_OK,
2045 "ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE) failed: %08x\n", hres);
2047 bscf |= BSCF_FIRSTDATANOTIFICATION;
2048 break;
2050 case 2:
2051 case 3:
2052 bscf = BSCF_INTERMEDIATEDATANOTIFICATION;
2053 break;
2056 pr = prot_read;
2057 if(mimefilter_test)
2058 SET_EXPECT(MimeFilter_ReportData);
2059 if((!mimefilter_test || no_mime) && (pi & PI_MIMEVERIFICATION)) {
2060 if(pr < 200)
2061 SET_EXPECT(Read); /* checked in ReportData for short_read */
2062 if(pr == 200) {
2063 if(!mimefilter_test)
2064 SET_EXPECT(Read); /* checked in BINDSTATUS_MIMETYPEAVAILABLE or ReportData */
2065 SET_EXPECT(GetBindInfo);
2066 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2068 if(pr >= 200)
2069 SET_EXPECT(ReportData);
2070 }else {
2071 SET_EXPECT(ReportData);
2074 hres = IInternetProtocolSink_ReportData(binding_sink, bscf, pr, 400);
2075 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2077 if(mimefilter_test) {
2078 SET_EXPECT(MimeFilter_ReportData);
2079 }else if(pi & PI_MIMEVERIFICATION) {
2080 if(!short_read && pr < 200)
2081 CHECK_CALLED(Read);
2082 if(pr == 200) {
2083 CLEAR_CALLED(GetBindInfo); /* IE9 */
2084 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2086 }else {
2087 CHECK_CALLED(ReportData);
2090 if(prot_state == 3)
2091 prot_state = 4;
2093 return S_OK;
2096 static HRESULT WINAPI ProtocolEmul_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2098 CHECK_EXPECT(Terminate);
2099 ok(!dwOptions, "dwOptions=%d\n", dwOptions);
2100 return S_OK;
2103 static HRESULT WINAPI ProtocolEmul_Read(IInternetProtocolEx *iface, void *pv,
2104 ULONG cb, ULONG *pcbRead)
2106 if(read_report_data)
2107 CHECK_EXPECT2(Read2);
2109 if(mimefilter_test || short_read) {
2110 if(!read_report_data)
2111 CHECK_EXPECT2(Read);
2112 }else if((pi & PI_MIMEVERIFICATION)) {
2113 if(!read_report_data)
2114 CHECK_EXPECT2(Read);
2116 if(prot_read < 300) {
2117 ok(pv != expect_pv, "pv == expect_pv\n");
2118 if(prot_read < 300)
2119 ok(cb == 2048-prot_read, "cb=%d\n", cb);
2120 else
2121 ok(cb == 700, "cb=%d\n", cb);
2122 }else {
2123 ok(expect_pv <= pv && (BYTE*)pv < (BYTE*)expect_pv + cb, "pv != expect_pv\n");
2125 }else {
2126 if(!read_report_data)
2127 CHECK_EXPECT(Read);
2129 ok(pv == expect_pv, "pv != expect_pv\n");
2130 ok(cb == 1000, "cb=%d\n", cb);
2131 ok(!*pcbRead, "*pcbRead = %d\n", *pcbRead);
2133 ok(pcbRead != NULL, "pcbRead == NULL\n");
2135 if(prot_state == 3 || (short_read && prot_state != 4)) {
2136 HRESULT hres;
2138 prot_state = 4;
2139 if(short_read) {
2140 SET_EXPECT(Read2); /* checked in BINDSTATUS_MIMETYPEAVAILABLE */
2141 SET_EXPECT(GetBindInfo);
2142 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2144 if(mimefilter_test)
2145 SET_EXPECT(MimeFilter_ReportData);
2146 else if(direct_read)
2147 SET_EXPECT(ReportData2);
2148 read_report_data++;
2149 hres = IInternetProtocolSink_ReportData(binding_sink,
2150 BSCF_LASTDATANOTIFICATION|BSCF_INTERMEDIATEDATANOTIFICATION, 0, 0);
2151 read_report_data--;
2152 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
2153 if(short_read) {
2154 CLEAR_CALLED(GetBindInfo); /* IE9 */
2155 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2157 if(mimefilter_test)
2158 CHECK_CALLED(MimeFilter_ReportData);
2159 else if(direct_read)
2160 CHECK_CALLED(ReportData2);
2162 if(mimefilter_test)
2163 SET_EXPECT(MimeFilter_ReportResult);
2164 else
2165 SET_EXPECT(ReportResult);
2166 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
2167 ok(hres == S_OK, "ReportResult failed: %08x\n", hres);
2168 if(mimefilter_test)
2169 CHECK_CALLED(MimeFilter_ReportResult);
2170 else
2171 CHECK_CALLED(ReportResult);
2173 if(cb > 100)
2174 cb = 100;
2175 memset(pv, 'x', cb);
2176 if(cb>6)
2177 memcpy(pv, "gif87a", 6);
2178 prot_read += *pcbRead = cb;
2179 return S_OK;
2182 if(prot_state == 4) {
2183 *pcbRead = 0;
2184 return S_FALSE;
2187 if((async_read_pending = !async_read_pending)) {
2188 *pcbRead = 0;
2189 return tested_protocol == HTTP_TEST || tested_protocol == HTTPS_TEST ? E_PENDING : S_FALSE;
2192 if(cb > 100)
2193 cb = 100;
2194 memset(pv, 'x', cb);
2195 if(cb>6)
2196 memcpy(pv, "gif87a", 6);
2197 prot_read += *pcbRead = cb;
2198 return S_OK;
2201 static HRESULT WINAPI ProtocolEmul_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2203 CHECK_EXPECT(LockRequest);
2204 ok(dwOptions == 0, "dwOptions=%x\n", dwOptions);
2205 return S_OK;
2208 static HRESULT WINAPI ProtocolEmul_UnlockRequest(IInternetProtocolEx *iface)
2210 CHECK_EXPECT(UnlockRequest);
2211 return S_OK;
2214 static HRESULT WINAPI ProtocolEmul_StartEx(IInternetProtocolEx *iface, IUri *pUri,
2215 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2216 DWORD grfPI, HANDLE *dwReserved)
2218 CHECK_EXPECT(StartEx);
2219 ok(!dwReserved, "dwReserved = %p\n", dwReserved);
2220 protocol_start(pOIProtSink, pOIBindInfo, grfPI);
2221 return S_OK;
2224 static const IInternetProtocolExVtbl ProtocolVtbl = {
2225 ProtocolEmul_QueryInterface,
2226 ProtocolEmul_AddRef,
2227 ProtocolEmul_Release,
2228 ProtocolEmul_Start,
2229 ProtocolEmul_Continue,
2230 Protocol_Abort,
2231 ProtocolEmul_Terminate,
2232 Protocol_Suspend,
2233 Protocol_Resume,
2234 ProtocolEmul_Read,
2235 Protocol_Seek,
2236 ProtocolEmul_LockRequest,
2237 ProtocolEmul_UnlockRequest,
2238 ProtocolEmul_StartEx
2241 static Protocol *impl_from_IUnknown(IUnknown *iface)
2243 return CONTAINING_RECORD(iface, Protocol, IUnknown_inner);
2246 static HRESULT WINAPI ProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2248 static const IID IID_undocumentedIE10 = {0x7daf9908,0x8415,0x4005,{0x95,0xae,0xbd,0x27,0xf6,0xe3,0xdc,0x00}};
2249 Protocol *This = impl_from_IUnknown(iface);
2251 if(IsEqualGUID(&IID_IUnknown, riid)) {
2252 trace("QI(IUnknown)\n");
2253 *ppv = &This->IUnknown_inner;
2254 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
2255 trace("QI(InternetProtocol)\n");
2256 *ppv = &This->IInternetProtocolEx_iface;
2257 }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
2258 trace("QI(InternetProtocolEx)\n");
2259 if(!impl_protex) {
2260 *ppv = NULL;
2261 return E_NOINTERFACE;
2263 *ppv = &This->IInternetProtocolEx_iface;
2264 }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
2265 trace("QI(InternetPriority)\n");
2266 *ppv = &This->IInternetPriority_iface;
2267 }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
2268 trace("QI(IWinInetInfo)\n");
2269 CHECK_EXPECT(QueryInterface_IWinInetInfo);
2270 *ppv = NULL;
2271 return E_NOINTERFACE;
2272 }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
2273 trace("QI(IWinInetHttpInfo)\n");
2274 CHECK_EXPECT(QueryInterface_IWinInetHttpInfo);
2275 *ppv = NULL;
2276 return E_NOINTERFACE;
2277 }else if(IsEqualGUID(&IID_undocumentedIE10, riid)) {
2278 trace("QI(%s)\n", wine_dbgstr_guid(riid));
2279 *ppv = NULL;
2280 return E_NOINTERFACE;
2281 }else {
2282 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
2283 *ppv = NULL;
2284 return E_NOINTERFACE;
2287 IUnknown_AddRef((IUnknown*)*ppv);
2288 return S_OK;
2291 static ULONG WINAPI ProtocolUnk_AddRef(IUnknown *iface)
2293 Protocol *This = impl_from_IUnknown(iface);
2294 return ++This->inner_ref;
2297 static ULONG WINAPI ProtocolUnk_Release(IUnknown *iface)
2299 Protocol *This = impl_from_IUnknown(iface);
2300 LONG ref = --This->inner_ref;
2301 if(!ref) {
2302 /* IE9 is broken on redirects. It will cause -1 outer_ref on original protocol handler
2303 * and 1 on redirected handler. */
2304 ok(!This->outer_ref
2305 || broken(test_redirect && (This->outer_ref == -1 || This->outer_ref == 1)),
2306 "outer_ref = %d\n", This->outer_ref);
2307 if(This->outer_ref)
2308 trace("outer_ref %d\n", This->outer_ref);
2309 CHECK_EXPECT(Protocol_destructor);
2310 heap_free(This);
2312 return ref;
2315 static const IUnknownVtbl ProtocolUnkVtbl = {
2316 ProtocolUnk_QueryInterface,
2317 ProtocolUnk_AddRef,
2318 ProtocolUnk_Release
2321 static HRESULT WINAPI MimeProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
2323 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocol, riid)) {
2324 *ppv = iface;
2325 return S_OK;
2328 if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
2329 *ppv = &mime_protocol_sink;
2330 return S_OK;
2333 ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
2334 *ppv = NULL;
2335 return E_NOINTERFACE;
2338 static HRESULT WINAPI MimeProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
2339 IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
2340 DWORD grfPI, HANDLE_PTR dwReserved)
2342 PROTOCOLFILTERDATA *data;
2343 LPOLESTR url_str = NULL;
2344 DWORD fetched = 0;
2345 BINDINFO bindinfo;
2346 DWORD cbindf = 0;
2347 HRESULT hres;
2349 CHECK_EXPECT(MimeFilter_Start);
2351 ok(!lstrcmpW(szUrl, pjpegW), "wrong url %s\n", wine_dbgstr_w(szUrl));
2352 ok(grfPI == (PI_FILTER_MODE|PI_FORCE_ASYNC), "grfPI=%x, expected PI_FILTER_MODE|PI_FORCE_ASYNC\n", grfPI);
2353 ok(dwReserved, "dwReserved == 0\n");
2354 ok(pOIProtSink != NULL, "pOIProtSink == NULL\n");
2355 ok(pOIBindInfo != NULL, "pOIBindInfo == NULL\n");
2357 if(binding_test) {
2358 ok(pOIProtSink != binding_sink, "pOIProtSink == protocol_sink\n");
2359 ok(pOIBindInfo == prot_bind_info, "pOIBindInfo != bind_info\n");
2360 }else {
2361 ok(pOIProtSink == &protocol_sink, "pOIProtSink != protocol_sink\n");
2362 ok(pOIBindInfo == &bind_info, "pOIBindInfo != bind_info\n");
2365 data = (void*)dwReserved;
2366 ok(data->cbSize == sizeof(*data), "data->cbSize = %d\n", data->cbSize);
2367 ok(!data->pProtocolSink, "data->pProtocolSink != NULL\n");
2368 ok(data->pProtocol != NULL, "data->pProtocol == NULL\n");
2369 ok(!data->pUnk, "data->pUnk != NULL\n");
2370 ok(!data->dwFilterFlags, "data->dwProtocolFlags = %x\n", data->dwFilterFlags);
2371 if(binding_test) {
2372 IInternetProtocolSink *prot_sink;
2374 IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocolSink, (void**)&prot_sink);
2375 ok(prot_sink == pOIProtSink, "QI(data->pProtocol, IID_IInternetProtocolSink) != pOIProtSink\n");
2376 IInternetProtocolSink_Release(prot_sink);
2378 ok(data->pProtocol != binding_protocol, "data->pProtocol == binding_protocol\n");
2380 filtered_protocol = data->pProtocol;
2381 IInternetProtocol_AddRef(filtered_protocol);
2382 }else {
2383 IInternetProtocol *prot;
2385 IInternetProtocol_QueryInterface(data->pProtocol, &IID_IInternetProtocol, (void**)&prot);
2386 ok(prot == async_protocol, "QI(data->pProtocol, IID_IInternetProtocol) != async_protocol\n");
2387 IInternetProtocol_Release(prot);
2389 ok(data->pProtocol != async_protocol, "data->pProtocol == async_protocol\n");
2392 filtered_sink = pOIProtSink;
2394 SET_EXPECT(ReportProgress_DECODING);
2395 hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DECODING, pjpegW);
2396 ok(hres == S_OK, "ReportProgress(BINDSTATUS_DECODING) failed: %08x\n", hres);
2397 CHECK_CALLED(ReportProgress_DECODING);
2399 SET_EXPECT(GetBindInfo);
2400 memset(&bindinfo, 0, sizeof(bindinfo));
2401 bindinfo.cbSize = sizeof(bindinfo);
2402 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &cbindf, &bindinfo);
2403 ok(hres == S_OK, "GetBindInfo failed: %08x\n", hres);
2404 ok(cbindf == (bindf|BINDF_FROMURLMON), "cbindf = %x, expected %x\n", cbindf, bindf);
2405 CHECK_CALLED(GetBindInfo);
2407 SET_EXPECT(GetBindString_URL);
2408 hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_URL, &url_str, 1, &fetched);
2409 ok(hres == S_OK, "GetBindString(BINDSTRING_URL) failed: %08x\n", hres);
2410 ok(fetched == 1, "fetched = %d\n", fetched);
2411 ok(!lstrcmpW(url_str, binding_urls[tested_protocol]), "wrong url_str %s\n", wine_dbgstr_w(url_str));
2412 CoTaskMemFree(url_str);
2413 CHECK_CALLED(GetBindString_URL);
2415 return S_OK;
2418 static HRESULT WINAPI Protocol_Continue(IInternetProtocolEx *iface,
2419 PROTOCOLDATA *pProtocolData)
2421 CHECK_EXPECT(MimeFilter_Continue);
2422 return E_NOTIMPL;
2425 static HRESULT WINAPI MimeProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
2427 HRESULT hres;
2429 CHECK_EXPECT(MimeFilter_Terminate);
2431 ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2433 SET_EXPECT(Terminate);
2434 hres = IInternetProtocol_Terminate(filtered_protocol, dwOptions);
2435 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2436 CHECK_CALLED(Terminate);
2438 return S_OK;
2441 static HRESULT WINAPI MimeProtocol_Read(IInternetProtocolEx *iface, void *pv,
2442 ULONG cb, ULONG *pcbRead)
2444 BYTE buf[2096];
2445 DWORD read = 0;
2446 HRESULT hres;
2448 CHECK_EXPECT(MimeFilter_Read);
2450 ok(pv != NULL, "pv == NULL\n");
2451 ok(cb != 0, "cb == 0\n");
2452 ok(pcbRead != NULL, "pcbRead == NULL\n");
2454 if(read_report_data)
2455 SET_EXPECT(Read2);
2456 else
2457 SET_EXPECT(Read);
2458 hres = IInternetProtocol_Read(filtered_protocol, buf, sizeof(buf), &read);
2459 ok(hres == S_OK || hres == S_FALSE || hres == E_PENDING, "Read failed: %08x\n", hres);
2460 if(read_report_data)
2461 CHECK_CALLED(Read2);
2462 else
2463 CHECK_CALLED(Read);
2465 if(pcbRead) {
2466 ok(*pcbRead == 0, "*pcbRead=%d, expected 0\n", *pcbRead);
2467 *pcbRead = read;
2470 memset(pv, 'x', read);
2471 return hres;
2474 static HRESULT WINAPI MimeProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
2476 HRESULT hres;
2478 CHECK_EXPECT(MimeFilter_LockRequest);
2480 ok(!dwOptions, "dwOptions = %x\n", dwOptions);
2482 SET_EXPECT(LockRequest);
2483 hres = IInternetProtocol_LockRequest(filtered_protocol, dwOptions);
2484 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2485 CHECK_CALLED(LockRequest);
2487 return S_OK;
2490 static HRESULT WINAPI MimeProtocol_UnlockRequest(IInternetProtocolEx *iface)
2492 HRESULT hres;
2494 CHECK_EXPECT(MimeFilter_UnlockRequest);
2496 SET_EXPECT(UnlockRequest);
2497 hres = IInternetProtocol_UnlockRequest(filtered_protocol);
2498 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2499 CHECK_CALLED(UnlockRequest);
2501 return S_OK;
2504 static const IInternetProtocolExVtbl MimeProtocolVtbl = {
2505 MimeProtocol_QueryInterface,
2506 Protocol_AddRef,
2507 Protocol_Release,
2508 MimeProtocol_Start,
2509 Protocol_Continue,
2510 Protocol_Abort,
2511 MimeProtocol_Terminate,
2512 Protocol_Suspend,
2513 Protocol_Resume,
2514 MimeProtocol_Read,
2515 Protocol_Seek,
2516 MimeProtocol_LockRequest,
2517 MimeProtocol_UnlockRequest
2520 static IInternetProtocolEx MimeProtocol = { &MimeProtocolVtbl };
2522 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
2524 ok(0, "unexpected call\n");
2525 return E_NOINTERFACE;
2528 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
2530 return 2;
2533 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
2535 return 1;
2538 static HRESULT WINAPI InternetProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
2539 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
2540 DWORD *pcchResult, DWORD dwReserved)
2542 ok(0, "unexpected call %d\n", ParseAction);
2543 return E_NOTIMPL;
2546 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
2547 LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
2548 LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
2550 ok(0, "unexpected call\n");
2551 return E_NOTIMPL;
2554 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface,
2555 LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
2557 ok(0, "unexpected call\n");
2558 return E_NOTIMPL;
2561 static HRESULT WINAPI InternetProtocolInfo_QueryInfo(IInternetProtocolInfo *iface,
2562 LPCWSTR pwzUrl, QUERYOPTION OueryOption, DWORD dwQueryFlags, LPVOID pBuffer,
2563 DWORD cbBuffer, DWORD *pcbBuf, DWORD dwReserved)
2565 ok(0, "unexpected call\n");
2566 return E_NOTIMPL;
2569 static const IInternetProtocolInfoVtbl InternetProtocolInfoVtbl = {
2570 InternetProtocolInfo_QueryInterface,
2571 InternetProtocolInfo_AddRef,
2572 InternetProtocolInfo_Release,
2573 InternetProtocolInfo_ParseUrl,
2574 InternetProtocolInfo_CombineUrl,
2575 InternetProtocolInfo_CompareUrl,
2576 InternetProtocolInfo_QueryInfo
2579 static IInternetProtocolInfo protocol_info = { &InternetProtocolInfoVtbl };
2581 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
2583 if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
2584 *ppv = &protocol_info;
2585 return S_OK;
2588 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
2589 return E_NOINTERFACE;
2592 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
2594 return 2;
2597 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
2599 return 1;
2602 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
2603 REFIID riid, void **ppv)
2605 Protocol *ret;
2607 ok(ppv != NULL, "ppv == NULL\n");
2609 if(!pOuter) {
2610 CHECK_EXPECT(CreateInstance_no_aggregation);
2611 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2612 }else {
2613 CHECK_EXPECT(CreateInstance);
2614 ok(pOuter == (IUnknown*)prot_bind_info, "pOuter != protocol_unk\n");
2615 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2616 if (no_aggregation) {
2617 *ppv = NULL;
2618 return CLASS_E_NOAGGREGATION;
2622 ret = heap_alloc(sizeof(*ret));
2623 ret->IUnknown_inner.lpVtbl = &ProtocolUnkVtbl;
2624 ret->IInternetProtocolEx_iface.lpVtbl = &ProtocolVtbl;
2625 ret->IInternetPriority_iface.lpVtbl = &InternetPriorityVtbl;
2626 ret->outer = pOuter;
2627 ret->inner_ref = 1;
2628 ret->outer_ref = 0;
2630 protocol_emul = ret;
2631 if (!pOuter)
2632 *ppv = &ret->IInternetProtocolEx_iface;
2633 else
2634 *ppv = &ret->IUnknown_inner;
2635 return S_OK;
2638 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
2640 ok(0, "unexpected call\n");
2641 return S_OK;
2644 static const IClassFactoryVtbl ClassFactoryVtbl = {
2645 ClassFactory_QueryInterface,
2646 ClassFactory_AddRef,
2647 ClassFactory_Release,
2648 ClassFactory_CreateInstance,
2649 ClassFactory_LockServer
2652 static IClassFactory ClassFactory = { &ClassFactoryVtbl };
2654 static HRESULT WINAPI MimeFilter_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
2656 CHECK_EXPECT(MimeFilter_CreateInstance);
2658 ok(!outer, "outer = %p\n", outer);
2659 ok(IsEqualGUID(&IID_IInternetProtocol, riid), "unexpected riid %s\n", wine_dbgstr_guid(riid));
2661 *ppv = &MimeProtocol;
2662 return S_OK;
2665 static const IClassFactoryVtbl MimeFilterCFVtbl = {
2666 ClassFactory_QueryInterface,
2667 ClassFactory_AddRef,
2668 ClassFactory_Release,
2669 MimeFilter_CreateInstance,
2670 ClassFactory_LockServer
2673 static IClassFactory mimefilter_cf = { &MimeFilterCFVtbl };
2675 #define TEST_BINDING 0x0001
2676 #define TEST_FILTER 0x0002
2677 #define TEST_FIRST_HTTP 0x0004
2678 #define TEST_DIRECT_READ 0x0008
2679 #define TEST_POST 0x0010
2680 #define TEST_EMULATEPROT 0x0020
2681 #define TEST_SHORT_READ 0x0040
2682 #define TEST_REDIRECT 0x0080
2683 #define TEST_ABORT 0x0100
2684 #define TEST_ASYNCREQ 0x0200
2685 #define TEST_USEIURI 0x0400
2686 #define TEST_IMPLPROTEX 0x0800
2687 #define TEST_EMPTY 0x1000
2688 #define TEST_NOMIME 0x2000
2689 #define TEST_FROMCACHE 0x4000
2690 #define TEST_DISABLEAUTOREDIRECT 0x8000
2692 static void register_filter(BOOL do_register)
2694 IInternetSession *session;
2695 HRESULT hres;
2697 hres = pCoInternetGetSession(0, &session, 0);
2698 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
2700 if(do_register) {
2701 hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, pjpegW);
2702 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2703 hres = IInternetSession_RegisterMimeFilter(session, &mimefilter_cf, &IID_IInternetProtocol, gifW);
2704 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2705 }else {
2706 hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, pjpegW);
2707 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2708 hres = IInternetSession_UnregisterMimeFilter(session, &mimefilter_cf, gifW);
2709 ok(hres == S_OK, "RegisterMimeFilter failed: %08x\n", hres);
2712 IInternetSession_Release(session);
2715 static void init_test(int prot, DWORD flags)
2717 tested_protocol = prot;
2718 binding_test = (flags & TEST_BINDING) != 0;
2719 first_data_notif = TRUE;
2720 prot_read = 0;
2721 prot_state = 0;
2722 async_read_pending = TRUE;
2723 mimefilter_test = (flags & TEST_FILTER) != 0;
2724 no_mime = (flags & TEST_NOMIME) != 0;
2725 filter_state = 0;
2726 post_stream_read = 0;
2727 ResetEvent(event_complete);
2728 ResetEvent(event_complete2);
2729 ResetEvent(event_continue);
2730 ResetEvent(event_continue_done);
2731 async_protocol = binding_protocol = filtered_protocol = NULL;
2732 filtered_sink = NULL;
2733 http_is_first = (flags & TEST_FIRST_HTTP) != 0;
2734 first_data_notif = TRUE;
2735 state = STATE_CONNECTING;
2736 test_async_req = (flags & TEST_ASYNCREQ) != 0;
2737 direct_read = (flags & TEST_DIRECT_READ) != 0;
2738 emulate_prot = (flags & TEST_EMULATEPROT) != 0;
2739 wait_for_switch = TRUE;
2740 short_read = (flags & TEST_SHORT_READ) != 0;
2741 http_post_test = TYMED_NULL;
2742 redirect_on_continue = test_redirect = (flags & TEST_REDIRECT) != 0;
2743 test_abort = (flags & TEST_ABORT) != 0;
2744 impl_protex = (flags & TEST_IMPLPROTEX) != 0;
2745 empty_file = (flags & TEST_EMPTY) != 0;
2746 bind_from_cache = (flags & TEST_FROMCACHE) != 0;
2747 file_with_hash = FALSE;
2748 security_problem = FALSE;
2749 reuse_protocol_thread = FALSE;
2751 bindinfo_options = 0;
2752 if(flags & TEST_DISABLEAUTOREDIRECT)
2753 bindinfo_options |= BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS;
2755 register_filter(mimefilter_test);
2758 static void test_priority(IInternetProtocol *protocol)
2760 IInternetPriority *priority;
2761 LONG pr;
2762 HRESULT hres;
2764 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority,
2765 (void**)&priority);
2766 ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
2767 if(FAILED(hres))
2768 return;
2770 hres = IInternetPriority_GetPriority(priority, &pr);
2771 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2772 ok(pr == 0, "pr=%d, expected 0\n", pr);
2774 hres = IInternetPriority_SetPriority(priority, 1);
2775 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
2777 hres = IInternetPriority_GetPriority(priority, &pr);
2778 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
2779 ok(pr == 1, "pr=%d, expected 1\n", pr);
2781 IInternetPriority_Release(priority);
2784 static void test_early_abort(const CLSID *clsid)
2786 IInternetProtocol *protocol;
2787 HRESULT hres;
2789 hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2790 &IID_IInternetProtocol, (void**)&protocol);
2791 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2793 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
2794 ok(hres == S_OK, "Abort failed: %08x\n", hres);
2796 hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
2797 ok(hres == S_OK, "Abort failed: %08x\n", hres);
2799 IInternetProtocol_Release(protocol);
2802 static BOOL file_protocol_start(IInternetProtocol *protocol, LPCWSTR url,
2803 IInternetProtocolEx *protocolex, IUri *uri, BOOL is_first)
2805 HRESULT hres;
2807 SET_EXPECT(GetBindInfo);
2808 if(!(bindf & BINDF_FROMURLMON))
2809 SET_EXPECT(ReportProgress_DIRECTBIND);
2810 if(is_first) {
2811 SET_EXPECT(ReportProgress_SENDINGREQUEST);
2812 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
2813 if(bindf & BINDF_FROMURLMON)
2814 SET_EXPECT(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2815 else
2816 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
2818 SET_EXPECT(ReportData);
2819 if(is_first)
2820 SET_EXPECT(ReportResult);
2822 expect_hrResult = S_OK;
2824 if(protocolex) {
2825 hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
2826 ok(hres == S_OK, "StartEx failed: %08x\n", hres);
2827 }else {
2828 hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
2829 if(hres == INET_E_RESOURCE_NOT_FOUND) {
2830 win_skip("Start failed\n");
2831 return FALSE;
2833 ok(hres == S_OK, "Start failed: %08x\n", hres);
2836 CHECK_CALLED(GetBindInfo);
2837 if(!(bindf & BINDF_FROMURLMON))
2838 CLEAR_CALLED(ReportProgress_DIRECTBIND); /* Not called by IE10 */
2839 if(is_first) {
2840 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
2841 CHECK_CALLED(ReportProgress_CACHEFILENAMEAVAILABLE);
2842 if(bindf & BINDF_FROMURLMON)
2843 CHECK_CALLED(ReportProgress_VERIFIEDMIMETYPEAVAILABLE);
2844 else
2845 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
2847 CHECK_CALLED(ReportData);
2848 if(is_first)
2849 CHECK_CALLED(ReportResult);
2851 return TRUE;
2854 static void test_file_protocol_url(LPCWSTR url)
2856 IInternetProtocolInfo *protocol_info;
2857 IUnknown *unk;
2858 IClassFactory *factory;
2859 IInternetProtocol *protocol;
2860 BYTE buf[512];
2861 ULONG cb;
2862 HRESULT hres;
2864 hres = CoGetClassObject(&CLSID_FileProtocol, CLSCTX_INPROC_SERVER, NULL,
2865 &IID_IUnknown, (void**)&unk);
2866 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
2867 if(FAILED(hres))
2868 return;
2870 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
2871 ok(hres == E_NOINTERFACE,
2872 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
2874 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
2875 ok(hres == S_OK, "Could not get IClassFactory interface\n");
2876 IUnknown_Release(unk);
2877 if(FAILED(hres))
2878 return;
2880 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2881 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2883 if(SUCCEEDED(hres)) {
2884 if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2885 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2886 ok(hres == S_OK, "Read failed: %08x\n", hres);
2887 ok(cb == 2, "cb=%u expected 2\n", cb);
2888 buf[2] = 0;
2889 ok(!memcmp(buf, file_with_hash ? "XX" : "<H", 2), "Unexpected data %s\n", buf);
2890 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2891 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2892 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
2893 ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
2894 ok(cb == 0, "cb=%u expected 0\n", cb);
2895 hres = IInternetProtocol_UnlockRequest(protocol);
2896 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2899 if(file_protocol_start(protocol, url, NULL, NULL, FALSE)) {
2900 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2901 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
2902 hres = IInternetProtocol_LockRequest(protocol, 0);
2903 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2904 hres = IInternetProtocol_UnlockRequest(protocol);
2905 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2908 IInternetProtocol_Release(protocol);
2911 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2912 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2913 if(SUCCEEDED(hres)) {
2914 if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2915 hres = IInternetProtocol_LockRequest(protocol, 0);
2916 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2917 hres = IInternetProtocol_Terminate(protocol, 0);
2918 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2919 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2920 ok(hres == S_OK, "Read failed: %08x\n\n", hres);
2921 hres = IInternetProtocol_UnlockRequest(protocol);
2922 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2923 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2924 todo_wine_if(file_with_hash) /* FIXME: An effect of UnlockRequest call? */
2925 ok(hres == S_OK, "Read failed: %08x\n", hres);
2926 hres = IInternetProtocol_Terminate(protocol, 0);
2927 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2930 IInternetProtocol_Release(protocol);
2933 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
2934 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
2935 if(SUCCEEDED(hres)) {
2936 if(file_protocol_start(protocol, url, NULL, NULL, TRUE)) {
2937 hres = IInternetProtocol_Terminate(protocol, 0);
2938 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
2939 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
2940 ok(hres == S_OK, "Read failed: %08x\n", hres);
2941 ok(cb == 2, "cb=%u expected 2\n", cb);
2944 IInternetProtocol_Release(protocol);
2947 if(pCreateUri) {
2948 IInternetProtocolEx *protocolex;
2949 IUri *uri;
2951 hres = pCreateUri(url, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
2952 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2954 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2955 ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2957 if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2958 hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2959 ok(hres == S_OK, "Read failed: %08x\n", hres);
2960 hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2961 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2962 hres = IInternetProtocolEx_UnlockRequest(protocolex);
2963 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2966 IUri_Release(uri);
2967 IInternetProtocolEx_Release(protocolex);
2969 hres = pCreateUri(url, 0, 0, &uri);
2970 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
2972 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocolEx, (void**)&protocolex);
2973 ok(hres == S_OK, "Could not get IInternetProtocolEx: %08x\n", hres);
2975 if(file_protocol_start(NULL, NULL, protocolex, uri, TRUE)) {
2976 hres = IInternetProtocolEx_Read(protocolex, buf, 2, &cb);
2977 ok(hres == S_OK, "Read failed: %08x\n", hres);
2978 hres = IInternetProtocolEx_LockRequest(protocolex, 0);
2979 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
2980 hres = IInternetProtocolEx_UnlockRequest(protocolex);
2981 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
2984 IUri_Release(uri);
2985 IInternetProtocolEx_Release(protocolex);
2986 }else {
2987 win_skip("Skipping file protocol StartEx tests\n");
2990 IClassFactory_Release(factory);
2993 static void test_file_protocol_fail(void)
2995 IInternetProtocol *protocol;
2996 HRESULT hres;
2998 static const WCHAR index_url2[] =
2999 {'f','i','l','e',':','/','/','i','n','d','e','x','.','h','t','m','l',0};
3001 hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
3002 &IID_IInternetProtocol, (void**)&protocol);
3003 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
3004 if(FAILED(hres))
3005 return;
3007 SET_EXPECT(GetBindInfo);
3008 expect_hrResult = MK_E_SYNTAX;
3009 hres = IInternetProtocol_Start(protocol, wszIndexHtml, &protocol_sink, &bind_info, 0, 0);
3010 ok(hres == MK_E_SYNTAX ||
3011 hres == E_INVALIDARG,
3012 "Start failed: %08x, expected MK_E_SYNTAX or E_INVALIDARG\n", hres);
3013 CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
3015 SET_EXPECT(GetBindInfo);
3016 if(!(bindf & BINDF_FROMURLMON))
3017 SET_EXPECT(ReportProgress_DIRECTBIND);
3018 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3019 SET_EXPECT(ReportResult);
3020 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
3021 hres = IInternetProtocol_Start(protocol, index_url, &protocol_sink, &bind_info, 0, 0);
3022 ok(hres == INET_E_RESOURCE_NOT_FOUND,
3023 "Start failed: %08x expected INET_E_RESOURCE_NOT_FOUND\n", hres);
3024 CHECK_CALLED(GetBindInfo);
3025 if(!(bindf & BINDF_FROMURLMON))
3026 CHECK_CALLED(ReportProgress_DIRECTBIND);
3027 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
3028 CHECK_CALLED(ReportResult);
3030 IInternetProtocol_Release(protocol);
3032 hres = CoCreateInstance(&CLSID_FileProtocol, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
3033 &IID_IInternetProtocol, (void**)&protocol);
3034 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
3035 if(FAILED(hres))
3036 return;
3038 SET_EXPECT(GetBindInfo);
3039 if(!(bindf & BINDF_FROMURLMON))
3040 SET_EXPECT(ReportProgress_DIRECTBIND);
3041 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3042 SET_EXPECT(ReportResult);
3043 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
3045 hres = IInternetProtocol_Start(protocol, index_url2, &protocol_sink, &bind_info, 0, 0);
3046 ok(hres == INET_E_RESOURCE_NOT_FOUND,
3047 "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND\n", hres);
3048 CHECK_CALLED(GetBindInfo);
3049 if(!(bindf & BINDF_FROMURLMON))
3050 CHECK_CALLED(ReportProgress_DIRECTBIND);
3051 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
3052 CHECK_CALLED(ReportResult);
3054 SET_EXPECT(GetBindInfo);
3055 hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
3056 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3057 CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
3059 SET_EXPECT(GetBindInfo);
3060 hres = IInternetProtocol_Start(protocol, emptyW, &protocol_sink, &bind_info, 0, 0);
3061 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3062 CLEAR_CALLED(GetBindInfo); /* GetBindInfo not called in IE7 */
3064 IInternetProtocol_Release(protocol);
3067 static void test_file_protocol(void) {
3068 WCHAR buf[INTERNET_MAX_URL_LENGTH], file_name_buf[MAX_PATH];
3069 DWORD size;
3070 ULONG len;
3071 HANDLE file;
3073 static const WCHAR wszFile[] = {'f','i','l','e',':',0};
3074 static const WCHAR wszFile2[] = {'f','i','l','e',':','/','/',0};
3075 static const WCHAR wszFile3[] = {'f','i','l','e',':','/','/','/',0};
3076 static const WCHAR wszFile4[] = {'f','i','l','e',':','\\','\\',0};
3077 static const char html_doc[] = "<HTML></HTML>";
3078 static const WCHAR fragmentW[] = {'#','f','r','a','g',0};
3080 trace("Testing file protocol...\n");
3081 init_test(FILE_TEST, 0);
3083 SetLastError(0xdeadbeef);
3084 file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
3085 FILE_ATTRIBUTE_NORMAL, NULL);
3086 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
3087 if(file == INVALID_HANDLE_VALUE)
3088 return;
3089 WriteFile(file, html_doc, sizeof(html_doc)-1, &size, NULL);
3090 CloseHandle(file);
3092 file_name = wszIndexHtml;
3093 bindf = 0;
3094 test_file_protocol_url(index_url);
3095 bindf = BINDF_FROMURLMON;
3096 test_file_protocol_url(index_url);
3097 bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
3098 test_file_protocol_url(index_url);
3100 memcpy(buf, wszFile, sizeof(wszFile));
3101 len = ARRAY_SIZE(wszFile)-1;
3102 len += GetCurrentDirectoryW(ARRAY_SIZE(buf)-len, buf+len);
3103 buf[len++] = '\\';
3104 memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
3106 file_name = buf + ARRAY_SIZE(wszFile)-1;
3107 bindf = 0;
3108 test_file_protocol_url(buf);
3109 bindf = BINDF_FROMURLMON;
3110 test_file_protocol_url(buf);
3112 memcpy(buf, wszFile2, sizeof(wszFile2));
3113 len = GetCurrentDirectoryW(ARRAY_SIZE(file_name_buf), file_name_buf);
3114 file_name_buf[len++] = '\\';
3115 memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
3116 lstrcpyW(buf+ARRAY_SIZE(wszFile2)-1, file_name_buf);
3117 file_name = file_name_buf;
3118 bindf = 0;
3119 test_file_protocol_url(buf);
3120 bindf = BINDF_FROMURLMON;
3121 test_file_protocol_url(buf);
3123 buf[ARRAY_SIZE(wszFile2)] = '|';
3124 test_file_protocol_url(buf);
3126 memcpy(buf, wszFile3, sizeof(wszFile3));
3127 len = ARRAY_SIZE(wszFile3)-1;
3128 len += GetCurrentDirectoryW(ARRAY_SIZE(buf)-len, buf+len);
3129 buf[len++] = '\\';
3130 memcpy(buf+len, wszIndexHtml, sizeof(wszIndexHtml));
3132 file_name = buf + ARRAY_SIZE(wszFile3)-1;
3133 bindf = 0;
3134 test_file_protocol_url(buf);
3135 bindf = BINDF_FROMURLMON;
3136 test_file_protocol_url(buf);
3138 memcpy(buf, wszFile4, sizeof(wszFile4));
3139 len = GetCurrentDirectoryW(ARRAY_SIZE(file_name_buf), file_name_buf);
3140 file_name_buf[len++] = '\\';
3141 memcpy(file_name_buf+len, wszIndexHtml, sizeof(wszIndexHtml));
3142 lstrcpyW(buf+ARRAY_SIZE(wszFile4)-1, file_name_buf);
3143 file_name = file_name_buf;
3144 bindf = 0;
3145 test_file_protocol_url(buf);
3146 bindf = BINDF_FROMURLMON;
3147 test_file_protocol_url(buf);
3149 buf[ARRAY_SIZE(wszFile4)] = '|';
3150 test_file_protocol_url(buf);
3152 /* Fragment part of URL is skipped if the file doesn't exist. */
3153 lstrcatW(buf, fragmentW);
3154 test_file_protocol_url(buf);
3156 /* Fragment part is considered a part of the file name, if the file exists. */
3157 len = lstrlenW(file_name_buf);
3158 lstrcpyW(file_name_buf+len, fragmentW);
3159 file = CreateFileW(wszIndexHtml, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
3160 FILE_ATTRIBUTE_NORMAL, NULL);
3161 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
3162 WriteFile(file, "XXX", 3, &size, NULL);
3163 CloseHandle(file);
3164 file_name_buf[len] = 0;
3166 file_with_hash = TRUE;
3167 test_file_protocol_url(buf);
3169 DeleteFileW(wszIndexHtml);
3170 DeleteFileW(file_name_buf);
3172 bindf = 0;
3173 test_file_protocol_fail();
3174 bindf = BINDF_FROMURLMON;
3175 test_file_protocol_fail();
3178 static void create_cache_entry(const WCHAR *urlw)
3180 FILETIME now, tomorrow, yesterday;
3181 char file_path[MAX_PATH];
3182 BYTE content[1000];
3183 ULARGE_INTEGER li;
3184 const char *url;
3185 HANDLE file;
3186 DWORD size;
3187 unsigned i;
3188 BOOL res;
3190 BYTE cache_headers[] = "HTTP/1.1 200 OK\r\n\r\n";
3192 trace("Testing cache read...\n");
3194 url = w2a(urlw);
3196 for(i = 0; i < sizeof(content); i++)
3197 content[i] = '0' + (i%10);
3199 GetSystemTimeAsFileTime(&now);
3200 li.u.HighPart = now.dwHighDateTime;
3201 li.u.LowPart = now.dwLowDateTime;
3202 li.QuadPart += (LONGLONG)10000000 * 3600 * 24;
3203 tomorrow.dwHighDateTime = li.u.HighPart;
3204 tomorrow.dwLowDateTime = li.u.LowPart;
3205 li.QuadPart -= (LONGLONG)10000000 * 3600 * 24 * 2;
3206 yesterday.dwHighDateTime = li.u.HighPart;
3207 yesterday.dwLowDateTime = li.u.LowPart;
3209 res = CreateUrlCacheEntryA(url, sizeof(content), "", file_path, 0);
3210 ok(res, "CreateUrlCacheEntryA failed: %u\n", GetLastError());
3212 file = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
3213 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
3215 WriteFile(file, content, sizeof(content), &size, NULL);
3216 CloseHandle(file);
3218 res = CommitUrlCacheEntryA(url, file_path, tomorrow, yesterday, NORMAL_CACHE_ENTRY,
3219 cache_headers, sizeof(cache_headers)-1, "", 0);
3220 ok(res, "CommitUrlCacheEntryA failed: %u\n", GetLastError());
3223 static BOOL http_protocol_start(LPCWSTR url, BOOL use_iuri)
3225 static BOOL got_user_agent = FALSE;
3226 IUri *uri = NULL;
3227 HRESULT hres;
3229 if(use_iuri && pCreateUri) {
3230 hres = pCreateUri(url, 0, 0, &uri);
3231 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
3234 SET_EXPECT(GetBindInfo);
3235 if (!(bindf & BINDF_FROMURLMON))
3236 SET_EXPECT(ReportProgress_DIRECTBIND);
3237 if(!got_user_agent)
3238 SET_EXPECT(GetBindString_USER_AGENT);
3239 SET_EXPECT(GetBindString_ROOTDOC_URL);
3240 SET_EXPECT(GetBindString_ACCEPT_MIMES);
3241 SET_EXPECT(QueryService_HttpNegotiate);
3242 SET_EXPECT(BeginningTransaction);
3243 SET_EXPECT(GetRootSecurityId);
3244 if(http_post_test) {
3245 SET_EXPECT(GetBindString_POST_COOKIE);
3246 if(http_post_test == TYMED_ISTREAM)
3247 SET_EXPECT(Stream_Seek);
3249 if(bind_from_cache) {
3250 SET_EXPECT(OnResponse);
3251 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
3252 SET_EXPECT(ReportData);
3255 if(uri) {
3256 IInternetProtocolEx *protocolex;
3258 hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3259 ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3261 hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, 0, 0);
3262 ok(hres == S_OK, "Start failed: %08x\n", hres);
3264 IInternetProtocolEx_Release(protocolex);
3265 IUri_Release(uri);
3266 }else {
3267 hres = IInternetProtocol_Start(async_protocol, url, &protocol_sink, &bind_info, 0, 0);
3268 ok(hres == S_OK, "Start failed: %08x\n", hres);
3270 if(FAILED(hres))
3271 return FALSE;
3273 CHECK_CALLED(GetBindInfo);
3274 if (!(bindf & BINDF_FROMURLMON))
3275 CHECK_CALLED(ReportProgress_DIRECTBIND);
3276 if (!got_user_agent)
3278 CHECK_CALLED(GetBindString_USER_AGENT);
3279 got_user_agent = TRUE;
3281 CLEAR_CALLED(GetBindString_ROOTDOC_URL); /* New in IE11 */
3282 CHECK_CALLED(GetBindString_ACCEPT_MIMES);
3283 CHECK_CALLED(QueryService_HttpNegotiate);
3284 CHECK_CALLED(BeginningTransaction);
3285 /* GetRootSecurityId called on WinXP but not on Win98 */
3286 CLEAR_CALLED(GetRootSecurityId);
3287 if(http_post_test) {
3288 CHECK_CALLED(GetBindString_POST_COOKIE);
3289 if(http_post_test == TYMED_ISTREAM)
3290 CHECK_CALLED(Stream_Seek);
3292 if(bind_from_cache) {
3293 CHECK_CALLED(OnResponse);
3294 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3295 CHECK_CALLED(ReportData);
3298 return TRUE;
3301 static void test_protocol_terminate(IInternetProtocol *protocol)
3303 BYTE buf[3600];
3304 DWORD cb;
3305 HRESULT hres;
3307 hres = IInternetProtocol_LockRequest(protocol, 0);
3308 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
3310 hres = IInternetProtocol_Read(protocol, buf, 1, &cb);
3311 ok(hres == (test_abort ? S_OK : S_FALSE), "Read failed: %08x\n", hres);
3313 hres = IInternetProtocol_Terminate(protocol, 0);
3314 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3316 /* This wait is to give the internet handles being freed in Terminate
3317 * enough time to actually terminate in all cases. Internet handles
3318 * terminate asynchronously and native reuses the main InternetOpen
3319 * handle. The only case in which this seems to be necessary is on
3320 * wine with native wininet and urlmon, resulting in the next time
3321 * test_http_protocol_url being called the first data notification actually
3322 * being an extra last data notification from the previous connection
3323 * about once out of every ten times. */
3324 Sleep(100);
3326 hres = IInternetProtocol_UnlockRequest(protocol);
3327 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
3330 /* is_first refers to whether this is the first call to this function
3331 * _for this url_ */
3332 static void test_http_protocol_url(LPCWSTR url, int prot, DWORD flags, DWORD tymed)
3334 IInternetProtocolInfo *protocol_info;
3335 IClassFactory *factory;
3336 IUnknown *unk;
3337 HRESULT hres;
3339 init_test(prot, flags);
3340 http_url = url;
3341 http_post_test = tymed;
3342 if(flags & TEST_FROMCACHE)
3343 create_cache_entry(url);
3345 hres = CoGetClassObject(prot == HTTPS_TEST ? &CLSID_HttpSProtocol : &CLSID_HttpProtocol,
3346 CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3347 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3348 if(FAILED(hres))
3349 return;
3351 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3352 ok(hres == E_NOINTERFACE,
3353 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
3354 hres);
3356 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3357 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3358 IUnknown_Release(unk);
3359 if(FAILED(hres))
3360 return;
3362 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3363 (void**)&async_protocol);
3364 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3365 if(SUCCEEDED(hres)) {
3366 BYTE buf[3600];
3367 DWORD cb;
3368 ULONG ref;
3370 test_priority(async_protocol);
3372 SET_EXPECT(ReportProgress_COOKIE_SENT);
3373 if(http_is_first) {
3374 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
3375 SET_EXPECT(ReportProgress_CONNECTING);
3377 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3378 if(test_redirect && !(bindinfo_options & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS)) {
3379 SET_EXPECT(ReportProgress_REDIRECTING);
3380 SET_EXPECT(GetBindString_SAMESITE_COOKIE_LEVEL); /* New in IE11 */
3382 SET_EXPECT(ReportProgress_PROXYDETECTING);
3383 if(prot == HTTP_TEST)
3384 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
3385 else
3386 SET_EXPECT(QueryService_HttpSecurity);
3387 if(!(bindf & BINDF_FROMURLMON)) {
3388 SET_EXPECT(OnResponse);
3389 SET_EXPECT(ReportProgress_RAWMIMETYPE);
3390 SET_EXPECT(ReportData);
3391 } else {
3392 SET_EXPECT(Switch);
3395 if(!http_protocol_start(url, (flags & TEST_USEIURI) != 0)) {
3396 IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3397 IInternetProtocol_Release(async_protocol);
3398 return;
3401 if(!direct_read && !test_abort && !bind_from_cache)
3402 SET_EXPECT(ReportResult);
3404 if(flags & TEST_DISABLEAUTOREDIRECT)
3405 expect_hrResult = INET_E_REDIRECT_FAILED;
3406 else if(test_abort)
3407 expect_hrResult = E_ABORT;
3408 else
3409 expect_hrResult = S_OK;
3411 if(direct_read) {
3412 SET_EXPECT(Switch);
3413 while(wait_for_switch) {
3414 ok( WaitForSingleObject(event_continue, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3415 CHECK_CALLED(Switch); /* Set in ReportData */
3416 call_continue(&continue_protdata);
3417 SetEvent(event_continue_done);
3419 }else if(bind_from_cache) {
3420 BYTE buf[1500];
3422 hres = IInternetProtocol_Read(async_protocol, buf, 100, &cb);
3423 ok(hres == S_OK && cb == 100, "Read failed: %08x (%d bytes)\n", hres, cb);
3425 SET_EXPECT(ReportResult);
3426 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3427 ok(hres == S_OK && cb == 900, "Read failed: %08x (%d bytes)\n", hres, cb);
3428 CHECK_CALLED(ReportResult);
3430 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3431 ok(hres == S_FALSE && !cb, "Read failed: %08x (%d bytes)\n", hres, cb);
3432 }else {
3433 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3434 ok((hres == E_PENDING && cb==0) ||
3435 (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3437 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3438 if(bindf & BINDF_FROMURLMON)
3439 CHECK_CALLED(Switch);
3440 else
3441 CHECK_CALLED(ReportData);
3442 if(prot == HTTPS_TEST)
3443 CLEAR_CALLED(QueryService_HttpSecurity);
3445 while(1) {
3446 if(bindf & BINDF_FROMURLMON)
3447 SET_EXPECT(Switch);
3448 else
3449 SET_EXPECT(ReportData);
3450 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3451 if(hres == E_PENDING) {
3452 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3453 ok((hres == E_PENDING && cb==0) ||
3454 (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3455 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3456 if(bindf & BINDF_FROMURLMON)
3457 CHECK_CALLED(Switch);
3458 else
3459 CHECK_CALLED(ReportData);
3461 if(test_abort) {
3462 HRESULT hres;
3464 SET_EXPECT(ReportResult);
3465 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3466 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3467 CHECK_CALLED(ReportResult);
3469 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3470 ok(hres == INET_E_RESULT_DISPATCHED || hres == S_OK /* IE10 */, "Abort failed: %08x\n", hres);
3471 break;
3473 }else {
3474 if(bindf & BINDF_FROMURLMON)
3475 CHECK_NOT_CALLED(Switch);
3476 else
3477 CHECK_NOT_CALLED(ReportData);
3478 if(cb == 0) break;
3481 if(!test_abort) {
3482 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3483 CHECK_CALLED(ReportResult);
3486 if(prot == HTTPS_TEST)
3487 CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3489 if (prot == HTTP_TEST || prot == HTTPS_TEST)
3490 CLEAR_CALLED(ReportProgress_COOKIE_SENT);
3492 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3493 ok(hres == INET_E_RESULT_DISPATCHED || hres == S_OK /* IE10 */, "Abort failed: %08x\n", hres);
3495 test_protocol_terminate(async_protocol);
3497 hres = IInternetProtocol_Abort(async_protocol, E_ABORT, 0);
3498 ok(hres == S_OK, "Abort failed: %08x\n", hres);
3500 ref = IInternetProtocol_Release(async_protocol);
3501 ok(!ref, "ref=%x\n", ref);
3504 IClassFactory_Release(factory);
3506 if(flags & TEST_FROMCACHE) {
3507 BOOL res;
3509 res = DeleteUrlCacheEntryW(url);
3510 ok(res, "DeleteUrlCacheEntryA failed: %u\n", GetLastError());
3514 static void test_http_protocol(void)
3516 static const WCHAR posttest_url[] =
3517 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3518 't','e','s','t','s','/','p','o','s','t','.','p','h','p',0};
3519 static const WCHAR redirect_url[] =
3520 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3521 't','e','s','t','s','/','r','e','d','i','r','e','c','t',0};
3522 static const WCHAR winetest_url[] =
3523 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3524 't','e','s','t','s','/','d','a','t','a','.','p','h','p',0};
3525 static const WCHAR empty_url[] =
3526 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3527 't','e','s','t','s','/','e','m','p','t','y','.','j','s',0};
3528 static const WCHAR cache_only_url[] =
3529 {'h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3530 't','e','s','t','s','/','c','a','c','h','e','-','o','n','l','y',0};
3533 trace("Testing http protocol (not from urlmon)...\n");
3534 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
3535 test_http_protocol_url(winetest_url, HTTP_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3537 trace("Testing http protocol (from urlmon)...\n");
3538 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3539 test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3541 trace("Testing http protocol (to file)...\n");
3542 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE;
3543 test_http_protocol_url(winetest_url, HTTP_TEST, 0, TYMED_NULL);
3545 trace("Testing http protocol (post data)...\n");
3546 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3547 test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST, TYMED_HGLOBAL);
3549 trace("Testing http protocol (post data stream)...\n");
3550 test_http_protocol_url(posttest_url, HTTP_TEST, TEST_FIRST_HTTP|TEST_POST|TEST_ASYNCREQ, TYMED_ISTREAM);
3552 trace("Testing http protocol (direct read)...\n");
3553 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3554 test_http_protocol_url(winetest_url, HTTP_TEST, TEST_DIRECT_READ|TEST_USEIURI, TYMED_NULL);
3556 trace("Testing http protocol (redirected)...\n");
3557 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3558 test_http_protocol_url(redirect_url, HTTP_TEST, TEST_REDIRECT, TYMED_NULL);
3560 trace("Testing http protocol (redirected, disable auto redirect)...\n");
3561 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3562 test_http_protocol_url(redirect_url, HTTP_TEST, TEST_REDIRECT | TEST_DISABLEAUTOREDIRECT, TYMED_NULL);
3564 trace("Testing http protocol empty file...\n");
3565 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3566 test_http_protocol_url(empty_url, HTTP_TEST, TEST_EMPTY, TYMED_NULL);
3568 /* This is a bit ugly. We unconditionally disable this test on Wine. This won't work until we have
3569 * support for reading from cache via HTTP layer in wininet. Until then, Wine will fail badly, affecting
3570 * other, unrelated, tests. Working around it is not worth the trouble, we may simply make sure those
3571 * tests work on Windows and have them around for the future.
3573 if(broken(1)) {
3574 trace("Testing http protocol (from cache)...\n");
3575 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON;
3576 test_http_protocol_url(cache_only_url, HTTP_TEST, TEST_FROMCACHE, TYMED_NULL);
3579 trace("Testing http protocol abort...\n");
3580 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3581 test_http_protocol_url(winetest_url, HTTP_TEST, TEST_ABORT, TYMED_NULL);
3583 test_early_abort(&CLSID_HttpProtocol);
3584 test_early_abort(&CLSID_HttpSProtocol);
3587 static void test_https_protocol(void)
3589 static const WCHAR https_winehq_url[] =
3590 {'h','t','t','p','s',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g','/',
3591 't','e','s','t','s','/','h','e','l','l','o','.','h','t','m','l',0};
3593 trace("Testing https protocol (from urlmon)...\n");
3594 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3595 test_http_protocol_url(https_winehq_url, HTTPS_TEST, TEST_FIRST_HTTP, TYMED_NULL);
3599 static void test_ftp_protocol(void)
3601 IInternetProtocolInfo *protocol_info;
3602 IClassFactory *factory;
3603 IUnknown *unk;
3604 BYTE buf[4096];
3605 ULONG ref;
3606 DWORD cb;
3607 HRESULT hres;
3609 static const WCHAR ftp_urlW[] = {'f','t','p',':','/','/','f','t','p','.','w','i','n','e','h','q','.','o','r','g',
3610 '/','p','u','b','/','o','t','h','e','r','/',
3611 'w','i','n','e','l','o','g','o','.','x','c','f','.','t','a','r','.','b','z','2',0};
3613 trace("Testing ftp protocol...\n");
3615 init_test(FTP_TEST, 0);
3617 bindf = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NOWRITECACHE;
3618 state = STATE_STARTDOWNLOADING;
3619 expect_hrResult = E_PENDING;
3621 hres = CoGetClassObject(&CLSID_FtpProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3622 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3623 if(FAILED(hres))
3624 return;
3626 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3627 ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3629 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3630 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3631 IUnknown_Release(unk);
3632 if(FAILED(hres))
3633 return;
3635 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3636 (void**)&async_protocol);
3637 IClassFactory_Release(factory);
3638 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3640 test_priority(async_protocol);
3642 SET_EXPECT(GetBindInfo);
3643 SET_EXPECT(ReportProgress_FINDINGRESOURCE);
3644 SET_EXPECT(ReportProgress_CONNECTING);
3645 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3646 SET_EXPECT(Switch);
3648 hres = IInternetProtocol_Start(async_protocol, ftp_urlW, &protocol_sink, &bind_info, 0, 0);
3649 ok(hres == S_OK, "Start failed: %08x\n", hres);
3650 CHECK_CALLED(GetBindInfo);
3652 SET_EXPECT(ReportResult);
3654 hres = IInternetProtocol_Read(async_protocol, buf, 1, &cb);
3655 ok((hres == E_PENDING && cb==0) ||
3656 (hres == S_OK && cb==1), "Read failed: %08x (%d bytes)\n", hres, cb);
3658 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
3660 while(1) {
3661 hres = IInternetProtocol_Read(async_protocol, buf, sizeof(buf), &cb);
3662 if(hres == E_PENDING)
3664 DWORD ret = WaitForSingleObject(event_complete, 90000);
3665 ok( ret == WAIT_OBJECT_0, "wait timed out\n" );
3666 if (ret != WAIT_OBJECT_0) break;
3668 else
3669 if(cb == 0) break;
3672 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3673 CHECK_CALLED(ReportResult);
3674 CHECK_CALLED(Switch);
3676 test_protocol_terminate(async_protocol);
3678 if(pCreateUri) {
3679 IInternetProtocolEx *protocolex;
3681 hres = IInternetProtocol_QueryInterface(async_protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
3682 ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
3683 IInternetProtocolEx_Release(protocolex);
3686 ref = IInternetProtocol_Release(async_protocol);
3687 ok(!ref, "ref=%d\n", ref);
3689 test_early_abort(&CLSID_FtpProtocol);
3692 static void test_gopher_protocol(void)
3694 IInternetProtocolInfo *protocol_info;
3695 IClassFactory *factory;
3696 IUnknown *unk;
3697 HRESULT hres;
3699 trace("Testing gopher protocol...\n");
3701 hres = CoGetClassObject(&CLSID_GopherProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
3702 ok(hres == S_OK ||
3703 broken(hres == REGDB_E_CLASSNOTREG || hres == CLASS_E_CLASSNOTAVAILABLE), /* Gopher protocol has been removed as of Vista */
3704 "CoGetClassObject failed: %08x\n", hres);
3705 if(FAILED(hres))
3706 return;
3708 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3709 ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n", hres);
3711 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3712 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3713 IUnknown_Release(unk);
3714 if(FAILED(hres))
3715 return;
3717 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3718 (void**)&async_protocol);
3719 IClassFactory_Release(factory);
3720 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3722 test_priority(async_protocol);
3724 IInternetProtocol_Release(async_protocol);
3726 test_early_abort(&CLSID_GopherProtocol);
3729 static void test_mk_protocol(void)
3731 IInternetProtocolInfo *protocol_info;
3732 IInternetProtocol *protocol;
3733 IClassFactory *factory;
3734 IUnknown *unk;
3735 HRESULT hres;
3737 static const WCHAR wrong_url1[] = {'t','e','s','t',':','@','M','S','I','T','S','t','o','r','e',
3738 ':',':','/','t','e','s','t','.','h','t','m','l',0};
3739 static const WCHAR wrong_url2[] = {'m','k',':','/','t','e','s','t','.','h','t','m','l',0};
3741 trace("Testing mk protocol...\n");
3742 init_test(MK_TEST, 0);
3744 hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL,
3745 &IID_IUnknown, (void**)&unk);
3746 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
3748 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
3749 ok(hres == E_NOINTERFACE,
3750 "Could not get IInternetProtocolInfo interface: %08x, expected E_NOINTERFACE\n",
3751 hres);
3753 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
3754 ok(hres == S_OK, "Could not get IClassFactory interface\n");
3755 IUnknown_Release(unk);
3756 if(FAILED(hres))
3757 return;
3759 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol,
3760 (void**)&protocol);
3761 IClassFactory_Release(factory);
3762 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
3764 SET_EXPECT(GetBindInfo);
3765 hres = IInternetProtocol_Start(protocol, wrong_url1, &protocol_sink, &bind_info, 0, 0);
3766 ok(hres == MK_E_SYNTAX || hres == INET_E_INVALID_URL,
3767 "Start failed: %08x, expected MK_E_SYNTAX or INET_E_INVALID_URL\n", hres);
3768 CLEAR_CALLED(GetBindInfo);
3770 SET_EXPECT(GetBindInfo);
3771 SET_EXPECT(ReportProgress_DIRECTBIND);
3772 SET_EXPECT(ReportProgress_SENDINGREQUEST);
3773 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
3774 SET_EXPECT(ReportResult);
3775 expect_hrResult = INET_E_RESOURCE_NOT_FOUND;
3777 hres = IInternetProtocol_Start(protocol, wrong_url2, &protocol_sink, &bind_info, 0, 0);
3778 ok(hres == INET_E_RESOURCE_NOT_FOUND ||
3779 hres == INET_E_INVALID_URL, /* win2k3 */
3780 "Start failed: %08x, expected INET_E_RESOURCE_NOT_FOUND or INET_E_INVALID_URL\n", hres);
3782 if (hres == INET_E_RESOURCE_NOT_FOUND) {
3783 CHECK_CALLED(GetBindInfo);
3784 CLEAR_CALLED(ReportProgress_DIRECTBIND);
3785 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
3786 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3787 CHECK_CALLED(ReportResult);
3788 }else {
3789 CLEAR_CALLED(GetBindInfo);
3790 CLEAR_CALLED(ReportProgress_DIRECTBIND);
3791 CLEAR_CALLED(ReportProgress_SENDINGREQUEST);
3792 CLEAR_CALLED(ReportProgress_MIMETYPEAVAILABLE);
3793 CLEAR_CALLED(ReportResult);
3796 IInternetProtocol_Release(protocol);
3799 static void test_CreateBinding(void)
3801 IInternetProtocol *protocol;
3802 IInternetPriority *priority;
3803 IInternetSession *session;
3804 IWinInetHttpInfo *http_info;
3805 IWinInetInfo *inet_info;
3806 LONG p;
3807 BYTE buf[1000];
3808 DWORD read;
3809 HRESULT hres;
3811 static const WCHAR test_url[] =
3812 {'t','e','s','t',':','/','/','f','i','l','e','.','h','t','m','l',0};
3813 static const WCHAR wsz_test[] = {'t','e','s','t',0};
3815 trace("Testing CreateBinding%s...\n", no_aggregation ? "(no aggregation)" : "");
3816 init_test(BIND_TEST, TEST_BINDING);
3818 hres = pCoInternetGetSession(0, &session, 0);
3819 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
3821 hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, wsz_test, 0, NULL, 0);
3822 ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
3824 hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
3825 binding_protocol = protocol;
3826 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
3827 ok(protocol != NULL, "protocol == NULL\n");
3829 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
3830 ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
3832 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
3833 ok(hres == S_OK, "Could not get IInternetProtocolSink: %08x\n", hres);
3835 hres = IInternetProtocol_Start(protocol, test_url, NULL, &bind_info, 0, 0);
3836 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3837 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, NULL, 0, 0);
3838 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3839 hres = IInternetProtocol_Start(protocol, NULL, &protocol_sink, &bind_info, 0, 0);
3840 ok(hres == E_INVALIDARG, "Start failed: %08x, expected E_INVALIDARG\n", hres);
3842 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
3843 ok(hres == S_OK, "QueryInterface(IID_IInternetPriority) failed: %08x\n", hres);
3845 p = 0xdeadbeef;
3846 hres = IInternetPriority_GetPriority(priority, &p);
3847 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3848 ok(!p, "p=%d\n", p);
3850 ex_priority = 100;
3851 hres = IInternetPriority_SetPriority(priority, 100);
3852 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3854 p = 0xdeadbeef;
3855 hres = IInternetPriority_GetPriority(priority, &p);
3856 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3857 ok(p == 100, "p=%d\n", p);
3859 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3860 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3862 SET_EXPECT(QueryService_InternetProtocol);
3864 SET_EXPECT(CreateInstance);
3865 if(no_aggregation) {
3866 SET_EXPECT(CreateInstance_no_aggregation);
3867 SET_EXPECT(StartEx);
3868 }else {
3869 SET_EXPECT(Start);
3872 SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
3873 SET_EXPECT(SetPriority);
3875 ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
3877 trace("Start >\n");
3878 expect_hrResult = S_OK;
3879 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
3880 ok(hres == S_OK, "Start failed: %08x\n", hres);
3881 trace("Start <\n");
3883 CHECK_CALLED(QueryService_InternetProtocol);
3885 CHECK_CALLED(CreateInstance);
3886 if(no_aggregation) {
3887 CHECK_CALLED(CreateInstance_no_aggregation);
3888 ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
3889 ok(protocol_emul->outer_ref == 0, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
3890 }else {
3891 ok(obj_refcount(protocol) == 5 || broken(obj_refcount(protocol) == 4) /* before win7 */, "wrong protocol refcount %d\n",
3892 obj_refcount(protocol));
3893 ok(protocol_emul->outer_ref == 1 || broken(protocol_emul->outer_ref == 0) /* before win7 */, "protocol_outer_ref = %u\n",
3894 protocol_emul->outer_ref);
3897 CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
3898 CHECK_CALLED(SetPriority);
3899 if(no_aggregation)
3900 CHECK_CALLED(StartEx);
3901 else
3902 CHECK_CALLED(Start);
3904 if(!no_aggregation)
3905 SET_EXPECT(QueryInterface_IWinInetInfo);
3906 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3907 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3908 if(!no_aggregation)
3909 CHECK_CALLED(QueryInterface_IWinInetInfo);
3911 if(!no_aggregation)
3912 SET_EXPECT(QueryInterface_IWinInetInfo);
3913 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&inet_info);
3914 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3915 if(!no_aggregation)
3916 CHECK_CALLED(QueryInterface_IWinInetInfo);
3918 if(!no_aggregation)
3919 SET_EXPECT(QueryInterface_IWinInetHttpInfo);
3920 hres = IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
3921 ok(hres == E_NOINTERFACE, "Could not get IWinInetInfo protocol: %08x\n", hres);
3922 if(!no_aggregation)
3923 CHECK_CALLED(QueryInterface_IWinInetHttpInfo);
3925 SET_EXPECT(Read);
3926 read = 0xdeadbeef;
3927 hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3928 ok(hres == S_OK, "Read failed: %08x\n", hres);
3929 ok(read == 100, "read = %d\n", read);
3930 CHECK_CALLED(Read);
3932 SET_EXPECT(Read);
3933 read = 0xdeadbeef;
3934 hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3935 ok(hres == S_FALSE, "Read failed: %08x\n", hres);
3936 ok(!read, "read = %d\n", read);
3937 CHECK_CALLED(Read);
3939 p = 0xdeadbeef;
3940 hres = IInternetPriority_GetPriority(priority, &p);
3941 ok(hres == S_OK, "GetPriority failed: %08x\n", hres);
3942 ok(p == 100, "p=%d\n", p);
3944 hres = IInternetPriority_SetPriority(priority, 101);
3945 ok(hres == S_OK, "SetPriority failed: %08x\n", hres);
3947 if(no_aggregation) {
3948 ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
3949 ok(protocol_emul->outer_ref == 0, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
3950 }else {
3951 ok(obj_refcount(protocol) == 5 || broken(obj_refcount(protocol) == 4) /* before win7 */, "wrong protocol refcount %d\n", obj_refcount(protocol));
3952 ok(protocol_emul->outer_ref == 1 || broken(protocol_emul->outer_ref == 0) /* before win7 */, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
3955 SET_EXPECT(Terminate);
3956 hres = IInternetProtocol_Terminate(protocol, 0xdeadbeef);
3957 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
3958 CHECK_CALLED(Terminate);
3960 ok(obj_refcount(protocol) == 4, "wrong protocol refcount %d\n", obj_refcount(protocol));
3961 ok(protocol_emul->outer_ref == 0, "protocol_outer_ref = %u\n", protocol_emul->outer_ref);
3963 SET_EXPECT(Continue);
3964 hres = IInternetProtocolSink_Switch(binding_sink, &protocoldata);
3965 ok(hres == S_OK, "Switch failed: %08x\n", hres);
3966 CHECK_CALLED(Continue);
3968 SET_EXPECT(Read);
3969 read = 0xdeadbeef;
3970 hres = IInternetProtocol_Read(protocol, expect_pv = buf, sizeof(buf), &read);
3971 if(no_aggregation) {
3972 ok(hres == S_OK, "Read failed: %08x\n", hres);
3973 ok(read == 100, "read = %d\n", read);
3974 CHECK_CALLED(Read);
3975 }else {
3976 todo_wine
3977 ok(hres == E_ABORT, "Read failed: %08x\n", hres);
3978 todo_wine
3979 ok(read == 0, "read = %d\n", read);
3980 todo_wine
3981 CHECK_NOT_CALLED(Read);
3984 hres = IInternetProtocolSink_ReportProgress(binding_sink,
3985 BINDSTATUS_CACHEFILENAMEAVAILABLE, expect_wsz = emptyW);
3986 ok(hres == S_OK, "ReportProgress(BINDSTATUS_CACHEFILENAMEAVAILABLE) failed: %08x\n", hres);
3988 hres = IInternetProtocolSink_ReportResult(binding_sink, S_OK, ERROR_SUCCESS, NULL);
3989 ok(hres == E_FAIL, "ReportResult failed: %08x, expected E_FAIL\n", hres);
3991 hres = IInternetProtocolSink_ReportData(binding_sink, 0, 0, 0);
3992 ok(hres == S_OK, "ReportData failed: %08x\n", hres);
3994 IInternetProtocolSink_Release(binding_sink);
3995 IInternetPriority_Release(priority);
3996 IInternetBindInfo_Release(prot_bind_info);
3998 ok(obj_refcount(protocol) == 1, "wrong protocol refcount %d\n", obj_refcount(protocol));
4000 SET_EXPECT(Protocol_destructor);
4001 IInternetProtocol_Release(protocol);
4002 CHECK_CALLED(Protocol_destructor);
4004 hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
4005 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
4006 ok(protocol != NULL, "protocol == NULL\n");
4008 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
4009 ok(hres == S_OK, "Abort failed: %08x\n", hres);
4011 hres = IInternetProtocol_Abort(protocol, E_FAIL, 0);
4012 ok(hres == S_OK, "Abort failed: %08x\n", hres);
4014 IInternetProtocol_Release(protocol);
4016 hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, wsz_test);
4017 ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
4019 hres = IInternetSession_CreateBinding(session, NULL, test_url, NULL, NULL, &protocol, 0);
4020 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
4021 ok(protocol != NULL, "protocol == NULL\n");
4023 SET_EXPECT(QueryService_InternetProtocol);
4024 hres = IInternetProtocol_Start(protocol, test_url, &protocol_sink, &bind_info, 0, 0);
4025 ok(hres == MK_E_SYNTAX, "Start failed: %08x, expected MK_E_SYNTAX\n", hres);
4026 CHECK_CALLED(QueryService_InternetProtocol);
4028 IInternetProtocol_Release(protocol);
4030 IInternetSession_Release(session);
4033 static void test_binding(int prot, DWORD grf_pi, DWORD test_flags)
4035 IInternetProtocolEx *protocolex = NULL;
4036 IInternetProtocol *protocol;
4037 IInternetSession *session;
4038 IUri *uri = NULL;
4039 ULONG ref;
4040 HRESULT hres;
4042 pi = grf_pi;
4044 init_test(prot, test_flags|TEST_BINDING);
4046 hres = pCoInternetGetSession(0, &session, 0);
4047 ok(hres == S_OK, "CoInternetGetSession failed: %08x\n", hres);
4049 if(test_flags & TEST_EMULATEPROT) {
4050 hres = IInternetSession_RegisterNameSpace(session, &ClassFactory, &IID_NULL, protocol_names[prot], 0, NULL, 0);
4051 ok(hres == S_OK, "RegisterNameSpace failed: %08x\n", hres);
4054 hres = IInternetSession_CreateBinding(session, NULL, binding_urls[prot], NULL, NULL, &protocol, 0);
4055 binding_protocol = protocol;
4056 ok(hres == S_OK, "CreateBinding failed: %08x\n", hres);
4057 ok(protocol != NULL, "protocol == NULL\n");
4059 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetBindInfo, (void**)&prot_bind_info);
4060 ok(hres == S_OK, "QueryInterface(IID_IInternetBindInfo) failed: %08x\n", hres);
4062 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolSink, (void**)&binding_sink);
4063 ok(hres == S_OK, "QueryInterface(IID_IInternetProtocolSink) failed: %08x\n", hres);
4065 if(test_flags & TEST_USEIURI) {
4066 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
4067 ok(hres == S_OK, "Could not get IInternetProtocolEx iface: %08x\n", hres);
4069 hres = pCreateUri(binding_urls[prot], Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
4070 ok(hres == S_OK, "CreateUri failed: %08x\n", hres);
4073 ex_priority = 0;
4074 SET_EXPECT(QueryService_InternetProtocol);
4075 SET_EXPECT(CreateInstance);
4076 SET_EXPECT(ReportProgress_PROTOCOLCLASSID);
4077 SET_EXPECT(SetPriority);
4078 if(impl_protex)
4079 SET_EXPECT(StartEx);
4080 else
4081 SET_EXPECT(Start);
4083 expect_hrResult = S_OK;
4085 if(protocolex) {
4086 hres = IInternetProtocolEx_StartEx(protocolex, uri, &protocol_sink, &bind_info, pi, 0);
4087 ok(hres == S_OK, "StartEx failed: %08x\n", hres);
4088 }else {
4089 hres = IInternetProtocol_Start(protocol, binding_urls[prot], &protocol_sink, &bind_info, pi, 0);
4090 ok(hres == S_OK, "Start failed: %08x\n", hres);
4093 CHECK_CALLED(QueryService_InternetProtocol);
4094 CHECK_CALLED(CreateInstance);
4095 CHECK_CALLED(ReportProgress_PROTOCOLCLASSID);
4096 CLEAR_CALLED(SetPriority); /* IE11 does not call it. */
4097 if(impl_protex)
4098 CHECK_CALLED(StartEx);
4099 else
4100 CHECK_CALLED(Start);
4102 if(protocolex)
4103 IInternetProtocolEx_Release(protocolex);
4104 if(uri)
4105 IUri_Release(uri);
4107 if(prot == HTTP_TEST || prot == HTTPS_TEST) {
4108 while(prot_state < 4) {
4109 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
4110 if(mimefilter_test && filtered_protocol) {
4111 SET_EXPECT(Continue);
4112 IInternetProtocol_Continue(filtered_protocol, pdata);
4113 CHECK_CALLED(Continue);
4114 }else {
4115 SET_EXPECT(Continue);
4116 IInternetProtocol_Continue(protocol, pdata);
4117 CHECK_CALLED(Continue);
4119 if(test_abort && prot_state == 2) {
4120 SET_EXPECT(Abort);
4121 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
4122 ok(hres == S_OK, "Abort failed: %08x\n", hres);
4123 CHECK_CALLED(Abort);
4125 hres = IInternetProtocol_Abort(protocol, E_ABORT, 0);
4126 ok(hres == S_OK, "Abort failed: %08x\n", hres);
4127 SetEvent(event_complete2);
4128 break;
4130 SetEvent(event_complete2);
4132 if(direct_read)
4133 CHECK_CALLED(ReportData); /* Set in ReportResult */
4134 ok( WaitForSingleObject(event_complete, 90000) == WAIT_OBJECT_0, "wait timed out\n" );
4135 }else {
4136 if(mimefilter_test)
4137 SET_EXPECT(MimeFilter_LockRequest);
4138 else
4139 SET_EXPECT(LockRequest);
4140 hres = IInternetProtocol_LockRequest(protocol, 0);
4141 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
4142 if(mimefilter_test)
4143 CHECK_CALLED(MimeFilter_LockRequest);
4144 else
4145 CHECK_CALLED(LockRequest);
4147 if(mimefilter_test)
4148 SET_EXPECT(MimeFilter_UnlockRequest);
4149 else
4150 SET_EXPECT(UnlockRequest);
4151 hres = IInternetProtocol_UnlockRequest(protocol);
4152 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
4153 if(mimefilter_test)
4154 CHECK_CALLED(MimeFilter_UnlockRequest);
4155 else
4156 CHECK_CALLED(UnlockRequest);
4159 if(mimefilter_test)
4160 SET_EXPECT(MimeFilter_Terminate);
4161 else
4162 SET_EXPECT(Terminate);
4163 hres = IInternetProtocol_Terminate(protocol, 0);
4164 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
4165 if(mimefilter_test)
4166 CLEAR_CALLED(MimeFilter_Terminate);
4167 else
4168 CHECK_CALLED(Terminate);
4170 if(filtered_protocol)
4171 IInternetProtocol_Release(filtered_protocol);
4172 IInternetBindInfo_Release(prot_bind_info);
4173 IInternetProtocolSink_Release(binding_sink);
4175 SET_EXPECT(Protocol_destructor);
4176 ref = IInternetProtocol_Release(protocol);
4177 ok(!ref, "ref=%u, expected 0\n", ref);
4178 CHECK_CALLED(Protocol_destructor);
4180 if(test_flags & TEST_EMULATEPROT) {
4181 hres = IInternetSession_UnregisterNameSpace(session, &ClassFactory, protocol_names[prot]);
4182 ok(hres == S_OK, "UnregisterNameSpace failed: %08x\n", hres);
4185 IInternetSession_Release(session);
4188 static const IID outer_test_iid = {0xabcabc00,0,0,{0,0,0,0,0,0,0,0x66}};
4190 static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
4192 if(IsEqualGUID(riid, &outer_test_iid)) {
4193 CHECK_EXPECT(outer_QI_test);
4194 *ppv = (IUnknown*)0xdeadbeef;
4195 return S_OK;
4197 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
4198 return E_NOINTERFACE;
4201 static ULONG WINAPI outer_AddRef(IUnknown *iface)
4203 return 2;
4206 static ULONG WINAPI outer_Release(IUnknown *iface)
4208 return 1;
4211 static const IUnknownVtbl outer_vtbl = {
4212 outer_QueryInterface,
4213 outer_AddRef,
4214 outer_Release
4217 static void test_com_aggregation(const CLSID *clsid)
4219 IUnknown outer = { &outer_vtbl };
4220 IClassFactory *class_factory;
4221 IUnknown *unk, *unk2, *unk3;
4222 HRESULT hres;
4224 hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&class_factory);
4225 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
4227 hres = IClassFactory_CreateInstance(class_factory, &outer, &IID_IUnknown, (void**)&unk);
4228 ok(hres == S_OK, "CreateInstance returned: %08x\n", hres);
4230 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&unk2);
4231 ok(hres == S_OK, "Could not get IDispatch iface: %08x\n", hres);
4233 SET_EXPECT(outer_QI_test);
4234 hres = IUnknown_QueryInterface(unk2, &outer_test_iid, (void**)&unk3);
4235 CHECK_CALLED(outer_QI_test);
4236 ok(hres == S_OK, "Could not get IInternetProtocol iface: %08x\n", hres);
4237 ok(unk3 == (IUnknown*)0xdeadbeef, "unexpected unk2\n");
4239 IUnknown_Release(unk2);
4240 IUnknown_Release(unk);
4242 unk = (void*)0xdeadbeef;
4243 hres = IClassFactory_CreateInstance(class_factory, &outer, &IID_IInternetProtocol, (void**)&unk);
4244 ok(hres == CLASS_E_NOAGGREGATION, "CreateInstance returned: %08x\n", hres);
4245 ok(!unk, "unk = %p\n", unk);
4247 IClassFactory_Release(class_factory);
4250 START_TEST(protocol)
4252 HMODULE hurlmon;
4254 hurlmon = GetModuleHandleA("urlmon.dll");
4255 pCoInternetGetSession = (void*) GetProcAddress(hurlmon, "CoInternetGetSession");
4256 pReleaseBindInfo = (void*) GetProcAddress(hurlmon, "ReleaseBindInfo");
4257 pCreateUri = (void*) GetProcAddress(hurlmon, "CreateUri");
4259 if(!GetProcAddress(hurlmon, "CompareSecurityIds")) {
4260 win_skip("Various needed functions not present, too old IE\n");
4261 return;
4264 if(!pCreateUri)
4265 win_skip("CreateUri not supported\n");
4267 OleInitialize(NULL);
4269 event_complete = CreateEventW(NULL, FALSE, FALSE, NULL);
4270 event_complete2 = CreateEventW(NULL, FALSE, FALSE, NULL);
4271 event_continue = CreateEventW(NULL, FALSE, FALSE, NULL);
4272 event_continue_done = CreateEventW(NULL, FALSE, FALSE, NULL);
4273 thread_id = GetCurrentThreadId();
4275 test_file_protocol();
4276 test_http_protocol();
4277 if(pCreateUri)
4278 test_https_protocol();
4279 else
4280 win_skip("Skipping https tests on too old platform\n");
4281 test_ftp_protocol();
4282 test_gopher_protocol();
4283 test_mk_protocol();
4284 test_CreateBinding();
4285 no_aggregation = TRUE;
4286 test_CreateBinding();
4287 no_aggregation = FALSE;
4289 bindf &= ~BINDF_FROMURLMON;
4290 trace("Testing file binding (mime verification, emulate prot)...\n");
4291 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
4292 trace("Testing http binding (mime verification, emulate prot)...\n");
4293 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
4294 trace("Testing its binding (mime verification, emulate prot)...\n");
4295 test_binding(ITS_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT);
4296 trace("Testing http binding (mime verification, emulate prot, short read, direct read)...\n");
4297 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_SHORT_READ|TEST_DIRECT_READ);
4298 trace("Testing http binding (mime verification, redirect, emulate prot)...\n");
4299 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_REDIRECT);
4300 trace("Testing http binding (mime verification, redirect, disable auto redirect, emulate prot)...\n");
4301 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_REDIRECT|TEST_DISABLEAUTOREDIRECT);
4302 trace("Testing file binding (mime verification, emulate prot, mime filter)...\n");
4303 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
4304 trace("Testing http binding (mime verification, emulate prot, mime filter)...\n");
4305 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER);
4306 trace("Testing http binding (mime verification, emulate prot, mime filter, no mime)...\n");
4307 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_FILTER|TEST_NOMIME);
4308 trace("Testing http binding (mime verification, emulate prot, direct read)...\n");
4309 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_DIRECT_READ);
4310 trace("Testing http binding (mime verification, emulate prot, abort)...\n");
4311 test_binding(HTTP_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_ABORT);
4312 if(pCreateUri) {
4313 trace("Testing file binding (use IUri, mime verification, emulate prot)...\n");
4314 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI);
4315 trace("Testing file binding (use IUri, impl StartEx, mime verification, emulate prot)...\n");
4316 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_USEIURI|TEST_IMPLPROTEX);
4317 trace("Testing file binding (impl StartEx, mime verification, emulate prot)...\n");
4318 test_binding(FILE_TEST, PI_MIMEVERIFICATION, TEST_EMULATEPROT|TEST_IMPLPROTEX);
4321 CloseHandle(event_complete);
4322 CloseHandle(event_complete2);
4323 CloseHandle(event_continue);
4324 CloseHandle(event_continue_done);
4326 test_com_aggregation(&CLSID_FileProtocol);
4327 test_com_aggregation(&CLSID_HttpProtocol);
4328 test_com_aggregation(&CLSID_HttpSProtocol);
4329 test_com_aggregation(&CLSID_FtpProtocol);
4330 test_com_aggregation(&CLSID_MkProtocol);
4332 OleUninitialize();