urlmon: Don't create stgmed_obj for binding to object.
[wine] / dlls / mshtml / tests / protocol.c
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 #define COBJMACROS
20
21 #include <wine/test.h>
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "ole2.h"
27 #include "urlmon.h"
28 #include "shlwapi.h"
29
30 #include "initguid.h"
31
32 #define DEFINE_EXPECT(func) \
33     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34
35 #define SET_EXPECT(func) \
36     expect_ ## func = TRUE
37
38 #define CHECK_EXPECT(func) \
39     do { \
40         ok(expect_ ##func, "unexpected call " #func "\n"); \
41         expect_ ## func = FALSE; \
42         called_ ## func = TRUE; \
43     }while(0)
44
45 #define CHECK_EXPECT2(func) \
46     do { \
47         ok(expect_ ##func, "unexpected call " #func  "\n"); \
48         called_ ## func = TRUE; \
49     }while(0)
50
51 #define CHECK_CALLED(func) \
52     do { \
53         ok(called_ ## func, "expected " #func "\n"); \
54         expect_ ## func = called_ ## func = FALSE; \
55     }while(0)
56
57 DEFINE_GUID(CLSID_ResProtocol, 0x3050F3BC, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
58 DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
59
60 DEFINE_EXPECT(GetBindInfo);
61 DEFINE_EXPECT(ReportProgress);
62 DEFINE_EXPECT(ReportData);
63 DEFINE_EXPECT(ReportResult);
64
65 static HRESULT expect_hrResult;
66 static BOOL expect_hr_win32err = FALSE;
67 static DWORD bindf;
68
69 static const WCHAR about_blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
70 static const WCHAR about_test_url[] = {'a','b','o','u','t',':','t','e','s','t',0};
71 static const WCHAR about_res_url[] = {'r','e','s',':','b','l','a','n','k',0};
72
73 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
74 {
75     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
76         *ppv = iface;
77         return S_OK;
78     }
79     return E_NOINTERFACE;
80 }
81
82 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
83 {
84     return 2;
85 }
86
87 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
88 {
89     return 1;
90 }
91
92 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
93 {
94     ok(0, "unexpected call\n");
95     return E_NOTIMPL;
96 }
97
98 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
99         LPCWSTR szStatusText)
100 {
101     static const WCHAR text_html[] = {'t','e','x','t','/','h','t','m','l',0};
102
103     CHECK_EXPECT(ReportProgress);
104
105     ok(ulStatusCode == BINDSTATUS_MIMETYPEAVAILABLE
106             || ulStatusCode == BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
107             "ulStatusCode=%d\n", ulStatusCode);
108     ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
109
110     return S_OK;
111 }
112
113 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF, ULONG ulProgress,
114         ULONG ulProgressMax)
115 {
116     CHECK_EXPECT(ReportData);
117
118     ok(ulProgress == ulProgressMax, "ulProgress != ulProgressMax\n");
119     ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE),
120             "grcf = %08x\n", grfBSCF);
121
122     return S_OK;
123 }
124
125 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult, DWORD dwError,
126         LPCWSTR szResult)
127 {
128     CHECK_EXPECT(ReportResult);
129
130     if(expect_hr_win32err)
131         ok((hrResult&0xffff0000) == ((FACILITY_WIN32 << 16)|0x80000000) || expect_hrResult,
132                 "expected win32 err or %08x got: %08x\n", expect_hrResult, hrResult);
133     else
134         ok(hrResult == expect_hrResult || ((expect_hrResult == E_INVALIDARG ||
135            expect_hrResult == HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND)) &&
136            hrResult == MK_E_SYNTAX), "expected: %08x got: %08x\n", expect_hrResult, hrResult);
137     ok(dwError == 0, "dwError = %d\n", dwError);
138     ok(!szResult, "szResult != NULL\n");
139
140     return S_OK;
141 }
142
143 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
144     ProtocolSink_QueryInterface,
145     ProtocolSink_AddRef,
146     ProtocolSink_Release,
147     ProtocolSink_Switch,
148     ProtocolSink_ReportProgress,
149     ProtocolSink_ReportData,
150     ProtocolSink_ReportResult
151 };
152
153 static IInternetProtocolSink protocol_sink = {
154     &protocol_sink_vtbl
155 };
156
157 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
158 {
159     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
160         *ppv = iface;
161         return S_OK;
162     }
163     return E_NOINTERFACE;
164 }
165
166 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
167 {
168     return 2;
169 }
170
171 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
172 {
173     return 1;
174 }
175
176 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
177 {
178     CHECK_EXPECT(GetBindInfo);
179
180     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
181     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
182     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %d\n", pbindinfo->cbSize);
183
184     *grfBINDF = bindf;
185     return S_OK;
186 }
187
188 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType, LPOLESTR *ppwzStr,
189         ULONG cEl, ULONG *pcElFetched)
190 {
191     ok(0, "unexpected call\n");
192     return E_NOTIMPL;
193 }
194
195 static IInternetBindInfoVtbl bind_info_vtbl = {
196     BindInfo_QueryInterface,
197     BindInfo_AddRef,
198     BindInfo_Release,
199     BindInfo_GetBindInfo,
200     BindInfo_GetBindString
201 };
202
203 static IInternetBindInfo bind_info = {
204     &bind_info_vtbl
205 };
206
207 static void test_protocol_fail(IInternetProtocol *protocol, LPCWSTR url, HRESULT expected_hres,
208         BOOL expect_win32err)
209 {
210     HRESULT hres;
211
212     SET_EXPECT(GetBindInfo);
213     SET_EXPECT(ReportResult);
214
215     expect_hrResult = expected_hres;
216     expect_hr_win32err = expect_win32err;
217     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
218     if(expect_win32err)
219         ok((hres&0xffff0000) == ((FACILITY_WIN32 << 16)|0x80000000) || hres == expect_hrResult,
220                 "expected win32 err or %08x got: %08x\n", expected_hres, hres);
221     else
222         ok(hres == expected_hres || ((expected_hres == E_INVALIDARG ||
223            expected_hres == HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND)) && hres == MK_E_SYNTAX),
224            "expected: %08x got: %08x\n", expected_hres, hres);
225
226     CHECK_CALLED(GetBindInfo);
227     CHECK_CALLED(ReportResult);
228 }
229
230 static void protocol_start(IInternetProtocol *protocol, LPCWSTR url)
231 {
232     HRESULT hres;
233
234     SET_EXPECT(GetBindInfo);
235     SET_EXPECT(ReportResult);
236     SET_EXPECT(ReportProgress);
237     SET_EXPECT(ReportData);
238     expect_hrResult = S_OK;
239     expect_hr_win32err = FALSE;
240
241     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
242     ok(hres == S_OK, "Start failed: %08x\n", hres);
243
244     CHECK_CALLED(GetBindInfo);
245     CHECK_CALLED(ReportProgress);
246     CHECK_CALLED(ReportData);
247     CHECK_CALLED(ReportResult);
248 }
249
250 static void test_res_protocol(void)
251 {
252     IInternetProtocolInfo *protocol_info;
253     IUnknown *unk;
254     IClassFactory *factory;
255     HRESULT hres;
256
257     static const WCHAR blank_url[] =
258         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
259     static const WCHAR test_part_url[] = {'r','e','s',':','/','/','C','S','S','/','t','e','s','t',0};
260     static const WCHAR wrong_url1[] =
261         {'m','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','m','t','h',0};
262     static const WCHAR wrong_url2[] =
263         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l',0};
264     static const WCHAR wrong_url3[] =
265         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l','/','x','x','.','h','t','m',0};
266     static const WCHAR wrong_url4[] =
267         {'r','e','s',':','/','/','x','x','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
268
269
270     hres = CoGetClassObject(&CLSID_ResProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
271     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
272     if(!SUCCEEDED(hres))
273         return;
274
275     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
276     ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08x\n", hres);
277     if(SUCCEEDED(hres)) {
278         WCHAR buf[128];
279         DWORD size;
280         int i;
281
282         for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
283             if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
284                 hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, i, 0, buf,
285                         sizeof(buf)/sizeof(buf[0]), &size, 0);
286                 ok(hres == INET_E_DEFAULT_ACTION,
287                         "[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
288             }
289         }
290
291         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
292                 sizeof(buf)/sizeof(buf[0]), &size, 0);
293         ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
294
295         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
296                 3, &size, 0);
297         ok(hres == S_FALSE, "ParseUrl failed: %08x, expected S_FALSE\n", hres);
298
299         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_SECURITY_URL, 0, buf,
300                 sizeof(buf)/sizeof(buf[0]), &size, 0);
301         ok(hres == MK_E_SYNTAX || hres == E_INVALIDARG,
302            "ParseUrl failed: %08x, expected MK_E_SYNTAX\n", hres);
303
304         size = 0xdeadbeef;
305         buf[0] = '?';
306         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
307                 sizeof(buf)/sizeof(buf[0]), &size, 0);
308         ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
309         ok(buf[0] == '?', "buf changed\n");
310         ok(size == sizeof(blank_url)/sizeof(WCHAR), "size=%d\n", size);
311
312         size = 0xdeadbeef;
313         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_DOMAIN, 0, buf,
314                 sizeof(buf)/sizeof(buf[0]), &size, 0);
315         ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
316         ok(buf[0] == '?', "buf changed\n");
317         ok(size == sizeof(wrong_url1)/sizeof(WCHAR), "size=%d\n", size);
318
319         if (0)
320         {
321         /* Crashes on win9x */
322         size = 0xdeadbeef;
323         buf[0] = '?';
324         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
325                 sizeof(buf)/sizeof(buf[0]), &size, 0);
326         ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
327         ok(buf[0] == '?', "buf changed\n");
328         ok(size == 1, "size=%u, ezpected 1\n", size);
329
330         buf[0] = '?';
331         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
332                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
333         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
334         ok(buf[0] == '?', "buf changed\n");
335
336         buf[0] = '?';
337         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
338                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
339         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
340         ok(buf[0] == '?', "buf changed\n");
341         }
342
343         buf[0] = '?';
344         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_UNESCAPE+1, 0, buf,
345                 sizeof(buf)/sizeof(buf[0]), &size, 0);
346         ok(hres == INET_E_DEFAULT_ACTION,
347                 "ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
348         ok(buf[0] == '?', "buf changed\n");
349
350         size = 0xdeadbeef;
351         hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_part_url,
352                 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
353         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
354         ok(size == 0xdeadbeef, "size=%d\n", size);
355
356         size = 0xdeadbeef;
357         hres = IInternetProtocolInfo_CombineUrl(protocol_info, blank_url, test_part_url,
358                 URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
359         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
360         ok(size == 0xdeadbeef, "size=%d\n", size);
361
362         size = 0xdeadbeef;
363         hres = IInternetProtocolInfo_CombineUrl(protocol_info, NULL, NULL,
364                 URL_FILE_USE_PATHURL, NULL, 0xdeadbeef, NULL, 0);
365         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
366         ok(size == 0xdeadbeef, "size=%d\n", size);
367
368         hres = IInternetProtocolInfo_CompareUrl(protocol_info, blank_url, blank_url, 0);
369         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
370
371         hres = IInternetProtocolInfo_CompareUrl(protocol_info, NULL, NULL, 0xdeadbeef);
372         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
373
374         for(i=0; i<30; i++) {
375             if(i == QUERY_USES_NETWORK || i == QUERY_IS_SECURE || i == QUERY_IS_SAFE)
376                 continue;
377
378             hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, i, 0,
379                                                    buf, sizeof(buf), &size, 0);
380             ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
381                "QueryInfo(%d) returned: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", i, hres);
382         }
383
384         size = 0xdeadbeef;
385         memset(buf, '?', sizeof(buf));
386         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
387                                                buf, sizeof(buf), &size, 0);
388         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
389         ok(size == sizeof(DWORD), "size=%d\n", size);
390         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
391
392         memset(buf, '?', sizeof(buf));
393         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
394                                                buf, sizeof(buf), NULL, 0);
395         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
396         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
397
398         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
399                                                buf, 3, &size, 0);
400         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
401
402         size = 0xdeadbeef;
403         memset(buf, '?', sizeof(buf));
404         hres = IInternetProtocolInfo_QueryInfo(protocol_info, NULL, QUERY_USES_NETWORK, 0,
405                                                buf, sizeof(buf), &size, 0);
406         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
407         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
408         ok(size == sizeof(DWORD), "size=%d\n", size);
409         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
410
411         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, QUERY_USES_NETWORK, 0,
412                                                NULL, sizeof(buf), &size, 0);
413         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
414
415         hres = IInternetProtocolInfo_QueryInfo(protocol_info, blank_url, 60, 0,
416                                                NULL, sizeof(buf), &size, 0);
417         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
418            "QueryInfo failed: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", hres);
419
420         IInternetProtocolInfo_Release(protocol_info);
421     }
422
423     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
424     ok(hres == S_OK, "Could not get IClassFactory interface\n");
425     if(SUCCEEDED(hres)) {
426         IInternetProtocol *protocol;
427         BYTE buf[512];
428         ULONG cb;
429         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
430         ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
431
432         if(SUCCEEDED(hres)) {
433             IInternetPriority *priority;
434
435             hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
436             ok(hres == E_NOINTERFACE,
437                "QueryInterface(IInternetPriority) returned %08x, expected E_NOINTEFACE\n", hres);
438
439             test_protocol_fail(protocol, wrong_url1, E_INVALIDARG, FALSE);
440             test_protocol_fail(protocol, wrong_url2,
441                                HRESULT_FROM_WIN32(ERROR_RESOURCE_TYPE_NOT_FOUND), FALSE);
442             test_protocol_fail(protocol, wrong_url3, E_FAIL, TRUE);
443             test_protocol_fail(protocol, wrong_url4, E_FAIL, TRUE);
444
445             cb = 0xdeadbeef;
446             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
447             ok(hres == E_FAIL, "Read returned %08x expected E_FAIL\n", hres);
448             ok(cb == 0xdeadbeef, "cb=%u expected 0xdeadbeef\n", cb);
449     
450             protocol_start(protocol, blank_url);
451             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
452             ok(hres == S_OK, "Read failed: %08x\n", hres);
453             ok(cb == 2, "cb=%u expected 2\n", cb);
454             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
455             ok(hres == S_OK, "Read failed: %08x\n", hres);
456             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
457             ok(hres == S_FALSE, "Read failed: %08x expected S_FALSE\n", hres);
458             ok(cb == 0, "cb=%u expected 0\n", cb);
459             hres = IInternetProtocol_UnlockRequest(protocol);
460             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
461
462             protocol_start(protocol, blank_url);
463             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
464             ok(hres == S_OK, "Read failed: %08x\n", hres);
465             hres = IInternetProtocol_LockRequest(protocol, 0);
466             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
467             hres = IInternetProtocol_UnlockRequest(protocol);
468             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
469             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
470             ok(hres == S_OK, "Read failed: %08x\n", hres);
471
472             protocol_start(protocol, blank_url);
473             hres = IInternetProtocol_LockRequest(protocol, 0);
474             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
475             hres = IInternetProtocol_Terminate(protocol, 0);
476             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
477             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
478             ok(hres == S_OK, "Read failed: %08x\n\n", hres);
479             hres = IInternetProtocol_UnlockRequest(protocol);
480             ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
481             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
482             ok(hres == S_OK, "Read failed: %08x\n", hres);
483             hres = IInternetProtocol_Terminate(protocol, 0);
484             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
485             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
486             ok(hres == S_OK, "Read failed: %08x\n", hres);
487             ok(cb == 2, "cb=%u expected 2\n", cb);
488
489             protocol_start(protocol, blank_url);
490             hres = IInternetProtocol_LockRequest(protocol, 0);
491             ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
492             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
493             ok(hres == S_OK, "Read failed: %08x\n", hres);
494             protocol_start(protocol, blank_url);
495             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
496             ok(hres == S_OK, "Read failed: %08x\n", hres);
497             hres = IInternetProtocol_Terminate(protocol, 0);
498             ok(hres == S_OK, "Terminate failed: %08x\n", hres);
499
500             IInternetProtocol_Release(protocol);
501         }
502
503         IClassFactory_Release(factory);
504     }
505
506     IUnknown_Release(unk);
507 }
508
509 static void do_test_about_protocol(IClassFactory *factory, DWORD bf)
510 {
511     IInternetProtocol *protocol;
512     IInternetPriority *priority;
513     BYTE buf[512];
514     ULONG cb;
515     HRESULT hres;
516
517     static const WCHAR blank_html[] = {0xfeff,'<','H','T','M','L','>','<','/','H','T','M','L','>',0};
518     static const WCHAR test_html[] =
519         {0xfeff,'<','H','T','M','L','>','t','e','s','t','<','/','H','T','M','L','>',0};
520
521     bindf = bf;
522
523     hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
524     ok(hres == S_OK, "Could not get IInternetProtocol: %08x\n", hres);
525     if(FAILED(hres))
526         return;
527
528     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
529     ok(hres == E_NOINTERFACE,
530        "QueryInterface(IInternetPriority) returned %08x, expected E_NOINTEFACE\n", hres);
531
532     protocol_start(protocol, about_blank_url);
533     hres = IInternetProtocol_LockRequest(protocol, 0);
534     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
535     hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
536     ok(hres == S_OK, "Read failed: %08x\n", hres);
537     ok(cb == sizeof(blank_html), "cb=%d\n", cb);
538     ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n");
539     hres = IInternetProtocol_UnlockRequest(protocol);
540     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
541
542     protocol_start(protocol, about_test_url);
543     hres = IInternetProtocol_LockRequest(protocol, 0);
544     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
545     hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
546     ok(hres == S_OK, "Read failed: %08x\n", hres);
547     ok(cb == sizeof(test_html), "cb=%d\n", cb);
548     ok(!memcmp(buf, test_html, cb), "Readed wrong data\n");
549     hres = IInternetProtocol_UnlockRequest(protocol);
550     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
551
552     protocol_start(protocol, about_res_url);
553     hres = IInternetProtocol_LockRequest(protocol, 0);
554     ok(hres == S_OK, "LockRequest failed: %08x\n", hres);
555     hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
556     ok(hres == S_OK, "Read failed: %08x\n", hres);
557     ok(cb == sizeof(blank_html), "cb=%d\n", cb);
558     ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n");
559     hres = IInternetProtocol_UnlockRequest(protocol);
560     ok(hres == S_OK, "UnlockRequest failed: %08x\n", hres);
561
562     IInternetProtocol_Release(protocol);
563 }
564
565 static void test_about_protocol(void)
566 {
567     IInternetProtocolInfo *protocol_info;
568     IUnknown *unk;
569     IClassFactory *factory;
570     HRESULT hres;
571
572     hres = CoGetClassObject(&CLSID_AboutProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
573     ok(hres == S_OK, "CoGetClassObject failed: %08x\n", hres);
574     if(!SUCCEEDED(hres))
575         return;
576
577     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
578     ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08x\n", hres);
579     if(SUCCEEDED(hres)) {
580         WCHAR buf[128];
581         DWORD size;
582         int i;
583
584         for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
585             if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
586                 hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, i, 0, buf,
587                         sizeof(buf)/sizeof(buf[0]), &size, 0);
588                 ok(hres == INET_E_DEFAULT_ACTION,
589                         "[%d] failed: %08x, expected INET_E_DEFAULT_ACTION\n", i, hres);
590             }
591         }
592
593         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf,
594                 sizeof(buf)/sizeof(buf[0]), &size, 0);
595         ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
596         ok(!lstrcmpW(about_blank_url, buf), "buf != blank_url\n");
597
598         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_SECURITY_URL, 0, buf,
599                 3, &size, 0);
600         ok(hres == S_FALSE, "ParseUrl failed: %08x, expected S_FALSE\n", hres);
601
602         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_test_url, PARSE_SECURITY_URL, 0, buf,
603                 sizeof(buf)/sizeof(buf[0]), &size, 0);
604         ok(hres == S_OK, "ParseUrl failed: %08x\n", hres);
605         ok(!lstrcmpW(about_test_url, buf), "buf != test_url\n");
606
607         size = 0xdeadbeef;
608         buf[0] = '?';
609         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf,
610                 sizeof(buf)/sizeof(buf[0]), &size, 0);
611         ok(hres == S_OK || hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
612         ok(buf[0] == '?', "buf changed\n");
613         ok(size == sizeof(about_blank_url)/sizeof(WCHAR), "size=%d\n", size);
614
615         if (0)
616         {
617         /* Crashes on win9x */
618         size = 0xdeadbeef;
619         buf[0] = '?';
620         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
621                 sizeof(buf)/sizeof(buf[0]), &size, 0);
622         ok(hres == E_FAIL, "ParseUrl failed: %08x\n", hres);
623         ok(buf[0] == '?', "buf changed\n");
624         ok(size == 1, "size=%u, ezpected 1\n", size);
625
626         buf[0] = '?';
627         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_DOMAIN, 0, buf,
628                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
629         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
630         ok(buf[0] == '?', "buf changed\n");
631
632         buf[0] = '?';
633         hres = IInternetProtocolInfo_ParseUrl(protocol_info, NULL, PARSE_DOMAIN, 0, buf,
634                 sizeof(buf)/sizeof(buf[0]), NULL, 0);
635         ok(hres == E_POINTER, "ParseUrl failed: %08x\n", hres);
636         ok(buf[0] == '?', "buf changed\n");
637         }
638
639         hres = IInternetProtocolInfo_ParseUrl(protocol_info, about_blank_url, PARSE_UNESCAPE+1, 0, buf,
640                 sizeof(buf)/sizeof(buf[0]), &size, 0);
641         ok(hres == INET_E_DEFAULT_ACTION,
642                 "ParseUrl failed: %08x, expected INET_E_DEFAULT_ACTION\n", hres);
643
644         size = 0xdeadbeef;
645         hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url,
646                 0, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
647         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
648         ok(size == 0xdeadbeef, "size=%d\n", size);
649
650         size = 0xdeadbeef;
651         hres = IInternetProtocolInfo_CombineUrl(protocol_info, about_blank_url, about_test_url,
652                 URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
653         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
654         ok(size == 0xdeadbeef, "size=%d\n", size);
655
656         size = 0xdeadbeef;
657         hres = IInternetProtocolInfo_CombineUrl(protocol_info, NULL, NULL,
658                 URL_FILE_USE_PATHURL, buf, sizeof(buf)/sizeof(buf[0]), &size, 0);
659         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER, "CombineUrl failed: %08x\n", hres);
660         ok(size == 0xdeadbeef, "size=%d\n", size);
661
662         hres = IInternetProtocolInfo_CompareUrl(protocol_info, about_blank_url, about_blank_url, 0);
663         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
664
665         hres = IInternetProtocolInfo_CompareUrl(protocol_info, NULL, NULL, 0xdeadbeef);
666         ok(hres == E_NOTIMPL, "CompareUrl failed: %08x\n", hres);
667
668         for(i=0; i<30; i++) {
669             switch(i) {
670             case QUERY_CAN_NAVIGATE:
671             case QUERY_USES_NETWORK:
672             case QUERY_IS_CACHED:
673             case QUERY_IS_INSTALLEDENTRY:
674             case QUERY_IS_CACHED_OR_MAPPED:
675             case QUERY_IS_SECURE:
676             case QUERY_IS_SAFE:
677                 break;
678             default:
679                 hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, i, 0,
680                                                        buf, sizeof(buf), &size, 0);
681                 ok(hres == E_FAIL, "QueryInfo(%d) returned: %08x, expected E_FAIL\n", i, hres);
682             }
683         }
684
685         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_CAN_NAVIGATE, 0,
686                                                buf, sizeof(buf), &size, 0);
687         ok(hres == INET_E_USE_DEFAULT_PROTOCOLHANDLER,
688            "QueryInfo returned: %08x, expected INET_E_USE_DEFAULT_PROTOCOLHANDLER\n", hres);
689
690         size = 0xdeadbeef;
691         memset(buf, '?', sizeof(buf));
692         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
693                                                buf, sizeof(buf), &size, 0);
694         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
695         ok(size == sizeof(DWORD), "size=%d\n", size);
696         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
697
698         memset(buf, '?', sizeof(buf));
699         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
700                                                buf, sizeof(buf), NULL, 0);
701         ok(hres == S_OK, "QueryInfo(QUERY_USES_NETWORK) failed: %08x\n", hres);
702         ok(!*(DWORD*)buf, "buf=%d\n", *(DWORD*)buf);
703
704         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
705                                                buf, 3, &size, 0);
706         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
707
708         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, QUERY_USES_NETWORK, 0,
709                                                NULL, sizeof(buf), &size, 0);
710         ok(hres == E_FAIL, "QueryInfo(QUERY_USES_NETWORK) failed: %08x, expected E_FAIL\n", hres);
711
712         hres = IInternetProtocolInfo_QueryInfo(protocol_info, about_blank_url, 60, 0,
713                                                NULL, sizeof(buf), &size, 0);
714         ok(hres == E_FAIL, "QueryInfo failed: %08x, expected E_FAIL\n", hres);
715
716         IInternetProtocolInfo_Release(protocol_info);
717     }
718
719     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
720     ok(hres == S_OK, "Could not get IClassFactory interface\n");
721     if(SUCCEEDED(hres)) {
722         do_test_about_protocol(factory, 0);
723         do_test_about_protocol(factory,
724                 BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_FROMURLMON | BINDF_NEEDFILE);
725
726         IClassFactory_Release(factory);
727     }
728
729     IUnknown_Release(unk);
730 }
731
732 START_TEST(protocol)
733 {
734     OleInitialize(NULL);
735
736     test_res_protocol();
737     test_about_protocol();
738
739     OleUninitialize();
740 }