mshtml: Use wide-char string literals.
[wine.git] / dlls / mshtml / protocol.c
blobd11c0132cf5b2d81ee78fe37cca47c06e36bc323
1 /*
2 * Copyright 2005 Jacek Caban
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.
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.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <stdio.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
29 #include "wine/debug.h"
31 #include "mshtml_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35 typedef struct {
36 IUnknown IUnknown_inner;
37 IInternetProtocol IInternetProtocol_iface;
39 LONG ref;
41 BYTE *data;
42 ULONG data_len;
43 ULONG cur;
45 IUnknown *outer;
46 } InternetProtocol;
48 /********************************************************************
49 * common ProtocolFactory implementation
52 typedef struct {
53 IInternetProtocolInfo IInternetProtocolInfo_iface;
54 IClassFactory IClassFactory_iface;
55 } ProtocolFactory;
57 static inline ProtocolFactory *impl_from_IInternetProtocolInfo(IInternetProtocolInfo *iface)
59 return CONTAINING_RECORD(iface, ProtocolFactory, IInternetProtocolInfo_iface);
62 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
64 ProtocolFactory *This = impl_from_IInternetProtocolInfo(iface);
66 *ppv = NULL;
67 if(IsEqualGUID(&IID_IUnknown, riid)) {
68 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
69 *ppv = &This->IInternetProtocolInfo_iface;
70 }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
71 TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
72 *ppv = &This->IInternetProtocolInfo_iface;
73 }else if(IsEqualGUID(&IID_IClassFactory, riid)) {
74 TRACE("(%p)->(IID_IClassFactory %p)\n", This, ppv);
75 *ppv = &This->IClassFactory_iface;
78 if(!*ppv) {
79 WARN("unknown interface %s\n", debugstr_guid(riid));
80 return E_NOINTERFACE;
83 IInternetProtocolInfo_AddRef(iface);
84 return S_OK;
87 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
89 TRACE("(%p)\n", iface);
90 return 2;
93 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
95 TRACE("(%p)\n", iface);
96 return 1;
99 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
100 LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult,
101 DWORD cchResult, DWORD* pcchResult, DWORD dwReserved)
103 TRACE("%p)->(%s %s %08x %p %d %p %d)\n", iface, debugstr_w(pwzBaseUrl),
104 debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult,
105 pcchResult, dwReserved);
107 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
110 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
111 LPCWSTR pwzUrl2, DWORD dwCompareFlags)
113 TRACE("%p)->(%s %s %08x)\n", iface, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
114 return E_NOTIMPL;
117 static inline ProtocolFactory *impl_from_IClassFactory(IClassFactory *iface)
119 return CONTAINING_RECORD(iface, ProtocolFactory, IClassFactory_iface);
122 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
124 ProtocolFactory *This = impl_from_IClassFactory(iface);
125 return IInternetProtocolInfo_QueryInterface(&This->IInternetProtocolInfo_iface, riid, ppv);
128 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
130 ProtocolFactory *This = impl_from_IClassFactory(iface);
131 return IInternetProtocolInfo_AddRef(&This->IInternetProtocolInfo_iface);
134 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
136 ProtocolFactory *This = impl_from_IClassFactory(iface);
137 return IInternetProtocolInfo_Release(&This->IInternetProtocolInfo_iface);
140 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
142 TRACE("(%p)->(%x)\n", iface, dolock);
143 return S_OK;
146 static inline InternetProtocol *impl_from_IUnknown(IUnknown *iface)
148 return CONTAINING_RECORD(iface, InternetProtocol, IUnknown_inner);
151 static inline InternetProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
153 return CONTAINING_RECORD(iface, InternetProtocol, IInternetProtocol_iface);
156 static HRESULT WINAPI Protocol_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
158 InternetProtocol *This = impl_from_IUnknown(iface);
160 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
162 if(IsEqualGUID(&IID_IUnknown, riid)) {
163 *ppv = &This->IUnknown_inner;
164 }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
165 *ppv = &This->IInternetProtocol_iface;
166 }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
167 *ppv = &This->IInternetProtocol_iface;
168 }else {
169 if(IsEqualGUID(&IID_IServiceProvider, riid))
170 FIXME("IServiceProvider is not implemented\n");
171 *ppv = NULL;
172 return E_NOINTERFACE;
175 IUnknown_AddRef((IUnknown*)*ppv);
176 return S_OK;
179 static ULONG WINAPI Protocol_AddRef(IUnknown *iface)
181 InternetProtocol *This = impl_from_IUnknown(iface);
182 ULONG ref = InterlockedIncrement(&This->ref);
183 TRACE("(%p) ref=%d\n", iface, ref);
184 return ref;
187 static ULONG WINAPI Protocol_Release(IUnknown *iface)
189 InternetProtocol *This = impl_from_IUnknown(iface);
190 ULONG ref = InterlockedDecrement(&This->ref);
192 TRACE("(%p) ref=%x\n", iface, ref);
194 if(!ref) {
195 heap_free(This->data);
196 heap_free(This);
199 return ref;
202 static const IUnknownVtbl ProtocolUnkVtbl = {
203 Protocol_QueryInterface,
204 Protocol_AddRef,
205 Protocol_Release
208 static HRESULT WINAPI InternetProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
210 InternetProtocol *This = impl_from_IInternetProtocol(iface);
211 return IUnknown_QueryInterface(This->outer, riid, ppv);
214 static ULONG WINAPI InternetProtocol_AddRef(IInternetProtocol *iface)
216 InternetProtocol *This = impl_from_IInternetProtocol(iface);
217 return IUnknown_AddRef(This->outer);
220 static ULONG WINAPI InternetProtocol_Release(IInternetProtocol *iface)
222 InternetProtocol *This = impl_from_IInternetProtocol(iface);
223 return IUnknown_Release(This->outer);
226 static HRESULT WINAPI InternetProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
228 InternetProtocol *This = impl_from_IInternetProtocol(iface);
229 FIXME("(%p)->(%p)\n", This, pProtocolData);
230 return E_NOTIMPL;
233 static HRESULT WINAPI InternetProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
234 DWORD dwOptions)
236 InternetProtocol *This = impl_from_IInternetProtocol(iface);
237 FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
238 return E_NOTIMPL;
241 static HRESULT WINAPI InternetProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
243 InternetProtocol *This = impl_from_IInternetProtocol(iface);
244 TRACE("(%p)->(%08x)\n", This, dwOptions);
245 return S_OK;
248 static HRESULT WINAPI InternetProtocol_Suspend(IInternetProtocol *iface)
250 InternetProtocol *This = impl_from_IInternetProtocol(iface);
251 FIXME("(%p)\n", This);
252 return E_NOTIMPL;
255 static HRESULT WINAPI InternetProtocol_Resume(IInternetProtocol *iface)
257 InternetProtocol *This = impl_from_IInternetProtocol(iface);
258 FIXME("(%p)\n", This);
259 return E_NOTIMPL;
262 static HRESULT WINAPI InternetProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
264 InternetProtocol *This = impl_from_IInternetProtocol(iface);
266 TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
268 if(!This->data)
269 return E_FAIL;
271 *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
273 if(!*pcbRead)
274 return S_FALSE;
276 memcpy(pv, This->data+This->cur, *pcbRead);
277 This->cur += *pcbRead;
279 return S_OK;
282 static HRESULT WINAPI InternetProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
283 DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
285 InternetProtocol *This = impl_from_IInternetProtocol(iface);
286 FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
287 return E_NOTIMPL;
290 static HRESULT WINAPI InternetProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
292 InternetProtocol *This = impl_from_IInternetProtocol(iface);
294 TRACE("(%p)->(%d)\n", This, dwOptions);
296 return S_OK;
299 static HRESULT WINAPI InternetProtocol_UnlockRequest(IInternetProtocol *iface)
301 InternetProtocol *This = impl_from_IInternetProtocol(iface);
303 TRACE("(%p)\n", This);
305 return S_OK;
308 static HRESULT create_protocol_instance(const IInternetProtocolVtbl *protocol_vtbl,
309 IUnknown *outer, REFIID riid, void **ppv)
311 InternetProtocol *protocol;
312 HRESULT hres;
314 if(outer && !IsEqualGUID(&IID_IUnknown, riid)) {
315 *ppv = NULL;
316 return E_INVALIDARG;
319 protocol = heap_alloc_zero(sizeof(InternetProtocol));
320 protocol->IUnknown_inner.lpVtbl = &ProtocolUnkVtbl;
321 protocol->IInternetProtocol_iface.lpVtbl = protocol_vtbl;
322 protocol->outer = outer ? outer : &protocol->IUnknown_inner;
323 protocol->ref = 1;
325 hres = IUnknown_QueryInterface(&protocol->IUnknown_inner, riid, ppv);
326 IUnknown_Release(&protocol->IUnknown_inner);
327 return hres;
330 /********************************************************************
331 * about protocol implementation
334 static HRESULT WINAPI AboutProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
335 IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
336 DWORD grfPI, HANDLE_PTR dwReserved)
338 InternetProtocol *This = impl_from_IInternetProtocol(iface);
339 BINDINFO bindinfo;
340 DWORD grfBINDF = 0;
341 LPCWSTR text = NULL;
342 DWORD data_len;
343 BYTE *data;
344 HRESULT hres;
345 static const WCHAR wszAbout[] = {'a','b','o','u','t',':'};
347 /* NOTE:
348 * the about protocol seems not to work as I would expect. It creates html document
349 * for a given url, eg. about:some_text -> <HTML>some_text</HTML> except for the case when
350 * some_text = "blank", when document is blank (<HTML></HMTL>). The same happens
351 * when the url does not have "about:" in the beginning.
354 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
355 pOIBindInfo, grfPI, dwReserved);
357 memset(&bindinfo, 0, sizeof(bindinfo));
358 bindinfo.cbSize = sizeof(BINDINFO);
359 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
360 if(FAILED(hres))
361 return hres;
362 ReleaseBindInfo(&bindinfo);
364 TRACE("bindf %x\n", grfBINDF);
366 if(lstrlenW(szUrl) >= ARRAY_SIZE(wszAbout) && !memcmp(wszAbout, szUrl, sizeof(wszAbout))) {
367 text = szUrl + ARRAY_SIZE(wszAbout);
368 if(!wcscmp(L"blank", text))
369 text = NULL;
372 data_len = sizeof(L"\xfeff<HTML>")+sizeof(L"</HTML>")-sizeof(WCHAR)
373 + (text ? lstrlenW(text)*sizeof(WCHAR) : 0);
374 data = heap_alloc(data_len);
375 if(!data)
376 return E_OUTOFMEMORY;
378 heap_free(This->data);
379 This->data = data;
380 This->data_len = data_len;
382 lstrcpyW((LPWSTR)This->data, L"\xfeff<HTML>");
383 if(text)
384 lstrcatW((LPWSTR)This->data, text);
385 lstrcatW((LPWSTR)This->data, L"</HTML>");
387 This->cur = 0;
389 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, L"text/html");
391 IInternetProtocolSink_ReportData(pOIProtSink,
392 BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
393 This->data_len, This->data_len);
395 IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
397 return S_OK;
400 static const IInternetProtocolVtbl AboutProtocolVtbl = {
401 InternetProtocol_QueryInterface,
402 InternetProtocol_AddRef,
403 InternetProtocol_Release,
404 AboutProtocol_Start,
405 InternetProtocol_Continue,
406 InternetProtocol_Abort,
407 InternetProtocol_Terminate,
408 InternetProtocol_Suspend,
409 InternetProtocol_Resume,
410 InternetProtocol_Read,
411 InternetProtocol_Seek,
412 InternetProtocol_LockRequest,
413 InternetProtocol_UnlockRequest
416 static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
417 REFIID riid, void **ppv)
419 TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
421 return create_protocol_instance(&AboutProtocolVtbl, pUnkOuter, riid, ppv);
424 static HRESULT WINAPI AboutProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
425 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
426 DWORD* pcchResult, DWORD dwReserved)
428 TRACE("%p)->(%s %d %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
429 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
431 if(ParseAction == PARSE_SECURITY_URL) {
432 unsigned int len = lstrlenW(pwzUrl)+1;
434 *pcchResult = len;
435 if(len > cchResult)
436 return S_FALSE;
438 memcpy(pwzResult, pwzUrl, len*sizeof(WCHAR));
439 return S_OK;
442 if(ParseAction == PARSE_DOMAIN) {
443 if(!pcchResult)
444 return E_POINTER;
446 if(pwzUrl)
447 *pcchResult = lstrlenW(pwzUrl)+1;
448 else
449 *pcchResult = 1;
450 return E_FAIL;
453 return INET_E_DEFAULT_ACTION;
456 static HRESULT WINAPI AboutProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
457 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
458 DWORD dwReserved)
460 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
461 cbBuffer, pcbBuf, dwReserved);
463 switch(QueryOption) {
464 case QUERY_CAN_NAVIGATE:
465 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
467 case QUERY_USES_NETWORK:
468 if(!pBuffer || cbBuffer < sizeof(DWORD))
469 return E_FAIL;
471 *(DWORD*)pBuffer = 0;
472 if(pcbBuf)
473 *pcbBuf = sizeof(DWORD);
475 break;
477 case QUERY_IS_CACHED:
478 FIXME("Unsupported option QUERY_IS_CACHED\n");
479 return E_NOTIMPL;
480 case QUERY_IS_INSTALLEDENTRY:
481 FIXME("Unsupported option QUERY_IS_INSTALLEDENTRY\n");
482 return E_NOTIMPL;
483 case QUERY_IS_CACHED_OR_MAPPED:
484 FIXME("Unsupported option QUERY_IS_CACHED_OR_MAPPED\n");
485 return E_NOTIMPL;
486 case QUERY_IS_SECURE:
487 FIXME("Unsupported option QUERY_IS_SECURE\n");
488 return E_NOTIMPL;
489 case QUERY_IS_SAFE:
490 FIXME("Unsupported option QUERY_IS_SAFE\n");
491 return E_NOTIMPL;
492 case QUERY_USES_HISTORYFOLDER:
493 FIXME("Unsupported option QUERY_USES_HISTORYFOLDER\n");
494 return E_FAIL;
495 case QUERY_IS_CACHED_AND_USABLE_OFFLINE:
496 FIXME("Unsupported option QUERY_IS_CACHED_AND_USABLE_OFFLINE\n");
497 return E_NOTIMPL;
498 default:
499 return E_FAIL;
502 return S_OK;
505 static const IInternetProtocolInfoVtbl AboutProtocolInfoVtbl = {
506 InternetProtocolInfo_QueryInterface,
507 InternetProtocolInfo_AddRef,
508 InternetProtocolInfo_Release,
509 AboutProtocolInfo_ParseUrl,
510 InternetProtocolInfo_CombineUrl,
511 InternetProtocolInfo_CompareUrl,
512 AboutProtocolInfo_QueryInfo
515 static const IClassFactoryVtbl AboutProtocolFactoryVtbl = {
516 ClassFactory_QueryInterface,
517 ClassFactory_AddRef,
518 ClassFactory_Release,
519 AboutProtocolFactory_CreateInstance,
520 ClassFactory_LockServer
523 static ProtocolFactory AboutProtocolFactory = {
524 { &AboutProtocolInfoVtbl },
525 { &AboutProtocolFactoryVtbl }
528 /********************************************************************
529 * res protocol implementation
532 static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
533 IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
534 DWORD grfPI, HANDLE_PTR dwReserved)
536 InternetProtocol *This = impl_from_IInternetProtocol(iface);
537 WCHAR *url_dll, *url_file, *url, *mime, *res_type, *alt_res_type = NULL, *ptr;
538 DWORD grfBINDF = 0, len;
539 BINDINFO bindinfo;
540 HMODULE hdll;
541 HRSRC src;
542 HRESULT hres;
544 static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
546 TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
547 pOIBindInfo, grfPI, dwReserved);
549 memset(&bindinfo, 0, sizeof(bindinfo));
550 bindinfo.cbSize = sizeof(BINDINFO);
551 hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
552 if(FAILED(hres))
553 return hres;
554 ReleaseBindInfo(&bindinfo);
556 len = lstrlenW(szUrl)+16;
557 url = heap_alloc(len*sizeof(WCHAR));
558 hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0);
559 if(FAILED(hres)) {
560 WARN("CoInternetParseUrl failed: %08x\n", hres);
561 heap_free(url);
562 IInternetProtocolSink_ReportResult(pOIProtSink, hres, 0, NULL);
563 return hres;
566 if(len < ARRAY_SIZE(wszRes) || memcmp(url, wszRes, sizeof(wszRes))) {
567 WARN("Wrong protocol of url: %s\n", debugstr_w(url));
568 IInternetProtocolSink_ReportResult(pOIProtSink, E_INVALIDARG, 0, NULL);
569 heap_free(url);
570 return E_INVALIDARG;
573 url_dll = url + ARRAY_SIZE(wszRes);
574 if(!(res_type = wcschr(url_dll, '/'))) {
575 WARN("wrong url: %s\n", debugstr_w(url));
576 IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL);
577 heap_free(url);
578 return MK_E_SYNTAX;
581 *res_type++ = 0;
582 if ((url_file = wcschr(res_type, '/'))) {
583 DWORD res_type_id;
584 WCHAR *endpoint;
585 *url_file++ = 0;
586 res_type_id = wcstol(res_type, &endpoint, 10);
587 if(!*endpoint)
588 res_type = MAKEINTRESOURCEW(res_type_id);
589 }else {
590 url_file = res_type;
591 res_type = MAKEINTRESOURCEW(RT_HTML);
592 alt_res_type = MAKEINTRESOURCEW(2110 /* RT_FILE */);
595 /* Ignore query and hash parts. */
596 if((ptr = wcschr(url_file, '?')))
597 *ptr = 0;
598 if(*url_file && (ptr = wcschr(url_file+1, '#')))
599 *ptr = 0;
601 hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE);
602 if(!hdll) {
603 WARN("Could not open dll: %s\n", debugstr_w(url_dll));
604 IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
605 heap_free(url);
606 return HRESULT_FROM_WIN32(GetLastError());
609 TRACE("trying to find resource type %s, name %s\n", debugstr_w(res_type), debugstr_w(url_file));
611 src = FindResourceW(hdll, url_file, res_type);
612 if(!src && alt_res_type)
613 src = FindResourceW(hdll, url_file, alt_res_type);
614 if(!src) {
615 LPWSTR endpoint = NULL;
616 DWORD file_id = wcstol(url_file, &endpoint, 10);
617 if(!*endpoint) {
618 src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), res_type);
619 if(!src && alt_res_type)
620 src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), alt_res_type);
622 if(!src) {
623 WARN("Could not find resource\n");
624 IInternetProtocolSink_ReportResult(pOIProtSink,
625 HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
626 heap_free(url);
627 return HRESULT_FROM_WIN32(GetLastError());
631 if(This->data) {
632 WARN("data already loaded\n");
633 heap_free(This->data);
636 This->data_len = SizeofResource(hdll, src);
637 This->data = heap_alloc(This->data_len);
638 memcpy(This->data, LoadResource(hdll, src), This->data_len);
639 This->cur = 0;
641 FreeLibrary(hdll);
643 hres = FindMimeFromData(NULL, url_file, This->data, This->data_len, NULL, 0, &mime, 0);
644 heap_free(url);
645 if(SUCCEEDED(hres)) {
646 IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
647 CoTaskMemFree(mime);
650 IInternetProtocolSink_ReportData(pOIProtSink,
651 BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
652 This->data_len, This->data_len);
654 IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
656 return S_OK;
659 static const IInternetProtocolVtbl ResProtocolVtbl = {
660 InternetProtocol_QueryInterface,
661 InternetProtocol_AddRef,
662 InternetProtocol_Release,
663 ResProtocol_Start,
664 InternetProtocol_Continue,
665 InternetProtocol_Abort,
666 InternetProtocol_Terminate,
667 InternetProtocol_Suspend,
668 InternetProtocol_Resume,
669 InternetProtocol_Read,
670 InternetProtocol_Seek,
671 InternetProtocol_LockRequest,
672 InternetProtocol_UnlockRequest
675 static HRESULT WINAPI ResProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
676 REFIID riid, void **ppv)
678 TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
680 return create_protocol_instance(&ResProtocolVtbl, pUnkOuter, riid, ppv);
683 static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
684 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
685 DWORD* pcchResult, DWORD dwReserved)
687 TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
688 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
690 if(ParseAction == PARSE_SECURITY_URL) {
691 WCHAR file_part[MAX_PATH], full_path[MAX_PATH];
692 WCHAR *ptr;
693 DWORD size, len;
695 static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
696 static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
698 if(lstrlenW(pwzUrl) <= ARRAY_SIZE(wszRes) || memcmp(pwzUrl, wszRes, sizeof(wszRes)))
699 return E_INVALIDARG;
701 ptr = wcschr(pwzUrl + ARRAY_SIZE(wszRes), '/');
702 if(!ptr)
703 return E_INVALIDARG;
705 len = ptr - (pwzUrl + ARRAY_SIZE(wszRes));
706 if(len >= ARRAY_SIZE(file_part)) {
707 FIXME("Too long URL\n");
708 return MK_E_SYNTAX;
711 memcpy(file_part, pwzUrl + ARRAY_SIZE(wszRes), len*sizeof(WCHAR));
712 file_part[len] = 0;
714 len = SearchPathW(NULL, file_part, NULL, ARRAY_SIZE(full_path), full_path, NULL);
715 if(!len) {
716 HMODULE module;
718 /* SearchPath does not work well with winelib files (like our test executable),
719 * so we also try to load the library here */
720 module = LoadLibraryExW(file_part, NULL, LOAD_LIBRARY_AS_DATAFILE);
721 if(!module) {
722 WARN("Could not find file %s\n", debugstr_w(file_part));
723 return MK_E_SYNTAX;
726 len = GetModuleFileNameW(module, full_path, ARRAY_SIZE(full_path));
727 FreeLibrary(module);
728 if(!len)
729 return E_FAIL;
732 size = ARRAY_SIZE(wszFile) + len + 1;
733 if(pcchResult)
734 *pcchResult = size;
735 if(size > cchResult)
736 return S_FALSE;
738 memcpy(pwzResult, wszFile, sizeof(wszFile));
739 memcpy(pwzResult + ARRAY_SIZE(wszFile), full_path, (len+1)*sizeof(WCHAR));
740 return S_OK;
743 if(ParseAction == PARSE_DOMAIN) {
744 if(!pcchResult)
745 return E_POINTER;
747 if(pwzUrl)
748 *pcchResult = lstrlenW(pwzUrl)+1;
749 else
750 *pcchResult = 1;
751 return E_FAIL;
754 return INET_E_DEFAULT_ACTION;
757 static HRESULT WINAPI ResProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
758 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
759 DWORD dwReserved)
761 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
762 cbBuffer, pcbBuf, dwReserved);
764 switch(QueryOption) {
765 case QUERY_USES_NETWORK:
766 if(!pBuffer || cbBuffer < sizeof(DWORD))
767 return E_FAIL;
769 *(DWORD*)pBuffer = 0;
770 if(pcbBuf)
771 *pcbBuf = sizeof(DWORD);
772 break;
774 case QUERY_IS_SECURE:
775 FIXME("QUERY_IS_SECURE not supported\n");
776 return E_NOTIMPL;
777 case QUERY_IS_SAFE:
778 FIXME("QUERY_IS_SAFE not supported\n");
779 return E_NOTIMPL;
780 default:
781 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
784 return S_OK;
787 static const IInternetProtocolInfoVtbl ResProtocolInfoVtbl = {
788 InternetProtocolInfo_QueryInterface,
789 InternetProtocolInfo_AddRef,
790 InternetProtocolInfo_Release,
791 ResProtocolInfo_ParseUrl,
792 InternetProtocolInfo_CombineUrl,
793 InternetProtocolInfo_CompareUrl,
794 ResProtocolInfo_QueryInfo
797 static const IClassFactoryVtbl ResProtocolFactoryVtbl = {
798 ClassFactory_QueryInterface,
799 ClassFactory_AddRef,
800 ClassFactory_Release,
801 ResProtocolFactory_CreateInstance,
802 ClassFactory_LockServer
805 static ProtocolFactory ResProtocolFactory = {
806 { &ResProtocolInfoVtbl },
807 { &ResProtocolFactoryVtbl }
810 /********************************************************************
811 * JSProtocol implementation
814 static HRESULT WINAPI JSProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
815 REFIID riid, void **ppv)
817 FIXME("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
818 return E_NOTIMPL;
821 static HRESULT WINAPI JSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
822 PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
823 DWORD* pcchResult, DWORD dwReserved)
825 TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
826 dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
828 switch(ParseAction) {
829 case PARSE_SECURITY_URL:
830 FIXME("PARSE_SECURITY_URL\n");
831 return E_NOTIMPL;
832 case PARSE_DOMAIN:
833 FIXME("PARSE_DOMAIN\n");
834 return E_NOTIMPL;
835 default:
836 return INET_E_DEFAULT_ACTION;
839 return S_OK;
842 static HRESULT WINAPI JSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
843 QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
844 DWORD dwReserved)
846 TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
847 cbBuffer, pcbBuf, dwReserved);
849 switch(QueryOption) {
850 case QUERY_USES_NETWORK:
851 if(!pBuffer || cbBuffer < sizeof(DWORD))
852 return E_FAIL;
854 *(DWORD*)pBuffer = 0;
855 if(pcbBuf)
856 *pcbBuf = sizeof(DWORD);
857 break;
859 case QUERY_IS_SECURE:
860 FIXME("QUERY_IS_SECURE not supported\n");
861 return E_NOTIMPL;
863 default:
864 return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
867 return S_OK;
870 static const IInternetProtocolInfoVtbl JSProtocolInfoVtbl = {
871 InternetProtocolInfo_QueryInterface,
872 InternetProtocolInfo_AddRef,
873 InternetProtocolInfo_Release,
874 JSProtocolInfo_ParseUrl,
875 InternetProtocolInfo_CombineUrl,
876 InternetProtocolInfo_CompareUrl,
877 JSProtocolInfo_QueryInfo
880 static const IClassFactoryVtbl JSProtocolFactoryVtbl = {
881 ClassFactory_QueryInterface,
882 ClassFactory_AddRef,
883 ClassFactory_Release,
884 JSProtocolFactory_CreateInstance,
885 ClassFactory_LockServer
888 static ProtocolFactory JSProtocolFactory = {
889 { &JSProtocolInfoVtbl },
890 { &JSProtocolFactoryVtbl }
893 HRESULT ProtocolFactory_Create(REFCLSID rclsid, REFIID riid, void **ppv)
895 ProtocolFactory *cf = NULL;
897 if(IsEqualGUID(&CLSID_AboutProtocol, rclsid))
898 cf = &AboutProtocolFactory;
899 else if(IsEqualGUID(&CLSID_ResProtocol, rclsid))
900 cf = &ResProtocolFactory;
901 else if(IsEqualGUID(&CLSID_JSProtocol, rclsid))
902 cf = &JSProtocolFactory;
904 if(!cf) {
905 FIXME("not implemented protocol %s\n", debugstr_guid(rclsid));
906 return CLASS_E_CLASSNOTAVAILABLE;
909 return IInternetProtocolInfo_QueryInterface(&cf->IInternetProtocolInfo_iface, riid, ppv);