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