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