itss: Use wide-char string literals.
[wine.git] / dlls / itss / tests / protocol.c
blob43d867b9cfbfb0cbc803a18ae41860641a899aab
1 /*
2 * Copyright 2006 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <wine/test.h>
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "initguid.h"
27 #include "ole2.h"
28 #include "urlmon.h"
29 #include "shlwapi.h"
31 #define DEFINE_EXPECT(func) \
32 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34 #define SET_EXPECT(func) \
35 expect_ ## func = TRUE
37 #define CHECK_EXPECT(func) \
38 do { \
39 ok(expect_ ##func, "unexpected call " #func "\n"); \
40 expect_ ## func = FALSE; \
41 called_ ## func = TRUE; \
42 }while(0)
44 #define SET_CALLED(func) \
45 expect_ ## func = called_ ## func = FALSE
47 #define CHECK_CALLED(func) \
48 do { \
49 ok(called_ ## func, "expected " #func "\n"); \
50 SET_CALLED(func); \
51 }while(0)
53 DEFINE_GUID(CLSID_ITSProtocol,0x9d148291,0xb9c8,0x11d0,0xa4,0xcc,0x00,0x00,0xf8,0x01,0x49,0xf6);
55 DEFINE_EXPECT(GetBindInfo);
56 DEFINE_EXPECT(ReportProgress_BEGINDOWNLOADDATA);
57 DEFINE_EXPECT(ReportProgress_SENDINGREQUEST);
58 DEFINE_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
59 DEFINE_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
60 DEFINE_EXPECT(ReportProgress_DIRECTBIND);
61 DEFINE_EXPECT(ReportData);
62 DEFINE_EXPECT(ReportResult);
63 DEFINE_EXPECT(outer_QI_test);
65 static HRESULT expect_hrResult;
66 static IInternetProtocol *read_protocol = NULL;
67 static DWORD bindf;
69 static const WCHAR blank_url1[] = L"its:test.chm::/blank.html";
70 static const WCHAR blank_url2[] = L"mS-iTs:test.chm::/blank.html";
71 static const WCHAR blank_url3[] = L"mk:@MSITStore:test.chm::/blank.html";
72 static const WCHAR blank_url4[] = L"its:test.chm::blank.html";
73 static const WCHAR blank_url5[] = L"its:test.chm::\\blank.html";
74 static const WCHAR blank_url6[] = L"its:test.chm::/%62lank.html";
75 static const WCHAR blank_url7[] = L"mk:@MSITStore:test.chm::\\blank.html";
76 static const WCHAR blank_url8[] = L"mk:@MSITStore:test.chm::/blank.html/";
77 static const WCHAR blank_url9[] = L"its:test.chm::/dir/../blank.html";
79 static enum {
80 ITS_PROTOCOL,
81 MK_PROTOCOL
82 } test_protocol;
84 static const WCHAR cache_file1[] = L"test.chm::/blank.html";
85 static const WCHAR cache_file2[] = L"test.chm::\\blank.html";
86 static const WCHAR cache_file3[] = L"test.chm::/blank.html/";
87 static const WCHAR *cache_file = cache_file1;
89 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
91 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
92 *ppv = iface;
93 return S_OK;
95 return E_NOINTERFACE;
98 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
100 return 2;
103 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
105 return 1;
108 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
110 ok(0, "unexpected call\n");
111 return E_NOTIMPL;
114 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
115 LPCWSTR szStatusText)
117 switch(ulStatusCode) {
118 case BINDSTATUS_BEGINDOWNLOADDATA:
119 CHECK_EXPECT(ReportProgress_BEGINDOWNLOADDATA);
120 ok(!szStatusText, "szStatusText != NULL\n");
121 break;
122 case BINDSTATUS_SENDINGREQUEST:
123 CHECK_EXPECT(ReportProgress_SENDINGREQUEST);
124 if(test_protocol == ITS_PROTOCOL)
125 ok(!lstrcmpW(szStatusText, L"blank.html"), "unexpected szStatusText\n");
126 else
127 ok(szStatusText == NULL, "szStatusText != NULL\n");
128 break;
129 case BINDSTATUS_MIMETYPEAVAILABLE:
130 CHECK_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
131 ok(!lstrcmpW(szStatusText, L"text/html"), "unexpected szStatusText\n");
132 break;
133 case BINDSTATUS_CACHEFILENAMEAVAILABLE:
134 CHECK_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
135 ok(!lstrcmpW(szStatusText, cache_file), "unexpected szStatusText\n");
136 break;
137 case BINDSTATUS_DIRECTBIND:
138 CHECK_EXPECT(ReportProgress_DIRECTBIND);
139 ok(!szStatusText, "szStatusText != NULL\n");
140 break;
141 default:
142 ok(0, "unexpected ulStatusCode %d\n", ulStatusCode);
143 break;
146 return S_OK;
149 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF, ULONG ulProgress,
150 ULONG ulProgressMax)
152 CHECK_EXPECT(ReportData);
154 ok(ulProgress == ulProgressMax, "ulProgress != ulProgressMax\n");
155 if(test_protocol == ITS_PROTOCOL)
156 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE), "grcf = %08x\n", grfBSCF);
157 else
158 ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION), "grcf = %08x\n", grfBSCF);
160 if(read_protocol) {
161 BYTE buf[100];
162 DWORD cb = 0xdeadbeef;
163 HRESULT hres;
165 hres = IInternetProtocol_Read(read_protocol, buf, sizeof(buf), &cb);
166 ok(hres == S_OK, "Read failed: %08x\n", hres);
167 ok(cb == 13, "cb=%u expected 13\n", cb);
168 ok(!memcmp(buf, "<html></html>", 13), "unexpected data\n");
171 return S_OK;
174 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult,
175 DWORD dwError, LPCWSTR szResult)
177 CHECK_EXPECT(ReportResult);
179 ok(hrResult == expect_hrResult, "expected: %08x got: %08x\n", expect_hrResult, hrResult);
180 ok(dwError == 0, "dwError = %d\n", dwError);
181 ok(!szResult, "szResult != NULL\n");
183 return S_OK;
186 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
187 ProtocolSink_QueryInterface,
188 ProtocolSink_AddRef,
189 ProtocolSink_Release,
190 ProtocolSink_Switch,
191 ProtocolSink_ReportProgress,
192 ProtocolSink_ReportData,
193 ProtocolSink_ReportResult
196 static IInternetProtocolSink protocol_sink = {
197 &protocol_sink_vtbl
200 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
202 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
203 *ppv = iface;
204 return S_OK;
206 return E_NOINTERFACE;
209 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
211 return 2;
214 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
216 return 1;
219 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
221 CHECK_EXPECT(GetBindInfo);
223 ok(grfBINDF != NULL, "grfBINDF == NULL\n");
224 if(grfBINDF)
225 ok(!*grfBINDF, "*grfBINDF != 0\n");
226 ok(pbindinfo != NULL, "pbindinfo == NULL\n");
227 ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
229 *grfBINDF = bindf;
230 return S_OK;
233 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType, LPOLESTR *ppwzStr,
234 ULONG cEl, ULONG *pcElFetched)
236 ok(0, "unexpected call\n");
237 return E_NOTIMPL;
240 static IInternetBindInfoVtbl bind_info_vtbl = {
241 BindInfo_QueryInterface,
242 BindInfo_AddRef,
243 BindInfo_Release,
244 BindInfo_GetBindInfo,
245 BindInfo_GetBindString
248 static IInternetBindInfo bind_info = {
249 &bind_info_vtbl
252 static void test_protocol_fail(IInternetProtocol *protocol, LPCWSTR url, HRESULT expected_hres)
254 HRESULT hres;
256 SET_EXPECT(GetBindInfo);
257 SET_EXPECT(ReportResult);
259 expect_hrResult = expected_hres;
260 hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
261 ok(hres == expected_hres, "expected: %08x got: %08x\n", expected_hres, hres);
263 CHECK_CALLED(GetBindInfo);
264 CHECK_CALLED(ReportResult);
267 #define protocol_start(p,u,e) _protocol_start(__LINE__,p,u,e)
268 static HRESULT _protocol_start(unsigned line, IInternetProtocol *protocol, LPCWSTR url, BOOL expect_mime)
270 HRESULT hres;
272 SET_EXPECT(GetBindInfo);
273 if(test_protocol == MK_PROTOCOL)
274 SET_EXPECT(ReportProgress_DIRECTBIND);
275 SET_EXPECT(ReportProgress_SENDINGREQUEST);
276 if(expect_mime)
277 SET_EXPECT(ReportProgress_MIMETYPEAVAILABLE);
278 if(test_protocol == MK_PROTOCOL)
279 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
280 SET_EXPECT(ReportData);
281 if(test_protocol == ITS_PROTOCOL)
282 SET_EXPECT(ReportProgress_BEGINDOWNLOADDATA);
283 SET_EXPECT(ReportResult);
284 expect_hrResult = S_OK;
286 hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
288 if(FAILED(hres)) {
289 SET_CALLED(GetBindInfo);
290 if(test_protocol == MK_PROTOCOL)
291 SET_CALLED(ReportProgress_DIRECTBIND);
292 SET_CALLED(ReportProgress_SENDINGREQUEST);
293 if(expect_mime)
294 SET_CALLED(ReportProgress_MIMETYPEAVAILABLE);
295 if(test_protocol == MK_PROTOCOL)
296 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
297 SET_CALLED(ReportData);
298 if(test_protocol == ITS_PROTOCOL)
299 SET_CALLED(ReportProgress_BEGINDOWNLOADDATA);
300 SET_CALLED(ReportResult);
301 }else {
302 CHECK_CALLED(GetBindInfo);
303 if(test_protocol == MK_PROTOCOL)
304 SET_CALLED(ReportProgress_DIRECTBIND);
305 CHECK_CALLED(ReportProgress_SENDINGREQUEST);
306 if(expect_mime)
307 CHECK_CALLED(ReportProgress_MIMETYPEAVAILABLE);
308 if(test_protocol == MK_PROTOCOL)
309 SET_EXPECT(ReportProgress_CACHEFILENAMEAVAILABLE);
310 CHECK_CALLED(ReportData);
311 if(test_protocol == ITS_PROTOCOL)
312 CHECK_CALLED(ReportProgress_BEGINDOWNLOADDATA);
313 CHECK_CALLED(ReportResult);
316 return hres;
319 static void test_protocol_url(IClassFactory *factory, LPCWSTR url, BOOL expect_mime)
321 IInternetProtocol *protocol;
322 BYTE buf[512];
323 ULONG cb, ref;
324 HRESULT hres;
326 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
327 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
328 if(FAILED(hres))
329 return;
331 hres = protocol_start(protocol, url, expect_mime);
332 if(FAILED(hres)) {
333 IInternetProtocol_Release(protocol);
334 return;
337 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
338 ok(hres == S_OK, "Read failed: %08x\n", hres);
339 ok(cb == 13, "cb=%u expected 13\n", cb);
340 ok(!memcmp(buf, "<html></html>", 13), "unexpected data\n");
341 ref = IInternetProtocol_Release(protocol);
342 ok(!ref, "protocol ref=%d\n", ref);
344 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
345 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
346 if(FAILED(hres))
347 return;
349 cb = 0xdeadbeef;
350 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
351 ok(hres == (test_protocol == ITS_PROTOCOL ? INET_E_DATA_NOT_AVAILABLE : E_FAIL),
352 "Read returned %08x\n", hres);
353 ok(cb == 0xdeadbeef, "cb=%u expected 0xdeadbeef\n", cb);
355 protocol_start(protocol, url, expect_mime);
356 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
357 ok(hres == S_OK, "Read failed: %08x\n", hres);
358 ok(cb == 2, "cb=%u expected 2\n", cb);
359 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
360 ok(hres == S_OK, "Read failed: %08x\n", hres);
361 ok(cb == 11, "cb=%u, expected 11\n", cb);
362 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
363 ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
364 ok(cb == 0, "cb=%u expected 0\n", cb);
365 hres = IInternetProtocol_UnlockRequest(protocol);
366 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
367 ref = IInternetProtocol_Release(protocol);
368 ok(!ref, "protocol ref=%d\n", ref);
370 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
371 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
372 if(FAILED(hres))
373 return;
375 protocol_start(protocol, url, expect_mime);
376 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
377 ok(hres == S_OK, "Read failed: %08x\n", hres);
378 hres = IInternetProtocol_LockRequest(protocol, 0);
379 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
380 hres = IInternetProtocol_UnlockRequest(protocol);
381 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
382 hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
383 ok(hres == S_OK, "Read failed: %08x\n", hres);
384 ok(cb == 11, "cb=%u, expected 11\n", cb);
385 ref = IInternetProtocol_Release(protocol);
386 ok(!ref, "protocol ref=%d\n", ref);
388 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
389 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
390 if(FAILED(hres))
391 return;
393 protocol_start(protocol, url, expect_mime);
394 hres = IInternetProtocol_LockRequest(protocol, 0);
395 ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
396 hres = IInternetProtocol_Terminate(protocol, 0);
397 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
398 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
399 ok(hres == S_OK, "Read failed: %08x\n", hres);
400 ok(cb == 2, "cb=%u, expected 2\n", cb);
401 hres = IInternetProtocol_UnlockRequest(protocol);
402 ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
403 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
404 ok(hres == S_OK, "Read failed: %08x\n", hres);
405 ok(cb == 2, "cb=%u, expected 2\n", cb);
406 hres = IInternetProtocol_Terminate(protocol, 0);
407 ok(hres == S_OK, "Terminate failed: %08x\n", hres);
408 hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
409 ok(hres == S_OK, "Read failed: %08x\n", hres);
410 ok(cb == 2, "cb=%u expected 2\n", cb);
411 ref = IInternetProtocol_Release(protocol);
412 ok(!ref, "protocol ref=%d\n", ref);
414 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&read_protocol);
415 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
416 if(FAILED(hres))
417 return;
419 protocol_start(read_protocol, url, expect_mime);
420 ref = IInternetProtocol_Release(read_protocol);
421 ok(!ref, "protocol ref=%d\n", ref);
422 read_protocol = NULL;
425 static const struct {
426 const WCHAR *base_url;
427 const WCHAR *rel_url;
428 DWORD flags;
429 HRESULT hres;
430 const WCHAR *combined_url;
431 } combine_tests[] = {
432 {L"its:test.chm::/blank.html", L"its:test.chm::/blank.html", 0, STG_E_INVALIDNAME, NULL},
433 {L"mS-iTs:test.chm::/blank.html", L"mS-iTs:test.chm::/blank.html", 0, STG_E_INVALIDNAME, NULL},
434 {L"its:test.chm::/blank.html", L"test.html", 0, S_OK, L"its:test.chm::/test.html"},
435 {L"its:test.chm::/blank.html", L"test.chm::/test.html", 0, STG_E_INVALIDNAME, NULL},
436 {L"its:test.chm::/blank.html", L"/test.html", 0, S_OK, L"its:test.chm::/test.html"},
437 {L"its:test.chm::/blank.html", L"te:t.html", 0, STG_E_INVALIDNAME, NULL},
438 {L"its:test.chm::/blank.html", L"/test.html", URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO, S_OK, L"its:test.chm::/test.html"},
439 {L"its:test.chm::/blank.html", L"dir/test.html", 0, S_OK, L"its:test.chm::/dir/test.html"},
440 {L"test.html", L"test.chm::/test.html", 0, 0x80041001, NULL},
441 {L"its:test:.chm::/blank.html", L"test.html", 0, S_OK, L"its:test:.chm::/test.html"},
442 {L"its:test.chm::/dir/blank.html", L"test.html", 0, S_OK, L"its:test.chm::/dir/test.html"},
443 {L"its:test.chm::blank.html", L"test.html", 0, S_OK, L"its:test.chm::blank.htmltest.html"},
444 {L"ms-its:test.chm::/dir/blank.html", L"test.html", 0, S_OK, L"ms-its:test.chm::/dir/test.html"},
445 {L"mk:@MSITStore:test.chm::/dir/blank.html", L"test.html", 0, S_OK, L"mk:@MSITStore:test.chm::/dir/test.html"},
446 {L"xxx:test.chm::/dir/blank.html", L"test.html", 0, INET_E_USE_DEFAULT_PROTOCOLHANDLER, NULL},
447 {L"its:test.chm::/dir/blank.html", L"/test.html", 0, S_OK, L"its:test.chm::/test.html"},
448 {L"its:test.chm::/blank.html", L"#frag", 0, S_OK, L"its:test.chm::/blank.html#frag"},
449 {L"its:test.chm::/blank.html#hash", L"#frag", 0, S_OK, L"its:test.chm::/blank.html#hash#frag"},
450 {L"its:test.chm::/blank.html", L"test.html#frag", 0, S_OK, L"its:test.chm::/test.html#frag"},
451 {L"its:test.chm::/blank.html", L"/test.html#frag", 0, S_OK, L"its:test.chm::/test.html#frag"},
452 {L"its:test.chm::/blank.html", L"?query", 0, S_OK, L"its:test.chm::/?query"},
453 {L"its:test.chm::/blank.html#frag/blank", L"test.html", 0, S_OK, L"its:test.chm::/blank.html#frag/test.html"},
456 static void test_its_protocol_info(IInternetProtocol *protocol)
458 IInternetProtocolInfo *info;
459 WCHAR buf[1024];
460 DWORD size, i;
461 HRESULT hres;
463 hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolInfo, (void**)&info);
464 ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08x\n", hres);
465 if(FAILED(hres))
466 return;
468 for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
469 if(i != PARSE_CANONICALIZE && i != PARSE_SECURITY_URL) {
470 hres = IInternetProtocolInfo_ParseUrl(info, blank_url1, i, 0, buf,
471 ARRAY_SIZE(buf), &size, 0);
472 ok(hres == INET_E_DEFAULT_ACTION,
473 "[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
477 for(i=0; i < ARRAY_SIZE(combine_tests); i++) {
478 size = 0xdeadbeef;
479 memset(buf, 0xfe, sizeof(buf));
480 hres = IInternetProtocolInfo_CombineUrl(info, combine_tests[i].base_url,
481 combine_tests[i].rel_url, combine_tests[i].flags, buf, ARRAY_SIZE(buf), &size, 0);
482 ok(hres == combine_tests[i].hres, "[%d] CombineUrl returned %08x, expected %08x\n",
483 i, hres, combine_tests[i].hres);
484 ok(size == (combine_tests[i].combined_url ? lstrlenW(combine_tests[i].combined_url)+1
485 : 0xdeadbeef), "[%d] unexpected size=%d\n", i, size);
486 if(combine_tests[i].combined_url)
487 ok(!lstrcmpW(buf, combine_tests[i].combined_url), "[%d] unexpected result: %s\n", i, wine_dbgstr_w(buf));
488 else
489 ok(buf[0] == 0xfefe, "buf changed\n");
492 size = 0xdeadbeef;
493 memset(buf, 0xfe, sizeof(buf));
494 hres = IInternetProtocolInfo_CombineUrl(info, L"its:test.chm::/blank.html", L"test.html", 0, buf,
495 1, &size, 0);
496 ok(hres == E_OUTOFMEMORY, "CombineUrl failed: %08x\n", hres);
497 ok(size == 25, "size=%d\n", size);
498 ok(buf[0] == 0xfefe, "buf changed\n");
500 IInternetProtocolInfo_Release(info);
503 static void test_its_protocol(void)
505 IInternetProtocolInfo *info;
506 IClassFactory *factory;
507 IUnknown *unk;
508 ULONG ref;
509 HRESULT hres;
511 static const WCHAR wrong_url1[] = L"its:test.chm::/blan.html";
512 static const WCHAR wrong_url2[] = L"its:tes.chm::b/lank.html";
513 static const WCHAR wrong_url3[] = L"its:test.chm/blank.html";
514 static const WCHAR wrong_url4[] = L"mk:@MSITStor:test.chm::/blank.html";
515 static const WCHAR wrong_url5[] = L"file:tes.chm::/blank.html";
517 test_protocol = ITS_PROTOCOL;
519 hres = CoGetClassObject(&CLSID_ITSProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
520 ok(hres == S_OK ||
521 broken(hres == REGDB_E_CLASSNOTREG), /* Some W95 and NT4 */
522 "CoGetClassObject failed: %08x\n", hres);
523 if(FAILED(hres))
524 return;
526 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&info);
527 ok(hres == E_NOINTERFACE, "Could not get IInternetProtocolInfo: %08x\n", hres);
529 hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
530 ok(hres == S_OK, "Could not get IClassFactory interface\n");
531 if(SUCCEEDED(hres)) {
532 IInternetProtocol *protocol;
534 hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
535 ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
536 if(SUCCEEDED(hres)) {
537 test_its_protocol_info(protocol);
539 test_protocol_fail(protocol, wrong_url1, STG_E_FILENOTFOUND);
540 test_protocol_fail(protocol, wrong_url2, STG_E_FILENOTFOUND);
541 test_protocol_fail(protocol, wrong_url3, STG_E_FILENOTFOUND);
543 hres = IInternetProtocol_Start(protocol, wrong_url4, &protocol_sink, &bind_info, 0, 0);
544 ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
545 "Start failed: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", hres);
547 hres = IInternetProtocol_Start(protocol, wrong_url5, &protocol_sink, &bind_info, 0, 0);
548 ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
549 "Start failed: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", hres);
551 ref = IInternetProtocol_Release(protocol);
552 ok(!ref, "protocol ref=%d\n", ref);
554 test_protocol_url(factory, blank_url1, TRUE);
555 test_protocol_url(factory, blank_url2, TRUE);
556 test_protocol_url(factory, blank_url3, TRUE);
557 test_protocol_url(factory, blank_url4, TRUE);
558 test_protocol_url(factory, blank_url5, TRUE);
559 test_protocol_url(factory, blank_url6, TRUE);
560 test_protocol_url(factory, blank_url8, TRUE);
561 test_protocol_url(factory, blank_url9, TRUE);
562 bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
563 test_protocol_url(factory, blank_url1, TRUE);
566 IClassFactory_Release(factory);
569 IUnknown_Release(unk);
572 static void test_mk_protocol(void)
574 IClassFactory *cf;
575 HRESULT hres;
577 test_protocol = MK_PROTOCOL;
579 hres = CoGetClassObject(&CLSID_MkProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory,
580 (void**)&cf);
581 ok(hres == S_OK ||
582 broken(hres == REGDB_E_CLASSNOTREG), /* Some W95 and NT4 */
583 "CoGetClassObject failed: %08x\n", hres);
584 if(FAILED(hres))
585 return;
587 cache_file = cache_file1;
588 test_protocol_url(cf, blank_url3, TRUE);
589 cache_file = cache_file2;
590 test_protocol_url(cf, blank_url7, TRUE);
591 cache_file = cache_file3;
592 test_protocol_url(cf, blank_url8, FALSE);
594 IClassFactory_Release(cf);
597 static BOOL create_chm(void)
599 HANDLE file;
600 HRSRC src;
601 DWORD size;
603 file = CreateFileA("test.chm", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
604 FILE_ATTRIBUTE_NORMAL, NULL);
605 ok(file != INVALID_HANDLE_VALUE, "Could not create test.chm file\n");
606 if(file == INVALID_HANDLE_VALUE)
607 return FALSE;
609 src = FindResourceA(NULL, MAKEINTRESOURCEA(60), MAKEINTRESOURCEA(60));
611 WriteFile(file, LoadResource(NULL, src), SizeofResource(NULL, src), &size, NULL);
612 CloseHandle(file);
614 return TRUE;
617 static void delete_chm(void)
619 BOOL ret;
621 ret = DeleteFileA("test.chm");
622 ok(ret, "DeleteFileA failed: %d\n", GetLastError());
625 static const IID outer_test_iid = {0xabcabc00,0,0,{0,0,0,0,0,0,0,0x66}};
627 static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
629 if(IsEqualGUID(riid, &outer_test_iid)) {
630 CHECK_EXPECT(outer_QI_test);
631 *ppv = (IUnknown*)0xdeadbeef;
632 return S_OK;
634 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
635 return E_NOINTERFACE;
638 static ULONG WINAPI outer_AddRef(IUnknown *iface)
640 return 2;
643 static ULONG WINAPI outer_Release(IUnknown *iface)
645 return 1;
648 static const IUnknownVtbl outer_vtbl = {
649 outer_QueryInterface,
650 outer_AddRef,
651 outer_Release
654 static void test_com_aggregation(const CLSID *clsid)
656 IUnknown outer = { &outer_vtbl };
657 IClassFactory *class_factory;
658 IUnknown *unk, *unk2, *unk3;
659 HRESULT hres;
661 hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**)&class_factory);
662 ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
664 hres = IClassFactory_CreateInstance(class_factory, &outer, &IID_IUnknown, (void**)&unk);
665 ok(hres == S_OK, "CreateInstance returned: %08x\n", hres);
667 hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&unk2);
668 ok(hres == S_OK, "Could not get IInternetProtocol iface: %08x\n", hres);
670 SET_EXPECT(outer_QI_test);
671 hres = IUnknown_QueryInterface(unk2, &outer_test_iid, (void**)&unk3);
672 CHECK_CALLED(outer_QI_test);
673 ok(hres == S_OK, "Could not get IInternetProtocol iface: %08x\n", hres);
674 ok(unk3 == (IUnknown*)0xdeadbeef, "unexpected unk2\n");
676 IUnknown_Release(unk2);
677 IUnknown_Release(unk);
679 unk = (void*)0xdeadbeef;
680 hres = IClassFactory_CreateInstance(class_factory, &outer, &IID_IInternetProtocol, (void**)&unk);
681 ok(hres == CLASS_E_NOAGGREGATION, "CreateInstance returned: %08x\n", hres);
682 ok(!unk, "unk = %p\n", unk);
684 IClassFactory_Release(class_factory);
687 START_TEST(protocol)
689 OleInitialize(NULL);
691 if(!create_chm())
692 return;
694 test_its_protocol();
695 test_mk_protocol();
696 test_com_aggregation(&CLSID_ITSProtocol);
698 delete_chm();
699 OleUninitialize();