1 /*
2  * Copyright 2005 Jacek Caban
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 #include "precomp.h"
20 
21 #include <shlwapi.h>
22 
23 #include <initguid.h>
24 
25 #define DEFINE_EXPECT(func) \
26     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
27 
28 #define SET_EXPECT(func) \
29     expect_ ## func = TRUE
30 
31 #define CHECK_EXPECT(func) \
32     do { \
33         ok(expect_ ##func, "unexpected call " #func "\n"); \
34         expect_ ## func = FALSE; \
35         called_ ## func = TRUE; \
36     }while(0)
37 
38 #define CHECK_EXPECT2(func) \
39     do { \
40         ok(expect_ ##func, "unexpected call " #func  "\n"); \
41         called_ ## func = TRUE; \
42     }while(0)
43 
44 #define CHECK_CALLED(func) \
45     do { \
46         ok(called_ ## func, "expected " #func "\n"); \
47         expect_ ## func = called_ ## func = FALSE; \
48     }while(0)
49 
50 DEFINE_GUID(CLSID_ResProtocol, 0x3050F3BC, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
51 DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
52 DEFINE_GUID(CLSID_JSProtocol, 0x3050F3B2, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
53 
54 DEFINE_EXPECT(GetBindInfo);
55 DEFINE_EXPECT(ReportProgress);
56 DEFINE_EXPECT(ReportData);
57 DEFINE_EXPECT(ReportResult);
58 
59 static HRESULT expect_hrResult;
60 static BOOL expect_hr_win32err = FALSE;
61 static DWORD bindf;
62 
63 static const WCHAR about_blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
64 static const WCHAR about_test_url[] = {'a','b','o','u','t',':','t','e','s','t',0};
65 static const WCHAR about_res_url[] = {'r','e','s',':','b','l','a','n','k',0};
66 static const WCHAR javascript_test_url[] = {'j','a','v','a','s','c','r','i','p','t',':','t','e','s','t','(',')',0};
67 
68 static WCHAR res_url_base[INTERNET_MAX_URL_LENGTH] = {'r','e','s',':','/','/'};
69 static unsigned res_url_base_len;
70 
71 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
72 {
73     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
74         *ppv = iface;
75         return S_OK;
76     }
77 
78     *ppv = NULL;
79     ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
80     return E_NOINTERFACE;
81 }
82 
83 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
84 {
85     return 2;
86 }
87 
88 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
89 {
90     return 1;
91 }
92 
93 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
94 {
95     ok(0, "unexpected call\n");
96     return E_NOTIMPL;
97 }
98 
99 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
100         LPCWSTR szStatusText)
101 {
102     static const WCHAR text_html[] = {'t','e','x','t','/','h','t','m','l',0};
103 
104     CHECK_EXPECT(ReportProgress);
105 
106     ok(ulStatusCode == BINDSTATUS_MIMETYPEAVAILABLE
107             || ulStatusCode == BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
108             "ulStatusCode=%d\n", ulStatusCode);
109     ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
110 
111     return S_OK;
112 }
113 
114 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF, ULONG ulProgress,
115         ULONG ulProgressMax)
116 {
117     CHECK_EXPECT(ReportData);
118 
119     ok(ulProgress == ulProgressMax, "ulProgress != ulProgressMax\n");
120     ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE),
121             "grcf = %08x\n", grfBSCF);
122 
123     return S_OK;
124 }
125 
126 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult, DWORD dwError,
127         LPCWSTR szResult)
128 {
129     CHECK_EXPECT(ReportResult);
130 
131     if(expect_hr_win32err) {
132         ok((hrResult&0xffff0000) == ((FACILITY_WIN32 << 16)|0x80000000) || expect_hrResult,
133                 "expected win32 err or %08x got: %08x\n", expect_hrResult, hrResult);
134     }else {
135         ok(hrResult == expect_hrResult || (expect_hrResult == E_INVALIDARG && hrResult == MK_E_SYNTAX)
136            || (expect_hrResult == HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND) &&
137                (hrResult == MK_E_SYNTAX || hrResult == HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND))),
138            "expected: %08x got: %08x\n", expect_hrResult, hrResult);
139         expect_hrResult = hrResult;
140     }
141     ok(dwError == 0, "dwError = %d\n", dwError);
142     ok(!szResult, "szResult != NULL\n");
143 
144     return S_OK;
145 }
146 
147 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
148     ProtocolSink_QueryInterface,
149     ProtocolSink_AddRef,
150     ProtocolSink_Release,
151     ProtocolSink_Switch,
152     ProtocolSink_ReportProgress,
153     ProtocolSink_ReportData,
154     ProtocolSink_ReportResult
155 };
156 
157 static IInternetProtocolSink protocol_sink = {
158     &protocol_sink_vtbl
159 };
160 
161 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
162 {
163     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
164         *ppv = iface;
165         return S_OK;
166     }
167 
168     *ppv = NULL;
169     ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
170     return E_NOINTERFACE;
171 }
172 
173 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
174 {
175     return 2;
176 }
177 
178 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
179 {
180     return 1;
181 }
182 
183 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
184 {
185     CHECK_EXPECT(GetBindInfo);
186 
187     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
188     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
189     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
190 
191     *grfBINDF = bindf;
192     return S_OK;
193 }
194 
195 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType, LPOLESTR *ppwzStr,
196         ULONG cEl, ULONG *pcElFetched)
197 {
198     ok(0, "unexpected call\n");
199     return E_NOTIMPL;
200 }
201 
202 static IInternetBindInfoVtbl bind_info_vtbl = {
203     BindInfo_QueryInterface,
204     BindInfo_AddRef,
205     BindInfo_Release,
206     BindInfo_GetBindInfo,
207     BindInfo_GetBindString
208 };
209 
210 static IInternetBindInfo bind_info = {
211     &bind_info_vtbl
212 };
213 
214 static void test_protocol_fail(IInternetProtocol *protocol, LPCWSTR url, HRESULT expected_hres,
215         BOOL expect_win32err)
216 {
217     HRESULT hres;
218 
219     SET_EXPECT(GetBindInfo);
220     SET_EXPECT(ReportResult);
221 
222     expect_hrResult = expected_hres;
223     expect_hr_win32err = expect_win32err;
224     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
225     if(expect_win32err)
226         ok((hres&0xffff0000) == ((FACILITY_WIN32 << 16)|0x80000000) || hres == expect_hrResult,
227                 "expected win32 err or %08x got: %08x\n", expected_hres, hres);
228     else
229         ok(hres == expect_hrResult, "expected: %08x got: %08x\n", expect_hrResult, hres);
230 
231     CHECK_CALLED(GetBindInfo);
232     CHECK_CALLED(ReportResult);
233 }
234 
235 static void protocol_start(IInternetProtocol *protocol, const WCHAR *url)
236 {
237     HRESULT hres;
238 
239     SET_EXPECT(GetBindInfo);
240     SET_EXPECT(ReportResult);
241     SET_EXPECT(ReportProgress);
242     SET_EXPECT(ReportData);
243     expect_hrResult = S_OK;
244     expect_hr_win32err = FALSE;
245 
246     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
247     ok(hres == S_OK, "Start failed: %08x\n", hres);
248 
249     CHECK_CALLED(GetBindInfo);
250     CHECK_CALLED(ReportProgress);
251     CHECK_CALLED(ReportData);
252     CHECK_CALLED(ReportResult);
253 }
254 
255 static void test_res_url(const char *url_suffix)
256 {
257     WCHAR url[INTERNET_MAX_URL_LENGTH];
258     IInternetProtocol *protocol;
259     ULONG size, ref;
260     BYTE buf[100];
261     HRESULT hres;
262 
263     memcpy(url, res_url_base, res_url_base_len*sizeof(WCHAR));
264     MultiByteToWideChar(CP_ACP, 0, url_suffix, -1, url+res_url_base_len, sizeof(url)/sizeof(WCHAR)-res_url_base_len);
265 
266     hres = CoCreateInstance(&CLSID_ResProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocol, (void**)&protocol);
267     ok(hres == S_OK, "Could not create ResProtocol instance: %08x\n", hres);
268 
269     protocol_start(protocol, url);
270 
271     hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &size);
272     ok(hres == S_OK, "Read failed: %08x\n", hres);
273 
274     hres = IInternetProtocol_Terminate(protocol, 0);
275     ok(hres == S_OK, "Terminate failed: %08x\n", hres);
276 
277 
278     ref = IInternetProtocol_Release(protocol);
279     ok(!ref, "ref=%u\n", ref);
280 }
281 
282 static void res_sec_url_cmp(LPCWSTR url, DWORD size, LPCWSTR file)
283 {
284     WCHAR buf[MAX_PATH];
285     DWORD len;
286 
287     static const WCHAR fileW[] = {'f','i','l','e',':','/','/'};
288 
289     if(size < sizeof(fileW)/sizeof(WCHAR) || memcmp(url, fileW, sizeof(fileW))) {
290         ok(0, "wrong URL protocol\n");
291         return;
292     }
293 
294     SetLastError(0xdeadbeef);
295     len = SearchPathW(NULL, file, NULL, sizeof(buf)/sizeof(WCHAR), buf, NULL);
296     if(!len) {
297         if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
298             win_skip("SearchPathW is not implemented\n");
299         else
300             ok(0, "SearchPath failed: %u\n", GetLastError());
301         return;
302     }
303 
304     len += sizeof(fileW)/sizeof(WCHAR)+1;
305     ok(len == size, "wrong size %u, expected %u\n", size, len);
306     ok(!lstrcmpW(url + sizeof(fileW)/sizeof(WCHAR), buf), "wrong file part %s\n", wine_dbgstr_w(url));
307 }
308 
309 static void test_res_protocol(void)
310 {
311     IInternetProtocolInfo *protocol_info;
312     IUnknown *unk;
313     IClassFactory *factory;
314     HRESULT hres;
315 
316     static const WCHAR blank_url[] =
317         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
318     static const WCHAR test_part_url[] = {'r','e','s',':','/','/','C','S','S','/','t','e','s','t',0};
319     static const WCHAR wrong_url1[] =
320         {'m','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','m','t','h',0};
321     static const WCHAR wrong_url2[] =
322         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l',0};
323     static const WCHAR wrong_url3[] =
324         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l','/','x','x','.','h','t','m',0};
325     static const WCHAR wrong_url4[] =
326         {'r','e','s',':','/','/','x','x','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
327     static const WCHAR wrong_url5[] =
328         {'r','e','s',':','/','/','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
329     static const WCHAR wrong_url6[] =
330         {'r','e','s',':','/','/','c',':','\\','d','i','r','\\','f','i','l','e','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
331     static const WCHAR mshtml_dllW[] = {'m','s','h','t','m','l','.','d','l','l',0};
332 
333     hres = CoGetClassObject(&CLSID_ResProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
334     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
335     if(FAILED(hres))
336         return;
337 
338     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
339     ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08x\n", hres);
340     if(SUCCEEDED(hres)) {
341         WCHAR buf[128];
342         DWORD size, expected_size;
343         int i;
344 
345         for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
346             if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
347                 hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, i, 0, buf,
348                         sizeof(buf)/sizeof(buf[0]), &size, 0);
349                 ok(hres == INET_E_DEFAULT_ACTION,
350                         "[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
351             }
352         }
353 
354         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
355                 sizeof(buf)/sizeof(buf[0]), &size, 0);
356         ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
357         res_sec_url_cmp(buf, size, mshtml_dllW);
358         ok(size == lstrlenW(buf)+1, "size = %d\n", size);
359         expected_size = size;
360 
361         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
362                 expected_size, &size, 0);
363         ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
364         res_sec_url_cmp(buf, size, mshtml_dllW);
365         ok(size == expected_size, "size = %d\n", size);
366 
367         size = 0;
368         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
369                 3, &size, 0);
370         ok(hres == S_FALSE, "ParseUrl failed: %08x, expected S_FALSE\n", hres);
371         ok(size == expected_size, "size = %d\n", size);
372 
373         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_SECURITY_URL, 0, buf,
374                 sizeof(buf)/sizeof(buf[0]), &size, 0);
375         ok(hres == MK_E_SYNTAX || hres == E_INVALIDARG,
376            "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres);
377 
378         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url5, PARSE_SECURITY_URL, 0, buf,
379                 sizeof(buf)/sizeof(buf[0]), &size, 0);
380         ok(hres == MK_E_SYNTAX, "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres);
381 
382         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url6, PARSE_SECURITY_URL, 0, buf,
383                 sizeof(buf)/sizeof(buf[0]), &size, 0);
384         ok(hres == MK_E_SYNTAX, "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres);
385 
386         size = 0xdeadbeef;
387         buf[0] = '?';
388         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
389                 sizeof(buf)/sizeof(buf[0]), &size, 0);
390         ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
391         ok(buf[0] == '?', "buf changed\n");
392         ok(size == sizeof(blank_url)/sizeof(WCHAR) ||
393            size == sizeof(buf)/sizeof(buf[0]), /* IE8 */
394            "size=%d\n", size);
395 
396         size = 0xdeadbeef;
397         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_DOMAIN, 0, buf,
398                 sizeof(buf)/sizeof(buf[0]), &size, 0);
399         ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
400         ok(buf[0] == '?', "buf changed\n");
401         ok(size == sizeof(wrong_url1)/sizeof(WCHAR) ||
402            size == sizeof(buf)/sizeof(buf[0]), /* IE8 */
403            "size=%d\n", size);
404 
405         if (0)
406         {
407         /* Crashes on windows */
408         size = 0xdeadbeef;
409         buf[0] = '?';
410         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
411                 sizeof(buf)/sizeof(buf[0]), &size, 0);
412         ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
413         ok(buf[0] == '?', "buf changed\n");
414         ok(size == 1, "size=%u, expected 1\n", size);
415 
416         buf[0] = '?';
417         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
418                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
419         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
420         ok(buf[0] == '?', "buf changed\n");
421 
422         buf[0] = '?';
423         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
424                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
425         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
426         ok(buf[0] == '?', "buf changed\n");
427         }
428 
429         buf[0] = '?';
430         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_UNESCAPE+1, 0, buf,
431                 sizeof(buf)/sizeof(buf[0]), &size, 0);
432         ok(hres == INET_E_DEFAULT_ACTION,
433                 "ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
434         ok(buf[0] == '?', "buf changed\n");
435 
436         size = 0xdeadbeef;
437         hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_part_url,
438                 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
439         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
440         ok(size == 0xdeadbeef, "size=%d\n", size);
441 
442         size = 0xdeadbeef;
443         hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_part_url,
444                 URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
445         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
446         ok(size == 0xdeadbeef, "size=%d\n", size);
447 
448         size = 0xdeadbeef;
449         hres = IInternetProtocolInfo_CombineUrl(protocol_info, NULL, NULL,
450                 URL_FILE_USE_PATHURL, NULL, 0xdeadbeef, NULL, 0);
451         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
452         ok(size == 0xdeadbeef, "size=%d\n", size);
453 
454         hres = IInternetProtocolInfo_CompareUrl(protocol_info, blank_url, blank_url, 0);
455         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
456 
457         hres = IInternetProtocolInfo_CompareUrl(protocol_info, NULL, NULL, 0xdeadbeef);
458         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
459 
460         for(i=0; i<30; i++) {
461             if(i == QUERY_USES_NETWORK || i == QUERY_IS_SECURE || i == QUERY_IS_SAFE)
462                 continue;
463 
464             hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, i, 0,
465                                                    buf, sizeof(buf), &size, 0);
466             ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
467                "QueryInfo(%d) returned: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", i, hres);
468         }
469 
470         size = 0xdeadbeef;
471         memset(buf, '?', sizeof(buf));
472         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
473                                                buf, sizeof(buf), &size, 0);
474         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
475         ok(size == sizeof(DWORD), "size=%d\n", size);
476         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
477 
478         memset(buf, '?', sizeof(buf));
479         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
480                                                buf, sizeof(buf), NULL, 0);
481         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
482         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
483 
484         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
485                                                buf, 3, &size, 0);
486         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
487 
488         size = 0xdeadbeef;
489         memset(buf, '?', sizeof(buf));
490         hres = IInternetProtocolInfo_QueryInfo(protocol_info, NULL, QUERY_USES_NETWORK, 0,
491                                                buf, sizeof(buf), &size, 0);
492         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
493         ok(size == sizeof(DWORD), "size=%d\n", size);
494         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
495 
496         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
497                                                NULL, sizeof(buf), &size, 0);
498         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
499 
500         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, 60, 0,
501                                                NULL, sizeof(buf), &size, 0);
502         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
503            "QueryInfo failed: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", hres);
504 
505         IInternetProtocolInfo_Release(protocol_info);
506     }
507 
508     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
509     ok(hres == S_OK, "Could not get IClassFactory interface\n");
510     if(SUCCEEDED(hres)) {
511         IInternetProtocol *protocol;
512         BYTE buf[512];
513         ULONG cb;
514         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
515         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
516 
517         if(SUCCEEDED(hres)) {
518             IInternetPriority *priority;
519 
520             hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
521             ok(hres == E_NOINTERFACE,
522                "QueryInterface(IInternetPriority) returned %08x, expected E_NOINTEFACE\n", hres);
523 
524             test_protocol_fail(protocol, wrong_url1, E_INVALIDARG, FALSE);
525             test_protocol_fail(protocol, wrong_url2,
526                                HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND), FALSE);
527             test_protocol_fail(protocol, wrong_url3, E_FAIL, TRUE);
528             test_protocol_fail(protocol, wrong_url4, E_FAIL, TRUE);
529 
530             cb = 0xdeadbeef;
531             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
532             ok(hres == E_FAIL, "Read returned %08x expected E_FAIL\n", hres);
533             ok(cb == 0xdeadbeef, "cb=%u expected 0xdeadbeef\n", cb);
534 
535             protocol_start(protocol, blank_url);
536             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
537             ok(hres == S_OK, "Read failed: %08x\n", hres);
538             ok(cb == 2, "cb=%u expected 2\n", cb);
539             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
540             ok(hres == S_OK, "Read failed: %08x\n", hres);
541             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
542             ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
543             ok(cb == 0, "cb=%u expected 0\n", cb);
544             hres = IInternetProtocol_UnlockRequest(protocol);
545             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
546 
547             protocol_start(protocol, blank_url);
548             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
549             ok(hres == S_OK, "Read failed: %08x\n", hres);
550             hres = IInternetProtocol_LockRequest(protocol, 0);
551             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
552             hres = IInternetProtocol_UnlockRequest(protocol);
553             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
554             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
555             ok(hres == S_OK, "Read failed: %08x\n", hres);
556 
557             protocol_start(protocol, blank_url);
558             hres = IInternetProtocol_LockRequest(protocol, 0);
559             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
560             hres = IInternetProtocol_Terminate(protocol, 0);
561             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
562             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
563             ok(hres == S_OK, "Read failed: %08x\n\n", hres);
564             hres = IInternetProtocol_UnlockRequest(protocol);
565             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
566             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
567             ok(hres == S_OK, "Read failed: %08x\n", hres);
568             hres = IInternetProtocol_Terminate(protocol, 0);
569             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
570             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
571             ok(hres == S_OK, "Read failed: %08x\n", hres);
572             ok(cb == 2, "cb=%u expected 2\n", cb);
573 
574             protocol_start(protocol, blank_url);
575             hres = IInternetProtocol_LockRequest(protocol, 0);
576             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
577             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
578             ok(hres == S_OK, "Read failed: %08x\n", hres);
579             protocol_start(protocol, blank_url);
580             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
581             ok(hres == S_OK, "Read failed: %08x\n", hres);
582             hres = IInternetProtocol_Terminate(protocol, 0);
583             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
584 
585             IInternetProtocol_Release(protocol);
586         }
587 
588         IClassFactory_Release(factory);
589     }
590 
591     IUnknown_Release(unk);
592 
593     test_res_url("/jstest.html");
594     test_res_url("/Test/res.html");
595     test_res_url("/test/dir/dir2/res.html");
596 
597     if(GetProcAddress(LoadLibraryA("urlmon.dll"), "CreateUri")) {
598         test_res_url("/test/dir/dir2/res.html?query_part");
599         test_res_url("/test/dir/dir2/res.html#hash_part");
600         test_res_url("/#123");
601         test_res_url("/#23/#123");
602         test_res_url("/#123#456");
603     }else {
604         win_skip("IUri not supported\n");
605     }
606 }
607 
608 static void do_test_about_protocol(IClassFactory *factory, DWORD bf)
609 {
610     IInternetProtocol *protocol;
611     IInternetPriority *priority;
612     BYTE buf[512];
613     ULONG cb;
614     HRESULT hres;
615 
616     static const WCHAR blank_html[] = {0xfeff,'<','H','T','M','L','>','<','/','H','T','M','L','>',0};
617     static const WCHAR test_html[] =
618         {0xfeff,'<','H','T','M','L','>','t','e','s','t','<','/','H','T','M','L','>',0};
619 
620     bindf = bf;
621 
622     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
623     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
624     if(FAILED(hres))
625         return;
626 
627     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
628     ok(hres == E_NOINTERFACE,
629        "QueryInterface(IInternetPriority) returned %08x, expected E_NOINTEFACE\n", hres);
630 
631     protocol_start(protocol, about_blank_url);
632     hres = IInternetProtocol_LockRequest(protocol, 0);
633     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
634     hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
635     ok(hres == S_OK, "Read failed: %08x\n", hres);
636     ok(cb == sizeof(blank_html), "cb=%d\n", cb);
637     ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n");
638     hres = IInternetProtocol_UnlockRequest(protocol);
639     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
640 
641     protocol_start(protocol, about_test_url);
642     hres = IInternetProtocol_LockRequest(protocol, 0);
643     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
644     hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
645     ok(hres == S_OK, "Read failed: %08x\n", hres);
646     ok(cb == sizeof(test_html), "cb=%d\n", cb);
647     ok(!memcmp(buf, test_html, cb), "Readed wrong data\n");
648     hres = IInternetProtocol_UnlockRequest(protocol);
649     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
650 
651     protocol_start(protocol, about_res_url);
652     hres = IInternetProtocol_LockRequest(protocol, 0);
653     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
654     hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
655     ok(hres == S_OK, "Read failed: %08x\n", hres);
656     ok(cb == sizeof(blank_html), "cb=%d\n", cb);
657     ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n");
658     hres = IInternetProtocol_UnlockRequest(protocol);
659     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
660 
661     IInternetProtocol_Release(protocol);
662 }
663 
664 static void test_about_protocol(void)
665 {
666     IInternetProtocolInfo *protocol_info;
667     IUnknown *unk;
668     IClassFactory *factory;
669     HRESULT hres;
670 
671     hres = CoGetClassObject(&CLSID_AboutProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
672     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
673     if(FAILED(hres))
674         return;
675 
676     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
677     ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08x\n", hres);
678     if(SUCCEEDED(hres)) {
679         WCHAR buf[128];
680         DWORD size;
681         int i;
682 
683         for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
684             if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
685                 hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, i, 0, buf,
686                         sizeof(buf)/sizeof(buf[0]), &size, 0);
687                 ok(hres == INET_E_DEFAULT_ACTION,
688                         "[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
689             }
690         }
691 
692         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf,
693                 sizeof(buf)/sizeof(buf[0]), &size, 0);
694         ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
695         ok(!lstrcmpW(about_blank_url, buf), "buf != blank_url\n");
696 
697         size = 0xdeadbeef;
698         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf,
699                 3, &size, 0);
700         ok(hres == S_FALSE, "ParseUrl failed: %08x, expected S_FALSE\n", hres);
701         ok(size == 12, "size = %d\n", size);
702 
703         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_test_url, PARSE_SECURITY_URL, 0, buf,
704                 sizeof(buf)/sizeof(buf[0]), &size, 0);
705         ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
706         ok(!lstrcmpW(about_test_url, buf), "buf != test_url\n");
707         ok(size == 11, "size = %d\n", size);
708 
709         size = 0xdeadbeef;
710         buf[0] = '?';
711         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf,
712                 sizeof(buf)/sizeof(buf[0]), &size, 0);
713         ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
714         ok(buf[0] == '?', "buf changed\n");
715         ok(size == sizeof(about_blank_url)/sizeof(WCHAR) ||
716            size == sizeof(buf)/sizeof(buf[0]), /* IE8 */
717            "size=%d\n", size);
718 
719         if (0)
720         {
721         /* Crashes on windows */
722         size = 0xdeadbeef;
723         buf[0] = '?';
724         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
725                 sizeof(buf)/sizeof(buf[0]), &size, 0);
726         ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
727         ok(buf[0] == '?', "buf changed\n");
728         ok(size == 1, "size=%u, expected 1\n", size);
729 
730         buf[0] = '?';
731         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf,
732                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
733         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
734         ok(buf[0] == '?', "buf changed\n");
735 
736         buf[0] = '?';
737         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
738                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
739         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
740         ok(buf[0] == '?', "buf changed\n");
741         }
742 
743         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_UNESCAPE+1, 0, buf,
744                 sizeof(buf)/sizeof(buf[0]), &size, 0);
745         ok(hres == INET_E_DEFAULT_ACTION,
746                 "ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
747 
748         size = 0xdeadbeef;
749         hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url,
750                 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
751         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
752         ok(size == 0xdeadbeef, "size=%d\n", size);
753 
754         size = 0xdeadbeef;
755         hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url,
756                 URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
757         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
758         ok(size == 0xdeadbeef, "size=%d\n", size);
759 
760         size = 0xdeadbeef;
761         hres = IInternetProtocolInfo_CombineUrl(protocol_info, NULL, NULL,
762                 URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
763         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
764         ok(size == 0xdeadbeef, "size=%d\n", size);
765 
766         hres = IInternetProtocolInfo_CompareUrl(protocol_info, about_blank_url, about_blank_url, 0);
767         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
768 
769         hres = IInternetProtocolInfo_CompareUrl(protocol_info, NULL, NULL, 0xdeadbeef);
770         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
771 
772         for(i=0; i<30; i++) {
773             switch(i) {
774             case QUERY_CAN_NAVIGATE:
775             case QUERY_USES_NETWORK:
776             case QUERY_IS_CACHED:
777             case QUERY_IS_INSTALLEDENTRY:
778             case QUERY_IS_CACHED_OR_MAPPED:
779             case QUERY_IS_SECURE:
780             case QUERY_IS_SAFE:
781             case QUERY_USES_HISTORYFOLDER:
782             case QUERY_IS_CACHED_AND_USABLE_OFFLINE:
783                 break;
784             default:
785                 hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, i, 0,
786                                                        buf, sizeof(buf), &size, 0);
787                 ok(hres == E_FAIL, "QueryInfo(%d) returned: %08x, expected E_FAIL\n", i, hres);
788             }
789         }
790 
791         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_CAN_NAVIGATE, 0,
792                                                buf, sizeof(buf), &size, 0);
793         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER ||
794            hres == E_FAIL, /* win2k */
795            "QueryInfo returned: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER or E_FAIL\n", hres);
796 
797         size = 0xdeadbeef;
798         memset(buf, '?', sizeof(buf));
799         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
800                                                buf, sizeof(buf), &size, 0);
801         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
802         ok(size == sizeof(DWORD), "size=%d\n", size);
803         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
804 
805         memset(buf, '?', sizeof(buf));
806         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
807                                                buf, sizeof(buf), NULL, 0);
808         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
809         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
810 
811         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
812                                                buf, 3, &size, 0);
813         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
814 
815         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
816                                                NULL, sizeof(buf), &size, 0);
817         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
818 
819         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, 60, 0,
820                                                NULL, sizeof(buf), &size, 0);
821         ok(hres == E_FAIL, "QueryInfo failed: %08x, expected E_FAIL\n", hres);
822 
823         IInternetProtocolInfo_Release(protocol_info);
824     }
825 
826     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
827     ok(hres == S_OK, "Could not get IClassFactory interface\n");
828     if(SUCCEEDED(hres)) {
829         do_test_about_protocol(factory, 0);
830         do_test_about_protocol(factory,
831                 BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE);
832 
833         IClassFactory_Release(factory);
834     }
835 
836     IUnknown_Release(unk);
837 }
838 
839 static void test_javascript_protocol(void)
840 {
841     IInternetProtocolInfo *protocol_info;
842     IUnknown *unk;
843     IClassFactory *factory;
844     HRESULT hres;
845 
846     hres = CoGetClassObject(&CLSID_JSProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
847     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
848     if(FAILED(hres))
849         return;
850 
851     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
852     ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08x\n", hres);
853     if(SUCCEEDED(hres)) {
854         WCHAR buf[128];
855         DWORD size;
856         int i;
857 
858         for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
859             if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
860                 hres = IInternetProtocolInfo_ParseUrl(protocol_info, javascript_test_url, i, 0, buf,
861                         sizeof(buf)/sizeof(buf[0]), &size, 0);
862                 ok(hres == INET_E_DEFAULT_ACTION,
863                         "[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
864             }
865         }
866 
867         hres = IInternetProtocolInfo_ParseUrl(protocol_info, javascript_test_url, PARSE_UNESCAPE+1, 0, buf,
868                 sizeof(buf)/sizeof(buf[0]), &size, 0);
869         ok(hres == INET_E_DEFAULT_ACTION,
870                 "ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
871 
872         size = 0xdeadbeef;
873         hres = IInternetProtocolInfo_CombineUrl(protocol_info, javascript_test_url, javascript_test_url,
874                 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
875         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
876         ok(size == 0xdeadbeef, "size=%d\n", size);
877 
878         hres = IInternetProtocolInfo_CompareUrl(protocol_info, javascript_test_url, javascript_test_url, 0);
879         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
880 
881         for(i=0; i<30; i++) {
882             switch(i) {
883             case QUERY_USES_NETWORK:
884             case QUERY_IS_SECURE:
885                 break;
886             default:
887                 hres = IInternetProtocolInfo_QueryInfo(protocol_info, javascript_test_url, i, 0,
888                                                        buf, sizeof(buf), &size, 0);
889                 ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
890                    "QueryInfo(%d) returned: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", i, hres);
891             }
892         }
893 
894 
895         memset(buf, '?', sizeof(buf));
896         hres = IInternetProtocolInfo_QueryInfo(protocol_info, javascript_test_url, QUERY_USES_NETWORK, 0,
897                                                buf, sizeof(buf), &size, 0);
898         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
899         ok(size == sizeof(DWORD), "size=%d\n", size);
900         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
901 
902         memset(buf, '?', sizeof(buf));
903         hres = IInternetProtocolInfo_QueryInfo(protocol_info, javascript_test_url, QUERY_USES_NETWORK, 0,
904                                                buf, sizeof(buf), NULL, 0);
905         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
906         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
907 
908         hres = IInternetProtocolInfo_QueryInfo(protocol_info, javascript_test_url, QUERY_USES_NETWORK, 0,
909                                                buf, 3, &size, 0);
910         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
911 
912         hres = IInternetProtocolInfo_QueryInfo(protocol_info, javascript_test_url, QUERY_USES_NETWORK, 0,
913                                                NULL, sizeof(buf), &size, 0);
914         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
915 
916         hres = IInternetProtocolInfo_QueryInfo(protocol_info, javascript_test_url, 60, 0,
917                                                NULL, sizeof(buf), &size, 0);
918         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
919            "QueryInfo failed: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", hres);
920 
921         /* FIXME: test QUERY_IS_SECURE */
922 
923         IInternetProtocolInfo_Release(protocol_info);
924     }
925 
926     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
927     ok(hres == S_OK, "Could not get IClassFactory interface\n");
928     if(SUCCEEDED(hres))
929         IClassFactory_Release(factory);
930 
931     IUnknown_Release(unk);
932 }
933 
934 START_TEST(protocol)
935 {
936     res_url_base_len = 6 + GetModuleFileNameW(NULL, res_url_base + 6 /* strlen("res://") */, sizeof(res_url_base)/sizeof(WCHAR)-6);
937 
938     OleInitialize(NULL);
939 
940     test_res_protocol();
941     test_about_protocol();
942     test_javascript_protocol();
943 
944     OleUninitialize();
945 }
946