comctl32: A couple fixes for tab icon offsets.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
29 #include "initguid.h"
30
31 #define DEFINE_EXPECT(func) \
32     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
33
34 #define SET_EXPECT(func) \
35     expect_ ## func = TRUE
36
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)
43
44 #define CHECK_EXPECT2(func) \
45     do { \
46         ok(expect_ ##func, "unexpected call " #func  "\n"); \
47         called_ ## func = TRUE; \
48     }while(0)
49
50 #define CHECK_CALLED(func) \
51     do { \
52         ok(called_ ## func, "expected " #func "\n"); \
53         expect_ ## func = called_ ## func = FALSE; \
54     }while(0)
55
56 DEFINE_GUID(CLSID_ResProtocol, 0x3050F3BC, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
57 DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B);
58
59 DEFINE_EXPECT(GetBindInfo);
60 DEFINE_EXPECT(ReportProgress);
61 DEFINE_EXPECT(ReportData);
62 DEFINE_EXPECT(ReportResult);
63
64 static HRESULT expect_hrResult;
65 static BOOL expect_hr_win32err = FALSE;
66
67 static HRESULT WINAPI ProtocolSink_QueryInterface(IInternetProtocolSink *iface, REFIID riid, void **ppv)
68 {
69     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
70         *ppv = iface;
71         return S_OK;
72     }
73     return E_NOINTERFACE;
74 }
75
76 static ULONG WINAPI ProtocolSink_AddRef(IInternetProtocolSink *iface)
77 {
78     return 2;
79 }
80
81 static ULONG WINAPI ProtocolSink_Release(IInternetProtocolSink *iface)
82 {
83     return 1;
84 }
85
86 static HRESULT WINAPI ProtocolSink_Switch(IInternetProtocolSink *iface, PROTOCOLDATA *pProtocolData)
87 {
88     ok(0, "unexpected call\n");
89     return E_NOTIMPL;
90 }
91
92 static HRESULT WINAPI ProtocolSink_ReportProgress(IInternetProtocolSink *iface, ULONG ulStatusCode,
93         LPCWSTR szStatusText)
94 {
95     static const WCHAR text_html[] = {'t','e','x','t','/','h','t','m','l',0};
96
97     CHECK_EXPECT(ReportProgress);
98
99     ok(ulStatusCode == BINDSTATUS_MIMETYPEAVAILABLE
100             || ulStatusCode == BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE,
101             "ulStatusCode=%ld\n", ulStatusCode);
102     ok(!lstrcmpW(szStatusText, text_html), "szStatusText != text/html\n");
103
104     return S_OK;
105 }
106
107 static HRESULT WINAPI ProtocolSink_ReportData(IInternetProtocolSink *iface, DWORD grfBSCF, ULONG ulProgress,
108         ULONG ulProgressMax)
109 {
110     CHECK_EXPECT(ReportData);
111
112     ok(ulProgress == ulProgressMax, "ulProgress != ulProgressMax\n");
113     ok(grfBSCF == (BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE),
114             "grcf = %08lx\n", grfBSCF);
115
116     return S_OK;
117 }
118
119 static HRESULT WINAPI ProtocolSink_ReportResult(IInternetProtocolSink *iface, HRESULT hrResult, DWORD dwError,
120         LPCWSTR szResult)
121 {
122     CHECK_EXPECT(ReportResult);
123
124     if(expect_hr_win32err)
125         ok((hrResult&0xffff0000) == ((FACILITY_WIN32 << 16)|0x80000000) || expect_hrResult,
126                 "expected win32 err or %08lx got: %08lx\n", expect_hrResult, hrResult);
127     else
128         ok(hrResult == expect_hrResult, "expected: %08lx got: %08lx\n", expect_hrResult, hrResult);
129     ok(dwError == 0, "dwError = %ld\n", dwError);
130     ok(!szResult, "szResult != NULL\n");
131
132     return S_OK;
133 }
134
135 static IInternetProtocolSinkVtbl protocol_sink_vtbl = {
136     ProtocolSink_QueryInterface,
137     ProtocolSink_AddRef,
138     ProtocolSink_Release,
139     ProtocolSink_Switch,
140     ProtocolSink_ReportProgress,
141     ProtocolSink_ReportData,
142     ProtocolSink_ReportResult
143 };
144
145 static IInternetProtocolSink protocol_sink = {
146     &protocol_sink_vtbl
147 };
148
149 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface, REFIID riid, void **ppv)
150 {
151     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IInternetBindInfo, riid)) {
152         *ppv = iface;
153         return S_OK;
154     }
155     return E_NOINTERFACE;
156 }
157
158 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
159 {
160     return 2;
161 }
162
163 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
164 {
165     return 1;
166 }
167
168 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
169 {
170     CHECK_EXPECT(GetBindInfo);
171
172     ok(grfBINDF != NULL, "grfBINDF == NULL\n");
173     if(grfBINDF)
174         ok(!*grfBINDF, "*grfBINDF != 0\n");
175     ok(pbindinfo != NULL, "pbindinfo == NULL\n");
176     ok(pbindinfo->cbSize == sizeof(BINDINFO), "wrong size of pbindinfo: %ld\n", pbindinfo->cbSize);
177
178     return S_OK;
179 }
180
181 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface, ULONG ulStringType, LPOLESTR *ppwzStr,
182         ULONG cEl, ULONG *pcElFetched)
183 {
184     ok(0, "unexpected call\n");
185     return E_NOTIMPL;
186 }
187
188 static IInternetBindInfoVtbl bind_info_vtbl = {
189     BindInfo_QueryInterface,
190     BindInfo_AddRef,
191     BindInfo_Release,
192     BindInfo_GetBindInfo,
193     BindInfo_GetBindString
194 };
195
196 static IInternetBindInfo bind_info = {
197     &bind_info_vtbl
198 };
199
200 static void test_protocol_fail(IInternetProtocol *protocol, LPCWSTR url, HRESULT expected_hres,
201         BOOL expect_win32err)
202 {
203     HRESULT hres;
204
205     SET_EXPECT(GetBindInfo);
206     SET_EXPECT(ReportResult);
207
208     expect_hrResult = expected_hres;
209     expect_hr_win32err = expect_win32err;
210     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
211     if(expect_win32err)
212         ok((hres&0xffff0000) == ((FACILITY_WIN32 << 16)|0x80000000) || hres == expect_hrResult,
213                 "expected win32 err or %08lx got: %08lx\n", expected_hres, hres);
214     else
215         ok(hres == expected_hres, "expected: %08lx got: %08lx\n", expected_hres, hres);
216
217     CHECK_CALLED(GetBindInfo);
218     CHECK_CALLED(ReportResult);
219 }
220
221 static void protocol_start(IInternetProtocol *protocol, LPCWSTR url)
222 {
223     HRESULT hres;
224
225     SET_EXPECT(GetBindInfo);
226     SET_EXPECT(ReportResult);
227     SET_EXPECT(ReportProgress);
228     SET_EXPECT(ReportData);
229     expect_hrResult = S_OK;
230     expect_hr_win32err = FALSE;
231
232     hres = IInternetProtocol_Start(protocol, url, &protocol_sink, &bind_info, 0, 0);
233     ok(hres == S_OK, "Start failed: %08lx\n", hres);
234
235     CHECK_CALLED(GetBindInfo);
236     CHECK_CALLED(ReportProgress);
237     CHECK_CALLED(ReportData);
238     CHECK_CALLED(ReportResult);
239 }
240
241 static void test_res_protocol(void)
242 {
243     IInternetProtocolInfo *protocol_info;
244     IUnknown *unk;
245     IClassFactory *factory;
246     HRESULT hres;
247
248     static const WCHAR blank_url[] =
249         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
250     static const WCHAR wrong_url1[] =
251         {'m','s','h','t','m','l','.','d','l','l','/','b','l','a','n','k','.','m','t','h',0};
252     static const WCHAR wrong_url2[] =
253         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l',0};
254     static const WCHAR wrong_url3[] =
255         {'r','e','s',':','/','/','m','s','h','t','m','l','.','d','l','l','/','x','x','.','h','t','m',0};
256     static const WCHAR wrong_url4[] =
257         {'r','e','s',':','/','/','x','x','.','d','l','l','/','b','l','a','n','k','.','h','t','m',0};
258
259
260     hres = CoGetClassObject(&CLSID_ResProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
261     ok(hres == S_OK, "CoGetClassObject failed: %08lx\n", hres);
262     if(!SUCCEEDED(hres))
263         return;
264
265     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
266     ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08lx\n", hres);
267     if(SUCCEEDED(hres)) {
268         WCHAR buf[128];
269         DWORD size;
270         int i;
271
272         for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
273             if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
274                 hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, i, 0, buf,
275                         sizeof(buf)/sizeof(buf[0]), &size, 0);
276                 ok(hres == INET_E_DEFAULT_ACTION,
277                         "[%d] failed: %08lx, expected INET_E_DEFAULT_ACTION\n", i, hres);
278             }
279         }
280
281         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
282                 sizeof(buf)/sizeof(buf[0]), &size, 0);
283         ok(hres == S_OK, "ParseUrl failed: %08lx\n", hres);
284
285         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
286                 3, &size, 0);
287         ok(hres == S_FALSE, "ParseUrl failed: %08lx, expected S_FALSE\n", hres);
288
289         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_SECURITY_URL, 0, buf,
290                 sizeof(buf)/sizeof(buf[0]), &size, 0);
291         ok(hres == MK_E_SYNTAX, "ParseUrl failed: %08lx, expected MK_E_SYNTAX\n", hres);
292
293         buf[0] = '?';
294         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
295                 sizeof(buf)/sizeof(buf[0]), &size, 0);
296         ok(hres == S_OK, "ParseUrl failed: %08lx\n", hres);
297         ok(buf[0] == '?', "buf changed\n");
298
299         hres = IInternetProtocolInfo_ParseUrl(protocol_info, wrong_url1, PARSE_DOMAIN, 0, buf,
300                 sizeof(buf)/sizeof(buf[0]), &size, 0);
301         ok(hres == S_OK, "ParseUrl failed: %08lx, expected MK_E_SYNTAX\n", hres);
302         ok(buf[0] == '?', "buf changed\n");
303
304         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_UNESCAPE+1, 0, buf,
305                 sizeof(buf)/sizeof(buf[0]), &size, 0);
306         ok(hres == INET_E_DEFAULT_ACTION,
307                 "ParseUrl failed: %08lx, expected INET_E_DEFAULT_ACTION\n", hres);
308
309         IInternetProtocolInfo_Release(protocol_info);
310     }
311
312     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
313     ok(hres == S_OK, "Could not get IClassFactory interface\n");
314     if(SUCCEEDED(hres)) {
315         IInternetProtocol *protocol;
316         BYTE buf[512];
317         ULONG cb;
318         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
319         ok(hres == S_OK, "Could not get IInternetProtocol: %08lx\n", hres);
320
321         if(SUCCEEDED(hres)) {
322             test_protocol_fail(protocol, wrong_url1, MK_E_SYNTAX, FALSE);
323             test_protocol_fail(protocol, wrong_url2, MK_E_SYNTAX, FALSE);
324             test_protocol_fail(protocol, wrong_url3, E_FAIL, TRUE);
325             test_protocol_fail(protocol, wrong_url4, E_FAIL, TRUE);
326
327             cb = 0xdeadbeef;
328             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
329             ok(hres == E_FAIL, "Read returned %08lx expected E_FAIL\n", hres);
330             ok(cb == 0xdeadbeef, "cb=%lu expected 0xdeadbeef\n", cb);
331     
332             protocol_start(protocol, blank_url);
333             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
334             ok(hres == S_OK, "Read failed: %08lx\n", hres);
335             ok(cb == 2, "cb=%lu expected 2\n", cb);
336             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
337             ok(hres == S_OK, "Read failed: %08lx\n", hres);
338             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
339             ok(hres == S_FALSE, "Read failed: %08lx expected S_FALSE\n", hres);
340             ok(cb == 0, "cb=%lu expected 0\n", cb);
341             hres = IInternetProtocol_UnlockRequest(protocol);
342             ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
343
344             protocol_start(protocol, blank_url);
345             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
346             ok(hres == S_OK, "Read failed: %08lx\n", hres);
347             hres = IInternetProtocol_LockRequest(protocol, 0);
348             ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
349             hres = IInternetProtocol_UnlockRequest(protocol);
350             ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
351             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
352             ok(hres == S_OK, "Read failed: %08lx\n", hres);
353
354             protocol_start(protocol, blank_url);
355             hres = IInternetProtocol_LockRequest(protocol, 0);
356             ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
357             hres = IInternetProtocol_Terminate(protocol, 0);
358             ok(hres == S_OK, "Terminate failed: %08lx\n", hres);
359             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
360             ok(hres == S_OK, "Read failed: %08lx\n\n", hres);
361             hres = IInternetProtocol_UnlockRequest(protocol);
362             ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
363             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
364             ok(hres == S_OK, "Read failed: %08lx\n", hres);
365             hres = IInternetProtocol_Terminate(protocol, 0);
366             ok(hres == S_OK, "Terminate failed: %08lx\n", hres);
367             hres = IInternetProtocol_Read(protocol, buf, 2, &cb);
368             ok(hres == S_OK, "Read failed: %08lx\n", hres);
369             ok(cb == 2, "cb=%lu expected 2\n", cb);
370
371             protocol_start(protocol, blank_url);
372             hres = IInternetProtocol_LockRequest(protocol, 0);
373             ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
374             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
375             ok(hres == S_OK, "Read failed: %08lx\n", hres);
376             protocol_start(protocol, blank_url);
377             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
378             ok(hres == S_OK, "Read failed: %08lx\n", hres);
379             hres = IInternetProtocol_Terminate(protocol, 0);
380             ok(hres == S_OK, "Terminate failed: %08lx\n", hres);
381
382             IInternetProtocol_Release(protocol);
383         }
384
385         IClassFactory_Release(factory);
386     }
387
388     IUnknown_Release(unk);
389 }
390
391 static void test_about_protocol(void)
392 {
393     IInternetProtocolInfo *protocol_info;
394     IUnknown *unk;
395     IClassFactory *factory;
396     HRESULT hres;
397
398     static const WCHAR blank_url[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
399     static const WCHAR test_url[] = {'a','b','o','u','t',':','t','e','s','t',0};
400     static const WCHAR res_url[] = {'r','e','s',':','b','l','a','n','k',0};
401     static const WCHAR blank_html[] = {0xfeff,'<','H','T','M','L','>','<','/','H','T','M','L','>',0};
402     static const WCHAR test_html[] =
403         {0xfeff,'<','H','T','M','L','>','t','e','s','t','<','/','H','T','M','L','>',0};
404
405     hres = CoGetClassObject(&CLSID_AboutProtocol, CLSCTX_INPROC_SERVER, NULL, &IID_IUnknown, (void**)&unk);
406     ok(hres == S_OK, "CoGetClassObject failed: %08lx\n", hres);
407     if(!SUCCEEDED(hres))
408         return;
409
410     hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocolInfo, (void**)&protocol_info);
411     ok(hres == S_OK, "Could not get IInternetProtocolInfo interface: %08lx\n", hres);
412     if(SUCCEEDED(hres)) {
413         WCHAR buf[128];
414         DWORD size;
415         int i;
416
417         for(i = PARSE_CANONICALIZE; i <= PARSE_UNESCAPE; i++) {
418             if(i != PARSE_SECURITY_URL && i != PARSE_DOMAIN) {
419                 hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, i, 0, buf,
420                         sizeof(buf)/sizeof(buf[0]), &size, 0);
421                 ok(hres == INET_E_DEFAULT_ACTION,
422                         "[%d] failed: %08lx, expected INET_E_DEFAULT_ACTION\n", i, hres);
423             }
424         }
425
426         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
427                 sizeof(buf)/sizeof(buf[0]), &size, 0);
428         ok(hres == S_OK, "ParseUrl failed: %08lx\n", hres);
429         ok(!lstrcmpW(blank_url, buf), "buf != blank_url\n");
430
431         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_SECURITY_URL, 0, buf,
432                 3, &size, 0);
433         ok(hres == S_FALSE, "ParseUrl failed: %08lx, expected S_FALSE\n", hres);
434
435         hres = IInternetProtocolInfo_ParseUrl(protocol_info, test_url, PARSE_SECURITY_URL, 0, buf,
436                 sizeof(buf)/sizeof(buf[0]), &size, 0);
437         ok(hres == S_OK, "ParseUrl failed: %08lx\n", hres);
438         ok(!lstrcmpW(test_url, buf), "buf != test_url\n");
439
440         buf[0] = '?';
441         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_DOMAIN, 0, buf,
442                 sizeof(buf)/sizeof(buf[0]), &size, 0);
443         ok(hres == S_OK, "ParseUrl failed: %08lx\n", hres);
444         ok(buf[0] == '?', "buf changed\n");
445
446         hres = IInternetProtocolInfo_ParseUrl(protocol_info, blank_url, PARSE_UNESCAPE+1, 0, buf,
447                 sizeof(buf)/sizeof(buf[0]), &size, 0);
448         ok(hres == INET_E_DEFAULT_ACTION,
449                 "ParseUrl failed: %08lx, expected INET_E_DEFAULT_ACTION\n", hres);
450
451         IInternetProtocolInfo_Release(protocol_info);
452     }
453
454     hres = IUnknown_QueryInterface(unk, &IID_IClassFactory, (void**)&factory);
455     ok(hres == S_OK, "Could not get IClassFactory interface\n");
456     if(SUCCEEDED(hres)) {
457         IInternetProtocol *protocol;
458         BYTE buf[512];
459         ULONG cb;
460         hres = IClassFactory_CreateInstance(factory, NULL, &IID_IInternetProtocol, (void**)&protocol);
461         ok(hres == S_OK, "Could not get IInternetProtocol: %08lx\n", hres);
462
463         if(SUCCEEDED(hres)) {
464             protocol_start(protocol, blank_url);
465             hres = IInternetProtocol_LockRequest(protocol, 0);
466             ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
467             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
468             ok(hres == S_OK, "Read failed: %08lx\n", hres);
469             ok(cb == sizeof(blank_html), "cb=%ld, expected %d\n", cb, sizeof(blank_html));
470             ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n");
471             hres = IInternetProtocol_UnlockRequest(protocol);
472             ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
473
474             protocol_start(protocol, test_url);
475             hres = IInternetProtocol_LockRequest(protocol, 0);
476             ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
477             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
478             ok(hres == S_OK, "Read failed: %08lx\n", hres);
479             ok(cb == sizeof(test_html), "cb=%ld, expected %d\n", cb, sizeof(test_html));
480             ok(!memcmp(buf, test_html, cb), "Readed wrong data\n");
481             hres = IInternetProtocol_UnlockRequest(protocol);
482             ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
483
484             protocol_start(protocol, res_url);
485             hres = IInternetProtocol_LockRequest(protocol, 0);
486             ok(hres == S_OK, "LockRequest failed: %08lx\n", hres);
487             hres = IInternetProtocol_Read(protocol, buf, sizeof(buf), &cb);
488             ok(hres == S_OK, "Read failed: %08lx\n", hres);
489             ok(cb == sizeof(blank_html), "cb=%ld, expected %d\n", cb, sizeof(blank_html));
490             ok(!memcmp(buf, blank_html, cb), "Readed wrong data\n");
491             hres = IInternetProtocol_UnlockRequest(protocol);
492             ok(hres == S_OK, "UnlockRequest failed: %08lx\n", hres);
493
494             IInternetProtocol_Release(protocol);
495         }
496
497         IClassFactory_Release(factory);
498     }
499
500     IUnknown_Release(unk);
501 }
502
503 START_TEST(protocol)
504 {
505     OleInitialize(NULL);
506
507     test_res_protocol();
508     test_about_protocol();
509
510     OleUninitialize();
511 }