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