Fix gcc 4.0 -Wpointer-sign warnings.
[wine] / dlls / mshtml / 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 #include "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "ole2.h"
30 #include "docobj.h"
31
32 #include "mshtml.h"
33
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 #include "mshtml_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40
41 /********************************************************************
42  * common ProtocolFactory implementation
43  */
44
45 #define PROTOCOLINFO(x) ((IInternetProtocolInfo*) &(x)->lpInternetProtocolInfoVtbl)
46 #define CLASSFACTORY(x) ((IClassFactory*)         &(x)->lpClassFactoryVtbl)
47
48 typedef struct {
49     const IInternetProtocolInfoVtbl *lpInternetProtocolInfoVtbl;
50     const IClassFactoryVtbl         *lpClassFactoryVtbl;
51 } ProtocolFactory;
52
53 #define PROTOCOLINFO_THIS(iface) \
54     (ProtocolFactory*)((char*)(iface)-offsetof(ProtocolFactory,lpInternetProtocolInfoVtbl))
55
56 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
57 {
58     ProtocolFactory *This = PROTOCOLINFO_THIS(iface);
59
60     *ppv = NULL;
61     if(IsEqualGUID(&IID_IUnknown, riid)) {
62         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
63         *ppv = PROTOCOLINFO(This);
64     }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
65         TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
66         *ppv = PROTOCOLINFO(This);
67     }else if(IsEqualGUID(&IID_IClassFactory, riid)) {
68         TRACE("(%p)->(IID_IClassFactory %p)\n", This, ppv);
69         *ppv = CLASSFACTORY(This);
70     }
71
72     if(!*ppv) {
73         WARN("unknown interface %s\n", debugstr_guid(riid));
74         return E_NOINTERFACE;
75     }
76
77     IInternetProtocolInfo_AddRef(iface);
78     return S_OK;
79 }
80
81 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
82 {
83     ProtocolFactory *This = PROTOCOLINFO_THIS(iface);
84     TRACE("(%p)\n", This);
85     return 2;
86 }
87
88 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
89 {
90     ProtocolFactory *This = PROTOCOLINFO_THIS(iface);
91     TRACE("(%p)\n", This);
92     return 1;
93 }
94
95 #undef PROTOCOLINFO_THIS
96
97 #define CLASSFACTORY_THIS(iface) \
98     (ProtocolFactory*)((char*)(iface)-offsetof(ProtocolFactory,lpClassFactoryVtbl))
99
100 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
101 {
102     ProtocolFactory *This = CLASSFACTORY_THIS(iface);
103     return IInternetProtocolInfo_QueryInterface(PROTOCOLINFO(This), riid, ppv);
104 }
105
106 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
107 {
108     ProtocolFactory *This = CLASSFACTORY_THIS(iface);
109     return IInternetProtocolInfo_AddRef(PROTOCOLINFO(This));
110 }
111
112 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
113 {
114     ProtocolFactory *This = CLASSFACTORY_THIS(iface);
115     return IInternetProtocolInfo_Release(PROTOCOLINFO(This));
116 }
117
118 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
119 {
120     ProtocolFactory *This = CLASSFACTORY_THIS(iface);
121     FIXME("(%p)->(%x)\n", This, dolock);
122     return S_OK;
123 }
124
125 #undef CLASSFACTORY_THIS
126
127 /********************************************************************
128  * AboutProtocol implementation
129  */
130
131 typedef struct {
132     const IInternetProtocolVtbl *lpInternetProtocolVtbl;
133     LONG ref;
134 } AboutProtocol;
135
136 static HRESULT WINAPI AboutProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
137 {
138     *ppv = NULL;
139
140     if(IsEqualGUID(&IID_IUnknown, riid)) {
141         TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
142         *ppv = iface;
143     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
144         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv);
145         *ppv = iface;
146     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
147         TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv);
148         *ppv = iface;
149     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
150         FIXME("IServiceProvider is not implemented\n");
151         return E_NOINTERFACE;
152     }
153
154     if(!*ppv) {
155         TRACE("unknown interface %s\n", debugstr_guid(riid));
156         return E_NOINTERFACE;
157     }
158
159     IInternetProtocol_AddRef(iface);
160     return S_OK;
161 }
162
163 static ULONG WINAPI AboutProtocol_AddRef(IInternetProtocol *iface)
164 {
165     AboutProtocol *This = (AboutProtocol*)iface;
166     ULONG ref = InterlockedIncrement(&This->ref);
167     TRACE("(%p) ref=%ld\n", iface, ref);
168     return ref;
169 }
170
171 static ULONG WINAPI AboutProtocol_Release(IInternetProtocol *iface)
172 {
173     AboutProtocol *This = (AboutProtocol*)iface;
174     ULONG ref = InterlockedDecrement(&This->ref);
175
176     TRACE("(%p) ref=%lx\n", iface, ref);
177
178     if(!ref)
179         HeapFree(GetProcessHeap(), 0, This);
180
181     return ref;
182 }
183
184 static HRESULT WINAPI AboutProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
185         IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
186         DWORD grfPI, DWORD dwReserved)
187 {
188     AboutProtocol *This = (AboutProtocol*)iface;
189     FIXME("(%p)->(%s %p %p %08lx %ld)\n", This, debugstr_w(szUrl), pOIProtSink,
190             pOIBindInfo, grfPI, dwReserved);
191     return E_NOTIMPL;
192 }
193
194 static HRESULT WINAPI AboutProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
195 {
196     AboutProtocol *This = (AboutProtocol*)iface;
197     FIXME("(%p)->(%p)\n", This, pProtocolData);
198     return E_NOTIMPL;
199 }
200
201 static HRESULT WINAPI AboutProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
202         DWORD dwOptions)
203 {
204     AboutProtocol *This = (AboutProtocol*)iface;
205     FIXME("(%p)->(%08lx %08lx)\n", This, hrReason, dwOptions);
206     return E_NOTIMPL;
207 }
208
209 static HRESULT WINAPI AboutProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
210 {
211     AboutProtocol *This = (AboutProtocol*)iface;
212     FIXME("(%p)->(%08lx)\n", This, dwOptions);
213     return E_NOTIMPL;
214 }
215
216 static HRESULT WINAPI AboutProtocol_Suspend(IInternetProtocol *iface)
217 {
218     AboutProtocol *This = (AboutProtocol*)iface;
219     FIXME("(%p)\n", This);
220     return E_NOTIMPL;
221 }
222
223 static HRESULT WINAPI AboutProtocol_Resume(IInternetProtocol *iface)
224 {
225     AboutProtocol *This = (AboutProtocol*)iface;
226     FIXME("(%p)\n", This);
227     return E_NOTIMPL;
228 }
229
230 static HRESULT WINAPI AboutProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
231 {
232     AboutProtocol *This = (AboutProtocol*)iface;
233     FIXME("(%p)->(%lu %p)\n", This, cb, pcbRead);
234     return E_NOTIMPL;
235 }
236
237 static HRESULT WINAPI AboutProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
238         DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
239 {
240     AboutProtocol *This = (AboutProtocol*)iface;
241     FIXME("(%p)->(%ld %ld %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
242     return E_NOTIMPL;
243 }
244
245 static HRESULT WINAPI AboutProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
246 {
247     AboutProtocol *This = (AboutProtocol*)iface;
248     FIXME("(%p)->(%ld)\n", This, dwOptions);
249     return E_NOTIMPL;
250 }
251
252 static HRESULT WINAPI AboutProtocol_UnlockRequest(IInternetProtocol *iface)
253 {
254     AboutProtocol *This = (AboutProtocol*)iface;
255     FIXME("(%p)\n", This);
256     return E_NOTIMPL;
257 }
258
259 static const IInternetProtocolVtbl AboutProtocolVtbl = {
260     AboutProtocol_QueryInterface,
261     AboutProtocol_AddRef,
262     AboutProtocol_Release,
263     AboutProtocol_Start,
264     AboutProtocol_Continue,
265     AboutProtocol_Abort,
266     AboutProtocol_Terminate,
267     AboutProtocol_Suspend,
268     AboutProtocol_Resume,
269     AboutProtocol_Read,
270     AboutProtocol_Seek,
271     AboutProtocol_LockRequest,
272     AboutProtocol_UnlockRequest
273 };
274
275 static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
276         REFIID riid, void **ppv)
277 {
278     AboutProtocol *ret;
279     HRESULT hres;
280
281     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
282
283     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(AboutProtocol));
284     ret->lpInternetProtocolVtbl = &AboutProtocolVtbl;
285     ret->ref = 0;
286
287     hres = IUnknown_QueryInterface((IUnknown*)ret, riid, ppv);
288
289     if(FAILED(hres))
290         HeapFree(GetProcessHeap(), 0, ret);
291
292     return hres;
293 }
294
295 static HRESULT WINAPI AboutProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
296         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
297         DWORD* pcchResult, DWORD dwReserved)
298 {
299     FIXME("%p)->(%s %08x %08lx %p %ld %p %ld)\n", iface, debugstr_w(pwzUrl), ParseAction,
300             dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
301     return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI AboutProtocolInfo_CombineUrl(IInternetProtocolInfo *iface, LPCWSTR pwzBaseUrl,
305         LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult,
306         DWORD* pcchResult, DWORD dwReserved)
307 {
308     FIXME("%p)->(%s %s %08lx %p %ld %p %ld)\n", iface, debugstr_w(pwzBaseUrl), debugstr_w(pwzRelativeUrl),
309             dwCombineFlags, pwzResult, cchResult, pcchResult, dwReserved);
310     return E_NOTIMPL;
311 }
312
313 static HRESULT WINAPI AboutProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
314         LPCWSTR pwzUrl2, DWORD dwCompareFlags)
315 {
316     FIXME("%p)->(%s %s %08lx)\n", iface, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
317     return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI AboutProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
321         QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
322         DWORD dwReserved)
323 {
324     FIXME("%p)->(%s %08x %08lx %p %ld %p %ld)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
325             cbBuffer, pcbBuf, dwReserved);
326     return E_NOTIMPL;
327 }
328
329 static const IInternetProtocolInfoVtbl AboutProtocolInfoVtbl = {
330     InternetProtocolInfo_QueryInterface,
331     InternetProtocolInfo_AddRef,
332     InternetProtocolInfo_Release,
333     AboutProtocolInfo_ParseUrl,
334     AboutProtocolInfo_CombineUrl,
335     AboutProtocolInfo_CompareUrl,
336     AboutProtocolInfo_QueryInfo
337 };
338
339 static const IClassFactoryVtbl AboutProtocolFactoryVtbl = {
340     ClassFactory_QueryInterface,
341     ClassFactory_AddRef,
342     ClassFactory_Release,
343     AboutProtocolFactory_CreateInstance,
344     ClassFactory_LockServer
345 };
346
347 static ProtocolFactory AboutProtocolFactory = {
348     &AboutProtocolInfoVtbl,
349     &AboutProtocolFactoryVtbl
350 };
351
352 /********************************************************************
353  * ResProtocol implementation
354  */
355
356 typedef struct {
357     const IInternetProtocolVtbl *lpInternetProtocolVtbl;
358     LONG ref;
359
360     BYTE *data;
361     ULONG data_len;
362     ULONG cur;
363 } ResProtocol;
364
365 static HRESULT WINAPI ResProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
366 {
367     *ppv = NULL;
368
369     if(IsEqualGUID(&IID_IUnknown, riid)) {
370         TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
371         *ppv = iface;
372     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
373         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv);
374         *ppv = iface;
375     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
376         TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv);
377         *ppv = iface;
378     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
379         FIXME("IServiceProvider is not implemented\n");
380         return E_NOINTERFACE;
381     }
382
383     if(!*ppv) {
384         TRACE("unknown interface %s\n", debugstr_guid(riid));
385         return E_NOINTERFACE;
386     }
387
388     IInternetProtocol_AddRef(iface);
389     return S_OK;
390 }
391
392 static ULONG WINAPI ResProtocol_AddRef(IInternetProtocol *iface)
393 {
394     ResProtocol *This = (ResProtocol*)iface;
395     ULONG ref = InterlockedIncrement(&This->ref);
396     TRACE("(%p) ref=%ld\n", iface, ref);
397     return ref;
398 }
399
400 static ULONG WINAPI ResProtocol_Release(IInternetProtocol *iface)
401 {
402     ResProtocol *This = (ResProtocol*)iface;
403     ULONG ref = InterlockedDecrement(&This->ref);
404
405     TRACE("(%p) ref=%lx\n", iface, ref);
406
407     if(!ref) {
408         HeapFree(GetProcessHeap(), 0, This->data);
409         HeapFree(GetProcessHeap(), 0, This);
410     }
411
412     return ref;
413 }
414
415 static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
416         IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
417         DWORD grfPI, DWORD dwReserved)
418 {
419     ResProtocol *This = (ResProtocol*)iface;
420     DWORD grfBINDF = 0;
421     BINDINFO bindinfo;
422     int len;
423     WCHAR dll[MAX_PATH];
424     LPCWSTR url_dll, url_file;
425     HMODULE hdll;
426     HRSRC src;
427
428     static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
429
430     TRACE("(%p)->(%s %p %p %08lx %ld)\n", This, debugstr_w(szUrl), pOIProtSink,
431             pOIBindInfo, grfPI, dwReserved);
432
433     memset(&bindinfo, 0, sizeof(bindinfo));
434     bindinfo.cbSize = sizeof(BINDINFO);
435     IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
436
437     /* FIXME:
438      * Implement MIME type checking
439      * Use CoInternetParseUrl (not implemented yet)
440      */
441
442     len = strlenW(szUrl);
443     if(len < sizeof(wszRes)/sizeof(wszRes[0]) || memcmp(szUrl, wszRes, sizeof(wszRes))) {
444         WARN("Wrong protocol of url: %s\n", debugstr_w(szUrl));
445         IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL);
446         return MK_E_SYNTAX;
447     }
448
449     url_dll = szUrl + sizeof(wszRes)/sizeof(wszRes[0]);
450     if(!(url_file = strchrW(url_dll, '/'))) {
451         WARN("wrong url: %s\n", debugstr_w(szUrl));
452         IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL);
453         return MK_E_SYNTAX;
454     }
455
456     memcpy(dll, url_dll, (url_file-url_dll)*sizeof(WCHAR));
457     dll[url_file-url_dll] = 0;
458
459     hdll = LoadLibraryExW(dll, NULL, LOAD_LIBRARY_AS_DATAFILE);
460     if(!hdll) {
461         WARN("Could not open dll: %s\n", debugstr_w(dll));
462         IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
463         return HRESULT_FROM_WIN32(GetLastError());
464     }
465
466     src = FindResourceW(hdll, ++url_file, (LPCWSTR)RT_HTML);
467     if(!src) {
468         WARN("Could not find resource: %s\n", debugstr_w(url_file));
469         IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
470         return HRESULT_FROM_WIN32(GetLastError());
471     }
472
473     if(This->data) {
474         WARN("data already loaded\n");
475         HeapFree(GetProcessHeap(), 0, This->data);
476     }
477
478     This->data_len = SizeofResource(hdll, src);
479     This->data = HeapAlloc(GetProcessHeap(), 0, This->data_len);
480     memcpy(This->data, LoadResource(hdll, src), This->data_len);
481     This->cur = 0;
482
483     FreeLibrary(hdll);
484
485     IInternetProtocolSink_ReportData(pOIProtSink,
486             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
487             This->data_len, This->data_len);
488
489     IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
490     
491     return S_OK;
492 }
493
494 static HRESULT WINAPI ResProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
495 {
496     ResProtocol *This = (ResProtocol*)iface;
497     FIXME("(%p)->(%p)\n", This, pProtocolData);
498     return E_NOTIMPL;
499 }
500
501 static HRESULT WINAPI ResProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
502         DWORD dwOptions)
503 {
504     ResProtocol *This = (ResProtocol*)iface;
505     FIXME("(%p)->(%08lx %08lx)\n", This, hrReason, dwOptions);
506     return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI ResProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
510 {
511     ResProtocol *This = (ResProtocol*)iface;
512
513     TRACE("(%p)->(%08lx)\n", This, dwOptions);
514
515     /* test show that we don't have to do anything here */
516     return S_OK;
517 }
518
519 static HRESULT WINAPI ResProtocol_Suspend(IInternetProtocol *iface)
520 {
521     ResProtocol *This = (ResProtocol*)iface;
522     FIXME("(%p)\n", This);
523     return E_NOTIMPL;
524 }
525
526 static HRESULT WINAPI ResProtocol_Resume(IInternetProtocol *iface)
527 {
528     ResProtocol *This = (ResProtocol*)iface;
529     FIXME("(%p)\n", This);
530     return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI ResProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
534 {
535     ResProtocol *This = (ResProtocol*)iface;
536
537     TRACE("(%p)->(%p %lu %p)\n", This, pv, cb, pcbRead);
538
539     if(!This->data)
540         return E_FAIL;
541
542     *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
543
544     if(!*pcbRead)
545         return S_FALSE;
546
547     memcpy(pv, This->data, *pcbRead);
548     This->cur += *pcbRead;
549
550     return S_OK;
551 }
552
553 static HRESULT WINAPI ResProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
554         DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
555 {
556     ResProtocol *This = (ResProtocol*)iface;
557     FIXME("(%p)->(%ld %ld %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
558     return E_NOTIMPL;
559 }
560
561 static HRESULT WINAPI ResProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
562 {
563     ResProtocol *This = (ResProtocol*)iface;
564
565     TRACE("(%p)->(%ld)\n", This, dwOptions);
566
567     /* test show that we don't have to do anything here */
568     return S_OK;
569 }
570
571 static HRESULT WINAPI ResProtocol_UnlockRequest(IInternetProtocol *iface)
572 {
573     ResProtocol *This = (ResProtocol*)iface;
574
575     TRACE("(%p)\n", This);
576
577     /* test show that we don't have to do anything here */
578     return S_OK;
579 }
580
581 static const IInternetProtocolVtbl ResProtocolVtbl = {
582     ResProtocol_QueryInterface,
583     ResProtocol_AddRef,
584     ResProtocol_Release,
585     ResProtocol_Start,
586     ResProtocol_Continue,
587     ResProtocol_Abort,
588     ResProtocol_Terminate,
589     ResProtocol_Suspend,
590     ResProtocol_Resume,
591     ResProtocol_Read,
592     ResProtocol_Seek,
593     ResProtocol_LockRequest,
594     ResProtocol_UnlockRequest
595 };
596
597 static HRESULT WINAPI ResProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
598         REFIID riid, void **ppv)
599 {
600     ResProtocol *ret;
601     HRESULT hres;
602
603     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
604
605     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ResProtocol));
606     ret->lpInternetProtocolVtbl = &ResProtocolVtbl;
607     ret->ref = 0;
608     ret->data = NULL;
609     ret->data_len = 0;
610     ret->cur = 0;
611
612     hres = IUnknown_QueryInterface((IUnknown*)ret, riid, ppv);
613
614     if(FAILED(hres))
615         HeapFree(GetProcessHeap(), 0, ret);
616
617     return hres;
618 }
619
620 static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
621         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
622         DWORD* pcchResult, DWORD dwReserved)
623 {
624     FIXME("%p)->(%s %08x %08lx %p %ld %p %ld)\n", iface, debugstr_w(pwzUrl), ParseAction,
625             dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
626     return E_NOTIMPL;
627 }
628
629 static HRESULT WINAPI ResProtocolInfo_CombineUrl(IInternetProtocolInfo *iface, LPCWSTR pwzBaseUrl,
630         LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult,
631         DWORD* pcchResult, DWORD dwReserved)
632 {
633     FIXME("%p)->(%s %s %08lx %p %ld %p %ld)\n", iface, debugstr_w(pwzBaseUrl), debugstr_w(pwzRelativeUrl),
634             dwCombineFlags, pwzResult, cchResult, pcchResult, dwReserved);
635     return E_NOTIMPL;
636 }
637
638 static HRESULT WINAPI ResProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
639         LPCWSTR pwzUrl2, DWORD dwCompareFlags)
640 {
641     FIXME("%p)->(%s %s %08lx)\n", iface, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
642     return E_NOTIMPL;
643 }
644
645 static HRESULT WINAPI ResProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
646         QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
647         DWORD dwReserved)
648 {
649     FIXME("%p)->(%s %08x %08lx %p %ld %p %ld)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
650             cbBuffer, pcbBuf, dwReserved);
651     return E_NOTIMPL;
652 }
653
654 static const IInternetProtocolInfoVtbl ResProtocolInfoVtbl = {
655     InternetProtocolInfo_QueryInterface,
656     InternetProtocolInfo_AddRef,
657     InternetProtocolInfo_Release,
658     ResProtocolInfo_ParseUrl,
659     ResProtocolInfo_CombineUrl,
660     ResProtocolInfo_CompareUrl,
661     ResProtocolInfo_QueryInfo
662 };
663
664 static const IClassFactoryVtbl ResProtocolFactoryVtbl = {
665     ClassFactory_QueryInterface,
666     ClassFactory_AddRef,
667     ClassFactory_Release,
668     ResProtocolFactory_CreateInstance,
669     ClassFactory_LockServer
670 };
671
672 static ProtocolFactory ResProtocolFactory = {
673     &ResProtocolInfoVtbl,
674     &ResProtocolFactoryVtbl
675 };
676
677 HRESULT ProtocolFactory_Create(REFCLSID rclsid, REFIID riid, void **ppv)
678 {
679     ProtocolFactory *cf = NULL;
680
681     if(IsEqualGUID(&CLSID_AboutProtocol, rclsid))
682         cf = &AboutProtocolFactory;
683     else if(IsEqualGUID(&CLSID_ResProtocol, rclsid))
684         cf = &ResProtocolFactory;
685
686     if(!cf) {
687         FIXME("not implemented protocol %s\n", debugstr_guid(rclsid));
688         return CLASS_E_CLASSNOTAVAILABLE;
689     }
690
691     return IUnknown_QueryInterface((IUnknown*)cf, riid, ppv);
692 }