Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056/* * Copyright 2005 Jacek Caban * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
#include "mshtml_private.h"
/******************************************************************** * common ProtocolFactory implementation */
typedef struct { IInternetProtocolInfo IInternetProtocolInfo_iface; IClassFactory IClassFactory_iface;} ProtocolFactory;
static inline ProtocolFactory *impl_from_IInternetProtocolInfo(IInternetProtocolInfo *iface){ return CONTAINING_RECORD(iface, ProtocolFactory, IInternetProtocolInfo_iface);}
static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv){ ProtocolFactory *This = impl_from_IInternetProtocolInfo(iface);
*ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); *ppv = &This->IInternetProtocolInfo_iface; }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) { TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv); *ppv = &This->IInternetProtocolInfo_iface; }else if(IsEqualGUID(&IID_IClassFactory, riid)) { TRACE("(%p)->(IID_IClassFactory %p)\n", This, ppv); *ppv = &This->IClassFactory_iface; }
if(!*ppv) { WARN("unknown interface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; }
IInternetProtocolInfo_AddRef(iface); return S_OK;}
static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface){ TRACE("(%p)\n", iface); return 2;}
static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface){ TRACE("(%p)\n", iface); return 1;}
static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface, LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, DWORD cchResult, DWORD* pcchResult, DWORD dwReserved){ TRACE("%p)->(%s %s %08x %p %d %p %d)\n", iface, debugstr_w(pwzBaseUrl), debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult, pcchResult, dwReserved);
return INET_E_USE_DEFAULT_PROTOCOLHANDLER;}
static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags){ TRACE("%p)->(%s %s %08x)\n", iface, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags); return E_NOTIMPL;}
static inline ProtocolFactory *impl_from_IClassFactory(IClassFactory *iface){ return CONTAINING_RECORD(iface, ProtocolFactory, IClassFactory_iface);}
static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv){ ProtocolFactory *This = impl_from_IClassFactory(iface); return IInternetProtocolInfo_QueryInterface(&This->IInternetProtocolInfo_iface, riid, ppv);}
static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface){ ProtocolFactory *This = impl_from_IClassFactory(iface); return IInternetProtocolInfo_AddRef(&This->IInternetProtocolInfo_iface);}
static ULONG WINAPI ClassFactory_Release(IClassFactory *iface){ ProtocolFactory *This = impl_from_IClassFactory(iface); return IInternetProtocolInfo_Release(&This->IInternetProtocolInfo_iface);}
static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock){ TRACE("(%p)->(%x)\n", iface, dolock); return S_OK;}
/******************************************************************** * AboutProtocol implementation */
typedef struct { IInternetProtocol IInternetProtocol_iface;
LONG ref;
BYTE *data; ULONG data_len; ULONG cur;
IUnknown *pUnkOuter;} AboutProtocol;
static inline AboutProtocol *AboutProtocol_from_IInternetProtocol(IInternetProtocol *iface){ return CONTAINING_RECORD(iface, AboutProtocol, IInternetProtocol_iface);}
static HRESULT WINAPI AboutProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface);
*ppv = NULL;
if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); if(This->pUnkOuter) return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); *ppv = &This->IInternetProtocol_iface; }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv); *ppv = &This->IInternetProtocol_iface; }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv); *ppv = &This->IInternetProtocol_iface; }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { FIXME("IServiceProvider is not implemented\n"); return E_NOINTERFACE; }
if(!*ppv) { TRACE("unknown interface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; }
IInternetProtocol_AddRef(iface); return S_OK;}
static ULONG WINAPI AboutProtocol_AddRef(IInternetProtocol *iface){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", iface, ref); return This->pUnkOuter ? IUnknown_AddRef(This->pUnkOuter) : ref;}
static ULONG WINAPI AboutProtocol_Release(IInternetProtocol *iface){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); IUnknown *pUnkOuter = This->pUnkOuter; ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%x\n", iface, ref);
if(!ref) { heap_free(This->data); heap_free(This); }
return pUnkOuter ? IUnknown_Release(pUnkOuter) : ref;}
static HRESULT WINAPI AboutProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); BINDINFO bindinfo; DWORD grfBINDF = 0; LPCWSTR text = NULL; DWORD data_len; BYTE *data; HRESULT hres;
static const WCHAR html_begin[] = {0xfeff,'<','H','T','M','L','>',0}; static const WCHAR html_end[] = {'<','/','H','T','M','L','>',0}; static const WCHAR wszBlank[] = {'b','l','a','n','k',0}; static const WCHAR wszAbout[] = {'a','b','o','u','t',':'}; static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
/* NOTE: * the about protocol seems not to work as I would expect. It creates html document * for a given url, eg. about:some_text -> <HTML>some_text</HTML> except for the case when * some_text = "blank", when document is blank (<HTML></HMTL>). The same happens * when the url does not have "about:" in the beginning. */
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved);
memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo); if(FAILED(hres)) return hres; ReleaseBindInfo(&bindinfo);
TRACE("bindf %x\n", grfBINDF);
if(strlenW(szUrl)>=sizeof(wszAbout)/sizeof(WCHAR) && !memcmp(wszAbout, szUrl, sizeof(wszAbout))) { text = szUrl + sizeof(wszAbout)/sizeof(WCHAR); if(!strcmpW(wszBlank, text)) text = NULL; }
data_len = sizeof(html_begin)+sizeof(html_end)-sizeof(WCHAR) + (text ? strlenW(text)*sizeof(WCHAR) : 0); data = heap_alloc(data_len); if(!data) return E_OUTOFMEMORY;
heap_free(This->data); This->data = data; This->data_len = data_len;
memcpy(This->data, html_begin, sizeof(html_begin)); if(text) strcatW((LPWSTR)This->data, text); strcatW((LPWSTR)This->data, html_end); This->cur = 0;
IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, wszTextHtml);
IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, This->data_len, This->data_len);
IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
return S_OK;}
static HRESULT WINAPI AboutProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); FIXME("(%p)->(%p)\n", This, pProtocolData); return E_NOTIMPL;}
static HRESULT WINAPI AboutProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, DWORD dwOptions){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); return E_NOTIMPL;}
static HRESULT WINAPI AboutProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); return S_OK;}
static HRESULT WINAPI AboutProtocol_Suspend(IInternetProtocol *iface){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); FIXME("(%p)\n", This); return E_NOTIMPL;}
static HRESULT WINAPI AboutProtocol_Resume(IInternetProtocol *iface){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); FIXME("(%p)\n", This); return E_NOTIMPL;}
static HRESULT WINAPI AboutProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface);
TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
if(!This->data) return E_FAIL;
*pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
if(!*pcbRead) return S_FALSE;
memcpy(pv, This->data+This->cur, *pcbRead); This->cur += *pcbRead;
return S_OK;}
static HRESULT WINAPI AboutProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface); FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); return E_NOTIMPL;}
static HRESULT WINAPI AboutProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface);
TRACE("(%p)->(%d)\n", This, dwOptions);
return S_OK;}
static HRESULT WINAPI AboutProtocol_UnlockRequest(IInternetProtocol *iface){ AboutProtocol *This = AboutProtocol_from_IInternetProtocol(iface);
TRACE("(%p)\n", This);
return S_OK;}
static const IInternetProtocolVtbl AboutProtocolVtbl = { AboutProtocol_QueryInterface, AboutProtocol_AddRef, AboutProtocol_Release, AboutProtocol_Start, AboutProtocol_Continue, AboutProtocol_Abort, AboutProtocol_Terminate, AboutProtocol_Suspend, AboutProtocol_Resume, AboutProtocol_Read, AboutProtocol_Seek, AboutProtocol_LockRequest, AboutProtocol_UnlockRequest};
static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv){ AboutProtocol *ret; HRESULT hres = S_OK;
TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
ret = heap_alloc(sizeof(AboutProtocol)); ret->IInternetProtocol_iface.lpVtbl = &AboutProtocolVtbl; ret->ref = 0;
ret->data = NULL; ret->data_len = 0; ret->cur = 0; ret->pUnkOuter = pUnkOuter;
if(pUnkOuter) { ret->ref = 1; if(IsEqualGUID(&IID_IUnknown, riid)) *ppv = &ret->IInternetProtocol_iface; else hres = E_INVALIDARG; }else { hres = IInternetProtocol_QueryInterface(&ret->IInternetProtocol_iface, riid, ppv); }
if(FAILED(hres)) heap_free(ret);
return hres;}
static HRESULT WINAPI AboutProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD* pcchResult, DWORD dwReserved){ TRACE("%p)->(%s %d %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction, dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
if(ParseAction == PARSE_SECURITY_URL) { unsigned int len = strlenW(pwzUrl)+1;
*pcchResult = len; if(len > cchResult) return S_FALSE;
memcpy(pwzResult, pwzUrl, len*sizeof(WCHAR)); return S_OK; }
if(ParseAction == PARSE_DOMAIN) { if(!pcchResult) return E_POINTER;
if(pwzUrl) *pcchResult = strlenW(pwzUrl)+1; else *pcchResult = 1; return E_FAIL; }
return INET_E_DEFAULT_ACTION;}
static HRESULT WINAPI AboutProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf, DWORD dwReserved){ TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer, cbBuffer, pcbBuf, dwReserved);
switch(QueryOption) { case QUERY_CAN_NAVIGATE: return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
case QUERY_USES_NETWORK: if(!pBuffer || cbBuffer < sizeof(DWORD)) return E_FAIL;
*(DWORD*)pBuffer = 0; if(pcbBuf) *pcbBuf = sizeof(DWORD);
break;
case QUERY_IS_CACHED: FIXME("Unsupported option QUERY_IS_CACHED\n"); return E_NOTIMPL; case QUERY_IS_INSTALLEDENTRY: FIXME("Unsupported option QUERY_IS_INSTALLEDENTRY\n"); return E_NOTIMPL; case QUERY_IS_CACHED_OR_MAPPED: FIXME("Unsupported option QUERY_IS_CACHED_OR_MAPPED\n"); return E_NOTIMPL; case QUERY_IS_SECURE: FIXME("Unsupported option QUERY_IS_SECURE\n"); return E_NOTIMPL; case QUERY_IS_SAFE: FIXME("Unsupported option QUERY_IS_SAFE\n"); return E_NOTIMPL; case QUERY_USES_HISTORYFOLDER: FIXME("Unsupported option QUERY_USES_HISTORYFOLDER\n"); return E_FAIL; case QUERY_IS_CACHED_AND_USABLE_OFFLINE: FIXME("Unsupported option QUERY_IS_CACHED_AND_USABLE_OFFLINE\n"); return E_NOTIMPL; default: return E_FAIL; }
return S_OK;}
static const IInternetProtocolInfoVtbl AboutProtocolInfoVtbl = { InternetProtocolInfo_QueryInterface, InternetProtocolInfo_AddRef, InternetProtocolInfo_Release, AboutProtocolInfo_ParseUrl, InternetProtocolInfo_CombineUrl, InternetProtocolInfo_CompareUrl, AboutProtocolInfo_QueryInfo};
static const IClassFactoryVtbl AboutProtocolFactoryVtbl = { ClassFactory_QueryInterface, ClassFactory_AddRef, ClassFactory_Release, AboutProtocolFactory_CreateInstance, ClassFactory_LockServer};
static ProtocolFactory AboutProtocolFactory = { { &AboutProtocolInfoVtbl }, { &AboutProtocolFactoryVtbl }};
/******************************************************************** * ResProtocol implementation */
typedef struct { IInternetProtocol IInternetProtocol_iface; LONG ref;
BYTE *data; ULONG data_len; ULONG cur;
IUnknown *pUnkOuter;} ResProtocol;
static inline ResProtocol *ResProtocol_from_IInternetProtocol(IInternetProtocol *iface){ return CONTAINING_RECORD(iface, ResProtocol, IInternetProtocol_iface);}
static HRESULT WINAPI ResProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface);
*ppv = NULL;
if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv); if(This->pUnkOuter) return IUnknown_QueryInterface(This->pUnkOuter, &IID_IUnknown, ppv); *ppv = &This->IInternetProtocol_iface; }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv); *ppv = &This->IInternetProtocol_iface; }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv); *ppv = &This->IInternetProtocol_iface; }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { FIXME("IServiceProvider is not implemented\n"); return E_NOINTERFACE; }
if(!*ppv) { TRACE("unknown interface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; }
IInternetProtocol_AddRef(iface); return S_OK;}
static ULONG WINAPI ResProtocol_AddRef(IInternetProtocol *iface){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", iface, ref); return This->pUnkOuter ? IUnknown_AddRef(This->pUnkOuter) : ref;}
static ULONG WINAPI ResProtocol_Release(IInternetProtocol *iface){ ResProtocol *This = (ResProtocol*)iface; IUnknown *pUnkOuter = This->pUnkOuter; ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%x\n", iface, ref);
if(!ref) { heap_free(This->data); heap_free(This); }
return pUnkOuter ? IUnknown_Release(pUnkOuter) : ref;}
static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); WCHAR *url_dll, *url_file, *url, *mime, *res_type = (LPWSTR)RT_HTML, *ptr; DWORD grfBINDF = 0, len; BINDINFO bindinfo; HMODULE hdll; HRSRC src; HRESULT hres;
static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved);
memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo); if(FAILED(hres)) return hres; ReleaseBindInfo(&bindinfo);
len = strlenW(szUrl)+16; url = heap_alloc(len*sizeof(WCHAR)); hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0); if(FAILED(hres)) { WARN("CoInternetParseUrl failed: %08x\n", hres); heap_free(url); IInternetProtocolSink_ReportResult(pOIProtSink, hres, 0, NULL); return hres; }
if(len < sizeof(wszRes)/sizeof(wszRes[0]) || memcmp(url, wszRes, sizeof(wszRes))) { WARN("Wrong protocol of url: %s\n", debugstr_w(url)); IInternetProtocolSink_ReportResult(pOIProtSink, E_INVALIDARG, 0, NULL); heap_free(url); return E_INVALIDARG; }
url_dll = url + sizeof(wszRes)/sizeof(wszRes[0]); if(!(res_type = strchrW(url_dll, '/'))) { WARN("wrong url: %s\n", debugstr_w(url)); IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL); heap_free(url); return MK_E_SYNTAX; }
*res_type++ = 0; if ((url_file = strchrW(res_type, '/'))) { *url_file++ = 0; }else { url_file = res_type; res_type = (LPWSTR)RT_HTML; }
/* Ignore query and hash parts. */ if((ptr = strchrW(url_file, '?'))) *ptr = 0; if(*url_file && (ptr = strchrW(url_file+1, '#'))) *ptr = 0;
hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE); if(!hdll) { WARN("Could not open dll: %s\n", debugstr_w(url_dll)); IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL); heap_free(url); return HRESULT_FROM_WIN32(GetLastError()); }
TRACE("trying to find resource type %s, name %s\n", debugstr_w(res_type), debugstr_w(url_file));
src = FindResourceW(hdll, url_file, res_type); if(!src) { LPWSTR endpoint = NULL; DWORD file_id = strtolW(url_file, &endpoint, 10); if(endpoint == url_file+strlenW(url_file)) src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), res_type);
if(!src) { WARN("Could not find resource\n"); IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL); heap_free(url); return HRESULT_FROM_WIN32(GetLastError()); } }
if(This->data) { WARN("data already loaded\n"); heap_free(This->data); }
This->data_len = SizeofResource(hdll, src); This->data = heap_alloc(This->data_len); memcpy(This->data, LoadResource(hdll, src), This->data_len); This->cur = 0;
FreeLibrary(hdll);
hres = FindMimeFromData(NULL, url_file, This->data, This->data_len, NULL, 0, &mime, 0); heap_free(url); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); }
IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, This->data_len, This->data_len);
IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL); return S_OK;}
static HRESULT WINAPI ResProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); FIXME("(%p)->(%p)\n", This, pProtocolData); return E_NOTIMPL;}
static HRESULT WINAPI ResProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, DWORD dwOptions){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); return E_NOTIMPL;}
static HRESULT WINAPI ResProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface);
TRACE("(%p)->(%08x)\n", This, dwOptions);
/* test show that we don't have to do anything here */ return S_OK;}
static HRESULT WINAPI ResProtocol_Suspend(IInternetProtocol *iface){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); FIXME("(%p)\n", This); return E_NOTIMPL;}
static HRESULT WINAPI ResProtocol_Resume(IInternetProtocol *iface){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); FIXME("(%p)\n", This); return E_NOTIMPL;}
static HRESULT WINAPI ResProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface);
TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
if(!This->data) return E_FAIL;
*pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
if(!*pcbRead) return S_FALSE;
memcpy(pv, This->data+This->cur, *pcbRead); This->cur += *pcbRead;
return S_OK;}
static HRESULT WINAPI ResProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); return E_NOTIMPL;}
static HRESULT WINAPI ResProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface);
TRACE("(%p)->(%d)\n", This, dwOptions);
/* test show that we don't have to do anything here */ return S_OK;}
static HRESULT WINAPI ResProtocol_UnlockRequest(IInternetProtocol *iface){ ResProtocol *This = ResProtocol_from_IInternetProtocol(iface);
TRACE("(%p)\n", This);
/* test show that we don't have to do anything here */ return S_OK;}
static const IInternetProtocolVtbl ResProtocolVtbl = { ResProtocol_QueryInterface, ResProtocol_AddRef, ResProtocol_Release, ResProtocol_Start, ResProtocol_Continue, ResProtocol_Abort, ResProtocol_Terminate, ResProtocol_Suspend, ResProtocol_Resume, ResProtocol_Read, ResProtocol_Seek, ResProtocol_LockRequest, ResProtocol_UnlockRequest};
static HRESULT WINAPI ResProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv){ ResProtocol *ret; HRESULT hres = S_OK;
TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
ret = heap_alloc(sizeof(ResProtocol)); ret->IInternetProtocol_iface.lpVtbl = &ResProtocolVtbl; ret->ref = 0; ret->data = NULL; ret->data_len = 0; ret->cur = 0; ret->pUnkOuter = pUnkOuter;
if(pUnkOuter) { ret->ref = 1; if(IsEqualGUID(&IID_IUnknown, riid)) *ppv = &ret->IInternetProtocol_iface; else hres = E_FAIL; }else { hres = IInternetProtocol_QueryInterface(&ret->IInternetProtocol_iface, riid, ppv); }
if(FAILED(hres)) heap_free(ret);
return hres;}
static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD* pcchResult, DWORD dwReserved){ TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction, dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
if(ParseAction == PARSE_SECURITY_URL) { WCHAR file_part[MAX_PATH], full_path[MAX_PATH]; WCHAR *ptr; DWORD size, len;
static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'}; static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
if(strlenW(pwzUrl) <= sizeof(wszRes)/sizeof(WCHAR) || memcmp(pwzUrl, wszRes, sizeof(wszRes))) return E_INVALIDARG;
ptr = strchrW(pwzUrl + sizeof(wszRes)/sizeof(WCHAR), '/'); if(!ptr) return E_INVALIDARG;
len = ptr - (pwzUrl + sizeof(wszRes)/sizeof(WCHAR)); if(len >= sizeof(file_part)/sizeof(WCHAR)) { FIXME("Too long URL\n"); return MK_E_SYNTAX; }
memcpy(file_part, pwzUrl + sizeof(wszRes)/sizeof(WCHAR), len*sizeof(WCHAR)); file_part[len] = 0;
len = SearchPathW(NULL, file_part, NULL, sizeof(full_path)/sizeof(WCHAR), full_path, NULL); if(!len) { HMODULE module;
/* SearchPath does not work well with winelib files (like our test executable), * so we also try to load the library here */ module = LoadLibraryExW(file_part, NULL, LOAD_LIBRARY_AS_DATAFILE); if(!module) { WARN("Could not find file %s\n", debugstr_w(file_part)); return MK_E_SYNTAX; }
len = GetModuleFileNameW(module, full_path, sizeof(full_path)/sizeof(WCHAR)); FreeLibrary(module); if(!len) return E_FAIL; }
size = sizeof(wszFile)/sizeof(WCHAR) + len + 1; if(pcchResult) *pcchResult = size; if(size > cchResult) return S_FALSE;
memcpy(pwzResult, wszFile, sizeof(wszFile)); memcpy(pwzResult + sizeof(wszFile)/sizeof(WCHAR), full_path, (len+1)*sizeof(WCHAR)); return S_OK; }
if(ParseAction == PARSE_DOMAIN) { if(!pcchResult) return E_POINTER;
if(pwzUrl) *pcchResult = strlenW(pwzUrl)+1; else *pcchResult = 1; return E_FAIL; }
return INET_E_DEFAULT_ACTION;}
static HRESULT WINAPI ResProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf, DWORD dwReserved){ TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer, cbBuffer, pcbBuf, dwReserved);
switch(QueryOption) { case QUERY_USES_NETWORK: if(!pBuffer || cbBuffer < sizeof(DWORD)) return E_FAIL;
*(DWORD*)pBuffer = 0; if(pcbBuf) *pcbBuf = sizeof(DWORD); break;
case QUERY_IS_SECURE: FIXME("QUERY_IS_SECURE not supported\n"); return E_NOTIMPL; case QUERY_IS_SAFE: FIXME("QUERY_IS_SAFE not supported\n"); return E_NOTIMPL; default: return INET_E_USE_DEFAULT_PROTOCOLHANDLER; }
return S_OK;}
static const IInternetProtocolInfoVtbl ResProtocolInfoVtbl = { InternetProtocolInfo_QueryInterface, InternetProtocolInfo_AddRef, InternetProtocolInfo_Release, ResProtocolInfo_ParseUrl, InternetProtocolInfo_CombineUrl, InternetProtocolInfo_CompareUrl, ResProtocolInfo_QueryInfo};
static const IClassFactoryVtbl ResProtocolFactoryVtbl = { ClassFactory_QueryInterface, ClassFactory_AddRef, ClassFactory_Release, ResProtocolFactory_CreateInstance, ClassFactory_LockServer};
static ProtocolFactory ResProtocolFactory = { { &ResProtocolInfoVtbl }, { &ResProtocolFactoryVtbl }};
/******************************************************************** * JSProtocol implementation */
static HRESULT WINAPI JSProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter, REFIID riid, void **ppv){ FIXME("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv); return E_NOTIMPL;}
static HRESULT WINAPI JSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, DWORD* pcchResult, DWORD dwReserved){ TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction, dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
switch(ParseAction) { case PARSE_SECURITY_URL: FIXME("PARSE_SECURITY_URL\n"); return E_NOTIMPL; case PARSE_DOMAIN: FIXME("PARSE_DOMAIN\n"); return E_NOTIMPL; default: return INET_E_DEFAULT_ACTION; }
return S_OK;}
static HRESULT WINAPI JSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf, DWORD dwReserved){ TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer, cbBuffer, pcbBuf, dwReserved);
switch(QueryOption) { case QUERY_USES_NETWORK: if(!pBuffer || cbBuffer < sizeof(DWORD)) return E_FAIL;
*(DWORD*)pBuffer = 0; if(pcbBuf) *pcbBuf = sizeof(DWORD); break;
case QUERY_IS_SECURE: FIXME("QUERY_IS_SECURE not supported\n"); return E_NOTIMPL;
default: return INET_E_USE_DEFAULT_PROTOCOLHANDLER; }
return S_OK;}
static const IInternetProtocolInfoVtbl JSProtocolInfoVtbl = { InternetProtocolInfo_QueryInterface, InternetProtocolInfo_AddRef, InternetProtocolInfo_Release, JSProtocolInfo_ParseUrl, InternetProtocolInfo_CombineUrl, InternetProtocolInfo_CompareUrl, JSProtocolInfo_QueryInfo};
static const IClassFactoryVtbl JSProtocolFactoryVtbl = { ClassFactory_QueryInterface, ClassFactory_AddRef, ClassFactory_Release, JSProtocolFactory_CreateInstance, ClassFactory_LockServer};
static ProtocolFactory JSProtocolFactory = { { &JSProtocolInfoVtbl }, { &JSProtocolFactoryVtbl }};
HRESULT ProtocolFactory_Create(REFCLSID rclsid, REFIID riid, void **ppv){ ProtocolFactory *cf = NULL;
if(IsEqualGUID(&CLSID_AboutProtocol, rclsid)) cf = &AboutProtocolFactory; else if(IsEqualGUID(&CLSID_ResProtocol, rclsid)) cf = &ResProtocolFactory; else if(IsEqualGUID(&CLSID_JSProtocol, rclsid)) cf = &JSProtocolFactory;
if(!cf) { FIXME("not implemented protocol %s\n", debugstr_guid(rclsid)); return CLASS_E_CLASSNOTAVAILABLE; } return IInternetProtocolInfo_QueryInterface(&cf->IInternetProtocolInfo_iface, riid, ppv);}