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