ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

protocol.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2005 Jacek Caban
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include "config.h"
00020 
00021 #include <stdarg.h>
00022 #include <stdio.h>
00023 
00024 #define COBJMACROS
00025 
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winuser.h"
00029 #include "ole2.h"
00030 
00031 #include "wine/debug.h"
00032 #include "wine/unicode.h"
00033 
00034 #include "mshtml_private.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
00037 
00038 /********************************************************************
00039  * common ProtocolFactory implementation
00040  */
00041 
00042 #define CLASSFACTORY(x) (&(x)->lpClassFactoryVtbl)
00043 #define PROTOCOL(x)     ((IInternetProtocol*)     &(x)->lpInternetProtocolVtbl)
00044 #define PROTOCOLINFO(x) ((IInternetProtocolInfo*) &(x)->lpInternetProtocolInfoVtbl)
00045 
00046 typedef struct {
00047     const IInternetProtocolInfoVtbl *lpInternetProtocolInfoVtbl;
00048     const IClassFactoryVtbl         *lpClassFactoryVtbl;
00049 } ProtocolFactory;
00050 
00051 #define PROTOCOLINFO_THIS(iface) DEFINE_THIS(ProtocolFactory, InternetProtocolInfo, iface)
00052 
00053 static HRESULT WINAPI InternetProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, REFIID riid, void **ppv)
00054 {
00055     ProtocolFactory *This = PROTOCOLINFO_THIS(iface);
00056 
00057     *ppv = NULL;
00058     if(IsEqualGUID(&IID_IUnknown, riid)) {
00059         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
00060         *ppv = PROTOCOLINFO(This);
00061     }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
00062         TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
00063         *ppv = PROTOCOLINFO(This);
00064     }else if(IsEqualGUID(&IID_IClassFactory, riid)) {
00065         TRACE("(%p)->(IID_IClassFactory %p)\n", This, ppv);
00066         *ppv = CLASSFACTORY(This);
00067     }
00068 
00069     if(!*ppv) {
00070         WARN("unknown interface %s\n", debugstr_guid(riid));
00071         return E_NOINTERFACE;
00072     }
00073 
00074     IInternetProtocolInfo_AddRef(iface);
00075     return S_OK;
00076 }
00077 
00078 static ULONG WINAPI InternetProtocolInfo_AddRef(IInternetProtocolInfo *iface)
00079 {
00080     TRACE("(%p)\n", iface);
00081     return 2;
00082 }
00083 
00084 static ULONG WINAPI InternetProtocolInfo_Release(IInternetProtocolInfo *iface)
00085 {
00086     TRACE("(%p)\n", iface);
00087     return 1;
00088 }
00089 
00090 static HRESULT WINAPI InternetProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
00091         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult,
00092         DWORD cchResult, DWORD* pcchResult, DWORD dwReserved)
00093 {
00094     TRACE("%p)->(%s %s %08x %p %d %p %d)\n", iface, debugstr_w(pwzBaseUrl),
00095             debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult,
00096             pcchResult, dwReserved);
00097 
00098     return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
00099 }
00100 
00101 static HRESULT WINAPI InternetProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
00102         LPCWSTR pwzUrl2, DWORD dwCompareFlags)
00103 {
00104     TRACE("%p)->(%s %s %08x)\n", iface, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
00105     return E_NOTIMPL;
00106 }
00107 
00108 #undef PROTOCOLINFO_THIS
00109 
00110 #define CLASSFACTORY_THIS(iface) DEFINE_THIS(ProtocolFactory, ClassFactory, iface)
00111 
00112 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
00113 {
00114     ProtocolFactory *This = CLASSFACTORY_THIS(iface);
00115     return IInternetProtocolInfo_QueryInterface(PROTOCOLINFO(This), riid, ppv);
00116 }
00117 
00118 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
00119 {
00120     ProtocolFactory *This = CLASSFACTORY_THIS(iface);
00121     return IInternetProtocolInfo_AddRef(PROTOCOLINFO(This));
00122 }
00123 
00124 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
00125 {
00126     ProtocolFactory *This = CLASSFACTORY_THIS(iface);
00127     return IInternetProtocolInfo_Release(PROTOCOLINFO(This));
00128 }
00129 
00130 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
00131 {
00132     TRACE("(%p)->(%x)\n", iface, dolock);
00133     return S_OK;
00134 }
00135 
00136 #undef CLASSFACTORY_THIS
00137 
00138 /********************************************************************
00139  * AboutProtocol implementation
00140  */
00141 
00142 typedef struct {
00143     const IInternetProtocolVtbl *lpInternetProtocolVtbl;
00144 
00145     LONG ref;
00146 
00147     BYTE *data;
00148     ULONG data_len;
00149     ULONG cur;
00150 
00151     IUnknown *pUnkOuter;
00152 } AboutProtocol;
00153 
00154 #define PROTOCOL_THIS(iface) DEFINE_THIS(AboutProtocol, InternetProtocol, iface)
00155 
00156 static HRESULT WINAPI AboutProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
00157 {
00158     AboutProtocol *This = PROTOCOL_THIS(iface);
00159 
00160     *ppv = NULL;
00161 
00162     if(IsEqualGUID(&IID_IUnknown, riid)) {
00163         TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
00164         if(This->pUnkOuter)
00165             return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
00166         *ppv = PROTOCOL(This);
00167     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
00168         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv);
00169         *ppv = PROTOCOL(This);
00170     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
00171         TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv);
00172         *ppv = PROTOCOL(This);
00173     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
00174         FIXME("IServiceProvider is not implemented\n");
00175         return E_NOINTERFACE;
00176     }
00177 
00178     if(!*ppv) {
00179         TRACE("unknown interface %s\n", debugstr_guid(riid));
00180         return E_NOINTERFACE;
00181     }
00182 
00183     IInternetProtocol_AddRef(iface);
00184     return S_OK;
00185 }
00186 
00187 static ULONG WINAPI AboutProtocol_AddRef(IInternetProtocol *iface)
00188 {
00189     AboutProtocol *This = PROTOCOL_THIS(iface);
00190     ULONG ref = InterlockedIncrement(&This->ref);
00191     TRACE("(%p) ref=%d\n", iface, ref);
00192     return This->pUnkOuter ? IUnknown_AddRef(This->pUnkOuter) : ref;
00193 }
00194 
00195 static ULONG WINAPI AboutProtocol_Release(IInternetProtocol *iface)
00196 {
00197     AboutProtocol *This = PROTOCOL_THIS(iface);
00198     IUnknown *pUnkOuter = This->pUnkOuter;
00199     ULONG ref = InterlockedDecrement(&This->ref);
00200 
00201     TRACE("(%p) ref=%x\n", iface, ref);
00202 
00203     if(!ref) {
00204         heap_free(This->data);
00205         heap_free(This);
00206     }
00207 
00208     return pUnkOuter ? IUnknown_Release(pUnkOuter) : ref;
00209 }
00210 
00211 static HRESULT WINAPI AboutProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
00212         IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
00213         DWORD grfPI, HANDLE_PTR dwReserved)
00214 {
00215     AboutProtocol *This = PROTOCOL_THIS(iface);
00216     BINDINFO bindinfo;
00217     DWORD grfBINDF = 0;
00218     LPCWSTR text = NULL;
00219 
00220     static const WCHAR html_begin[] = {0xfeff,'<','H','T','M','L','>',0};
00221     static const WCHAR html_end[] = {'<','/','H','T','M','L','>',0};
00222     static const WCHAR wszBlank[] = {'b','l','a','n','k',0};
00223     static const WCHAR wszAbout[] = {'a','b','o','u','t',':'};
00224     static const WCHAR wszTextHtml[] = {'t','e','x','t','/','h','t','m','l',0};
00225 
00226     /* NOTE:
00227      * the about protocol seems not to work as I would expect. It creates html document
00228      * for a given url, eg. about:some_text -> <HTML>some_text</HTML> except for the case when
00229      * some_text = "blank", when document is blank (<HTML></HMTL>). The same happens
00230      * when the url does not have "about:" in the beginning.
00231      */
00232 
00233     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
00234             pOIBindInfo, grfPI, dwReserved);
00235 
00236     memset(&bindinfo, 0, sizeof(bindinfo));
00237     bindinfo.cbSize = sizeof(BINDINFO);
00238     IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
00239     ReleaseBindInfo(&bindinfo);
00240 
00241     TRACE("bindf %x\n", grfBINDF);
00242 
00243     if(strlenW(szUrl)>=sizeof(wszAbout)/sizeof(WCHAR) && !memcmp(wszAbout, szUrl, sizeof(wszAbout))) {
00244         text = szUrl + sizeof(wszAbout)/sizeof(WCHAR);
00245         if(!strcmpW(wszBlank, text))
00246             text = NULL;
00247     }
00248 
00249     This->data_len = sizeof(html_begin)+sizeof(html_end)-sizeof(WCHAR) 
00250         + (text ? strlenW(text)*sizeof(WCHAR) : 0);
00251     This->data = heap_alloc(This->data_len);
00252 
00253     memcpy(This->data, html_begin, sizeof(html_begin));
00254     if(text)
00255         strcatW((LPWSTR)This->data, text);
00256     strcatW((LPWSTR)This->data, html_end);
00257     
00258     This->cur = 0;
00259 
00260     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, wszTextHtml);
00261 
00262     IInternetProtocolSink_ReportData(pOIProtSink,
00263             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
00264             This->data_len, This->data_len);
00265 
00266     IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
00267 
00268     return S_OK;
00269 }
00270 
00271 static HRESULT WINAPI AboutProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
00272 {
00273     AboutProtocol *This = PROTOCOL_THIS(iface);
00274     FIXME("(%p)->(%p)\n", This, pProtocolData);
00275     return E_NOTIMPL;
00276 }
00277 
00278 static HRESULT WINAPI AboutProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
00279         DWORD dwOptions)
00280 {
00281     AboutProtocol *This = PROTOCOL_THIS(iface);
00282     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
00283     return E_NOTIMPL;
00284 }
00285 
00286 static HRESULT WINAPI AboutProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
00287 {
00288     AboutProtocol *This = PROTOCOL_THIS(iface);
00289     TRACE("(%p)->(%08x)\n", This, dwOptions);
00290     return S_OK;
00291 }
00292 
00293 static HRESULT WINAPI AboutProtocol_Suspend(IInternetProtocol *iface)
00294 {
00295     AboutProtocol *This = PROTOCOL_THIS(iface);
00296     FIXME("(%p)\n", This);
00297     return E_NOTIMPL;
00298 }
00299 
00300 static HRESULT WINAPI AboutProtocol_Resume(IInternetProtocol *iface)
00301 {
00302     AboutProtocol *This = PROTOCOL_THIS(iface);
00303     FIXME("(%p)\n", This);
00304     return E_NOTIMPL;
00305 }
00306 
00307 static HRESULT WINAPI AboutProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
00308 {
00309     AboutProtocol *This = PROTOCOL_THIS(iface);
00310 
00311     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
00312 
00313     if(!This->data)
00314         return E_FAIL;
00315 
00316     *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
00317 
00318     if(!*pcbRead)
00319         return S_FALSE;
00320 
00321     memcpy(pv, This->data+This->cur, *pcbRead);
00322     This->cur += *pcbRead;
00323 
00324     return S_OK;
00325 }
00326 
00327 static HRESULT WINAPI AboutProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
00328         DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
00329 {
00330     AboutProtocol *This = PROTOCOL_THIS(iface);
00331     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
00332     return E_NOTIMPL;
00333 }
00334 
00335 static HRESULT WINAPI AboutProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
00336 {
00337     AboutProtocol *This = PROTOCOL_THIS(iface);
00338 
00339     TRACE("(%p)->(%d)\n", This, dwOptions);
00340 
00341     return S_OK;
00342 }
00343 
00344 static HRESULT WINAPI AboutProtocol_UnlockRequest(IInternetProtocol *iface)
00345 {
00346     AboutProtocol *This = PROTOCOL_THIS(iface);
00347 
00348     TRACE("(%p)\n", This);
00349 
00350     return S_OK;
00351 }
00352 
00353 #undef PROTOCOL_THIS
00354 
00355 static const IInternetProtocolVtbl AboutProtocolVtbl = {
00356     AboutProtocol_QueryInterface,
00357     AboutProtocol_AddRef,
00358     AboutProtocol_Release,
00359     AboutProtocol_Start,
00360     AboutProtocol_Continue,
00361     AboutProtocol_Abort,
00362     AboutProtocol_Terminate,
00363     AboutProtocol_Suspend,
00364     AboutProtocol_Resume,
00365     AboutProtocol_Read,
00366     AboutProtocol_Seek,
00367     AboutProtocol_LockRequest,
00368     AboutProtocol_UnlockRequest
00369 };
00370 
00371 static HRESULT WINAPI AboutProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
00372         REFIID riid, void **ppv)
00373 {
00374     AboutProtocol *ret;
00375     HRESULT hres = S_OK;
00376 
00377     TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
00378 
00379     ret = heap_alloc(sizeof(AboutProtocol));
00380     ret->lpInternetProtocolVtbl = &AboutProtocolVtbl;
00381     ret->ref = 0;
00382 
00383     ret->data = NULL;
00384     ret->data_len = 0;
00385     ret->cur = 0;
00386     ret->pUnkOuter = pUnkOuter;
00387 
00388     if(pUnkOuter) {
00389         ret->ref = 1;
00390         if(IsEqualGUID(&IID_IUnknown, riid))
00391             *ppv = PROTOCOL(ret);
00392         else
00393             hres = E_INVALIDARG;
00394     }else {
00395         hres = IInternetProtocol_QueryInterface(PROTOCOL(ret), riid, ppv);
00396     }
00397 
00398     if(FAILED(hres))
00399         heap_free(ret);
00400 
00401     return hres;
00402 }
00403 
00404 static HRESULT WINAPI AboutProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00405         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
00406         DWORD* pcchResult, DWORD dwReserved)
00407 {
00408     TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
00409             dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
00410 
00411     if(ParseAction == PARSE_SECURITY_URL) {
00412         unsigned int len = strlenW(pwzUrl);
00413 
00414         if(len >= cchResult)
00415             return S_FALSE;
00416 
00417         memcpy(pwzResult, pwzUrl, (len+1)*sizeof(WCHAR));
00418         return S_OK;
00419     }
00420 
00421     if(ParseAction == PARSE_DOMAIN) {
00422         if(!pcchResult)
00423             return E_POINTER;
00424 
00425         if(pwzUrl)
00426             *pcchResult = strlenW(pwzUrl)+1;
00427         else
00428             *pcchResult = 1;
00429         return E_FAIL;
00430     }
00431 
00432     return INET_E_DEFAULT_ACTION;
00433 }
00434 
00435 static HRESULT WINAPI AboutProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00436         QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
00437         DWORD dwReserved)
00438 {
00439     TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
00440           cbBuffer, pcbBuf, dwReserved);
00441 
00442     switch(QueryOption) {
00443     case QUERY_CAN_NAVIGATE:
00444         return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
00445 
00446     case QUERY_USES_NETWORK:
00447         if(!pBuffer || cbBuffer < sizeof(DWORD))
00448             return E_FAIL;
00449 
00450         *(DWORD*)pBuffer = 0;
00451         if(pcbBuf)
00452             *pcbBuf = sizeof(DWORD);
00453 
00454         break;
00455 
00456     case QUERY_IS_CACHED:
00457         FIXME("Unsupported option QUERY_IS_CACHED\n");
00458         return E_NOTIMPL;
00459     case QUERY_IS_INSTALLEDENTRY:
00460         FIXME("Unsupported option QUERY_IS_INSTALLEDENTRY\n");
00461         return E_NOTIMPL;
00462     case QUERY_IS_CACHED_OR_MAPPED:
00463         FIXME("Unsupported option QUERY_IS_CACHED_OR_MAPPED\n");
00464         return E_NOTIMPL;
00465     case QUERY_IS_SECURE:
00466         FIXME("Unsupported option QUERY_IS_SECURE\n");
00467         return E_NOTIMPL;
00468     case QUERY_IS_SAFE:
00469         FIXME("Unsupported option QUERY_IS_SAFE\n");
00470         return E_NOTIMPL;
00471     case QUERY_USES_HISTORYFOLDER:
00472         FIXME("Unsupported option QUERY_USES_HISTORYFOLDER\n");
00473         return E_FAIL;
00474     default:
00475         return E_FAIL;
00476     }
00477 
00478     return S_OK;
00479 }
00480 
00481 static const IInternetProtocolInfoVtbl AboutProtocolInfoVtbl = {
00482     InternetProtocolInfo_QueryInterface,
00483     InternetProtocolInfo_AddRef,
00484     InternetProtocolInfo_Release,
00485     AboutProtocolInfo_ParseUrl,
00486     InternetProtocolInfo_CombineUrl,
00487     InternetProtocolInfo_CompareUrl,
00488     AboutProtocolInfo_QueryInfo
00489 };
00490 
00491 static const IClassFactoryVtbl AboutProtocolFactoryVtbl = {
00492     ClassFactory_QueryInterface,
00493     ClassFactory_AddRef,
00494     ClassFactory_Release,
00495     AboutProtocolFactory_CreateInstance,
00496     ClassFactory_LockServer
00497 };
00498 
00499 static ProtocolFactory AboutProtocolFactory = {
00500     &AboutProtocolInfoVtbl,
00501     &AboutProtocolFactoryVtbl
00502 };
00503 
00504 /********************************************************************
00505  * ResProtocol implementation
00506  */
00507 
00508 typedef struct {
00509     const IInternetProtocolVtbl *lpInternetProtocolVtbl;
00510     LONG ref;
00511 
00512     BYTE *data;
00513     ULONG data_len;
00514     ULONG cur;
00515 
00516     IUnknown *pUnkOuter;
00517 } ResProtocol;
00518 
00519 #define PROTOCOL_THIS(iface) DEFINE_THIS(ResProtocol, InternetProtocol, iface)
00520 
00521 static HRESULT WINAPI ResProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
00522 {
00523     ResProtocol *This = PROTOCOL_THIS(iface);
00524 
00525     *ppv = NULL;
00526 
00527     if(IsEqualGUID(&IID_IUnknown, riid)) {
00528         TRACE("(%p)->(IID_IUnknown %p)\n", iface, ppv);
00529         if(This->pUnkOuter)
00530             return IUnknown_QueryInterface(This->pUnkOuter, &IID_IUnknown, ppv);
00531         *ppv = PROTOCOL(This);
00532     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
00533         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", iface, ppv);
00534         *ppv = PROTOCOL(This);
00535     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
00536         TRACE("(%p)->(IID_IInternetProtocol %p)\n", iface, ppv);
00537         *ppv = PROTOCOL(This);
00538     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
00539         FIXME("IServiceProvider is not implemented\n");
00540         return E_NOINTERFACE;
00541     }
00542 
00543     if(!*ppv) {
00544         TRACE("unknown interface %s\n", debugstr_guid(riid));
00545         return E_NOINTERFACE;
00546     }
00547 
00548     IInternetProtocol_AddRef(iface);
00549     return S_OK;
00550 }
00551 
00552 static ULONG WINAPI ResProtocol_AddRef(IInternetProtocol *iface)
00553 {
00554     ResProtocol *This = PROTOCOL_THIS(iface);
00555     ULONG ref = InterlockedIncrement(&This->ref);
00556     TRACE("(%p) ref=%d\n", iface, ref);
00557     return This->pUnkOuter ? IUnknown_AddRef(This->pUnkOuter) : ref;
00558 }
00559 
00560 static ULONG WINAPI ResProtocol_Release(IInternetProtocol *iface)
00561 {
00562     ResProtocol *This = (ResProtocol*)iface;
00563     IUnknown *pUnkOuter = This->pUnkOuter;
00564     ULONG ref = InterlockedDecrement(&This->ref);
00565 
00566     TRACE("(%p) ref=%x\n", iface, ref);
00567 
00568     if(!ref) {
00569         heap_free(This->data);
00570         heap_free(This);
00571     }
00572 
00573     return pUnkOuter ? IUnknown_Release(pUnkOuter) : ref;
00574 }
00575 
00576 static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
00577         IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo,
00578         DWORD grfPI, HANDLE_PTR dwReserved)
00579 {
00580     ResProtocol *This = PROTOCOL_THIS(iface);
00581     DWORD grfBINDF = 0, len;
00582     BINDINFO bindinfo;
00583     LPWSTR url_dll, url_file, url, mime, res_type = (LPWSTR)RT_HTML;
00584     HMODULE hdll;
00585     HRSRC src;
00586     HRESULT hres;
00587 
00588     static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
00589 
00590     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
00591             pOIBindInfo, grfPI, dwReserved);
00592 
00593     memset(&bindinfo, 0, sizeof(bindinfo));
00594     bindinfo.cbSize = sizeof(BINDINFO);
00595     IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo);
00596     ReleaseBindInfo(&bindinfo);
00597 
00598     len = strlenW(szUrl)+16;
00599     url = heap_alloc(len*sizeof(WCHAR));
00600     hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0);
00601     if(FAILED(hres)) {
00602         WARN("CoInternetParseUrl failed: %08x\n", hres);
00603         heap_free(url);
00604         IInternetProtocolSink_ReportResult(pOIProtSink, hres, 0, NULL);
00605         return hres;
00606     }
00607 
00608     if(len < sizeof(wszRes)/sizeof(wszRes[0]) || memcmp(url, wszRes, sizeof(wszRes))) {
00609         WARN("Wrong protocol of url: %s\n", debugstr_w(url));
00610         IInternetProtocolSink_ReportResult(pOIProtSink, E_INVALIDARG, 0, NULL);
00611         heap_free(url);
00612         return E_INVALIDARG;
00613     }
00614 
00615     url_dll = url + sizeof(wszRes)/sizeof(wszRes[0]);
00616     if(!(url_file = strrchrW(url_dll, '/'))) {
00617         WARN("wrong url: %s\n", debugstr_w(url));
00618         IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL);
00619         heap_free(url);
00620         return MK_E_SYNTAX;
00621     }
00622 
00623     *url_file++ = 0;
00624     hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE);
00625     if(!hdll) {
00626         if (!(res_type = strrchrW(url_dll, '/'))) {
00627             WARN("Could not open dll: %s\n", debugstr_w(url_dll));
00628             IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
00629             heap_free(url);
00630             return HRESULT_FROM_WIN32(GetLastError());
00631         }
00632         *res_type++ = 0;
00633 
00634         hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE);
00635         if(!hdll) {
00636             WARN("Could not open dll: %s\n", debugstr_w(url_dll));
00637             IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
00638             heap_free(url);
00639             return HRESULT_FROM_WIN32(GetLastError());
00640         }
00641     }
00642 
00643     TRACE("trying to find resource type %s, name %s\n", debugstr_w(res_type), debugstr_w(url_file));
00644 
00645     src = FindResourceW(hdll, url_file, res_type);
00646     if(!src) {
00647         LPWSTR endpoint = NULL;
00648         DWORD file_id = strtolW(url_file, &endpoint, 10);
00649         if(endpoint == url_file+strlenW(url_file))
00650             src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), MAKEINTRESOURCEW(RT_HTML));
00651 
00652         if(!src) {
00653             WARN("Could not find resource\n");
00654             IInternetProtocolSink_ReportResult(pOIProtSink,
00655                     HRESULT_FROM_WIN32(GetLastError()), 0, NULL);
00656             heap_free(url);
00657             return HRESULT_FROM_WIN32(GetLastError());
00658         }
00659     }
00660 
00661     if(This->data) {
00662         WARN("data already loaded\n");
00663         heap_free(This->data);
00664     }
00665 
00666     This->data_len = SizeofResource(hdll, src);
00667     This->data = heap_alloc(This->data_len);
00668     memcpy(This->data, LoadResource(hdll, src), This->data_len);
00669     This->cur = 0;
00670 
00671     FreeLibrary(hdll);
00672 
00673     hres = FindMimeFromData(NULL, url_file, This->data, This->data_len, NULL, 0, &mime, 0);
00674     heap_free(url);
00675     if(SUCCEEDED(hres)) {
00676         IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
00677         CoTaskMemFree(mime);
00678     }
00679 
00680     IInternetProtocolSink_ReportData(pOIProtSink,
00681             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE,
00682             This->data_len, This->data_len);
00683 
00684     IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
00685     
00686     return S_OK;
00687 }
00688 
00689 static HRESULT WINAPI ResProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA* pProtocolData)
00690 {
00691     ResProtocol *This = PROTOCOL_THIS(iface);
00692     FIXME("(%p)->(%p)\n", This, pProtocolData);
00693     return E_NOTIMPL;
00694 }
00695 
00696 static HRESULT WINAPI ResProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
00697         DWORD dwOptions)
00698 {
00699     ResProtocol *This = PROTOCOL_THIS(iface);
00700     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
00701     return E_NOTIMPL;
00702 }
00703 
00704 static HRESULT WINAPI ResProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
00705 {
00706     ResProtocol *This = PROTOCOL_THIS(iface);
00707 
00708     TRACE("(%p)->(%08x)\n", This, dwOptions);
00709 
00710     /* test show that we don't have to do anything here */
00711     return S_OK;
00712 }
00713 
00714 static HRESULT WINAPI ResProtocol_Suspend(IInternetProtocol *iface)
00715 {
00716     ResProtocol *This = PROTOCOL_THIS(iface);
00717     FIXME("(%p)\n", This);
00718     return E_NOTIMPL;
00719 }
00720 
00721 static HRESULT WINAPI ResProtocol_Resume(IInternetProtocol *iface)
00722 {
00723     ResProtocol *This = PROTOCOL_THIS(iface);
00724     FIXME("(%p)\n", This);
00725     return E_NOTIMPL;
00726 }
00727 
00728 static HRESULT WINAPI ResProtocol_Read(IInternetProtocol *iface, void* pv, ULONG cb, ULONG* pcbRead)
00729 {
00730     ResProtocol *This = PROTOCOL_THIS(iface);
00731 
00732     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
00733 
00734     if(!This->data)
00735         return E_FAIL;
00736 
00737     *pcbRead = (cb > This->data_len-This->cur ? This->data_len-This->cur : cb);
00738 
00739     if(!*pcbRead)
00740         return S_FALSE;
00741 
00742     memcpy(pv, This->data+This->cur, *pcbRead);
00743     This->cur += *pcbRead;
00744 
00745     return S_OK;
00746 }
00747 
00748 static HRESULT WINAPI ResProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
00749         DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
00750 {
00751     ResProtocol *This = PROTOCOL_THIS(iface);
00752     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
00753     return E_NOTIMPL;
00754 }
00755 
00756 static HRESULT WINAPI ResProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
00757 {
00758     ResProtocol *This = PROTOCOL_THIS(iface);
00759 
00760     TRACE("(%p)->(%d)\n", This, dwOptions);
00761 
00762     /* test show that we don't have to do anything here */
00763     return S_OK;
00764 }
00765 
00766 static HRESULT WINAPI ResProtocol_UnlockRequest(IInternetProtocol *iface)
00767 {
00768     ResProtocol *This = PROTOCOL_THIS(iface);
00769 
00770     TRACE("(%p)\n", This);
00771 
00772     /* test show that we don't have to do anything here */
00773     return S_OK;
00774 }
00775 
00776 #undef PROTOCOL_THIS
00777 
00778 static const IInternetProtocolVtbl ResProtocolVtbl = {
00779     ResProtocol_QueryInterface,
00780     ResProtocol_AddRef,
00781     ResProtocol_Release,
00782     ResProtocol_Start,
00783     ResProtocol_Continue,
00784     ResProtocol_Abort,
00785     ResProtocol_Terminate,
00786     ResProtocol_Suspend,
00787     ResProtocol_Resume,
00788     ResProtocol_Read,
00789     ResProtocol_Seek,
00790     ResProtocol_LockRequest,
00791     ResProtocol_UnlockRequest
00792 };
00793 
00794 static HRESULT WINAPI ResProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
00795         REFIID riid, void **ppv)
00796 {
00797     ResProtocol *ret;
00798     HRESULT hres = S_OK;
00799 
00800     TRACE("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
00801 
00802     ret = heap_alloc(sizeof(ResProtocol));
00803     ret->lpInternetProtocolVtbl = &ResProtocolVtbl;
00804     ret->ref = 0;
00805     ret->data = NULL;
00806     ret->data_len = 0;
00807     ret->cur = 0;
00808     ret->pUnkOuter = pUnkOuter;
00809 
00810     if(pUnkOuter) {
00811         ret->ref = 1;
00812         if(IsEqualGUID(&IID_IUnknown, riid))
00813             *ppv = PROTOCOL(ret);
00814         else
00815             hres = E_FAIL;
00816     }else {
00817         hres = IInternetProtocol_QueryInterface(PROTOCOL(ret), riid, ppv);
00818     }
00819 
00820     if(FAILED(hres))
00821         heap_free(ret);
00822 
00823     return hres;
00824 }
00825 
00826 static HRESULT WINAPI ResProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00827         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
00828         DWORD* pcchResult, DWORD dwReserved)
00829 {
00830     TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
00831             dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
00832 
00833     if(ParseAction == PARSE_SECURITY_URL) {
00834         WCHAR file_part[MAX_PATH], full_path[MAX_PATH];
00835         WCHAR *ptr;
00836         DWORD size, len;
00837 
00838         static const WCHAR wszFile[] = {'f','i','l','e',':','/','/'};
00839         static const WCHAR wszRes[] = {'r','e','s',':','/','/'};
00840 
00841         if(strlenW(pwzUrl) <= sizeof(wszRes)/sizeof(WCHAR) || memcmp(pwzUrl, wszRes, sizeof(wszRes)))
00842             return E_INVALIDARG;
00843 
00844         ptr = strchrW(pwzUrl + sizeof(wszRes)/sizeof(WCHAR), '/');
00845         if(!ptr)
00846             return E_INVALIDARG;
00847 
00848         len = ptr - (pwzUrl + sizeof(wszRes)/sizeof(WCHAR));
00849         if(len >= sizeof(file_part)/sizeof(WCHAR)) {
00850             FIXME("Too long URL\n");
00851             return MK_E_SYNTAX;
00852         }
00853 
00854         memcpy(file_part, pwzUrl + sizeof(wszRes)/sizeof(WCHAR), len*sizeof(WCHAR));
00855         file_part[len] = 0;
00856 
00857         len = SearchPathW(NULL, file_part, NULL, sizeof(full_path)/sizeof(WCHAR), full_path, NULL);
00858         if(!len) {
00859             WARN("Could not find file %s\n", debugstr_w(file_part));
00860             return MK_E_SYNTAX;
00861         }
00862 
00863         size = sizeof(wszFile)/sizeof(WCHAR) + len + 1;
00864         if(pcchResult)
00865             *pcchResult = size;
00866         if(size >= cchResult)
00867             return S_FALSE;
00868 
00869         memcpy(pwzResult, wszFile, sizeof(wszFile));
00870         memcpy(pwzResult + sizeof(wszFile)/sizeof(WCHAR), full_path, (len+1)*sizeof(WCHAR));
00871         return S_OK;
00872     }
00873 
00874     if(ParseAction == PARSE_DOMAIN) {
00875         if(!pcchResult)
00876             return E_POINTER;
00877 
00878         if(pwzUrl)
00879             *pcchResult = strlenW(pwzUrl)+1;
00880         else
00881             *pcchResult = 1;
00882         return E_FAIL;
00883     }
00884 
00885     return INET_E_DEFAULT_ACTION;
00886 }
00887 
00888 static HRESULT WINAPI ResProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00889         QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
00890         DWORD dwReserved)
00891 {
00892     TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
00893           cbBuffer, pcbBuf, dwReserved);
00894 
00895     switch(QueryOption) {
00896     case QUERY_USES_NETWORK:
00897         if(!pBuffer || cbBuffer < sizeof(DWORD))
00898             return E_FAIL;
00899 
00900         *(DWORD*)pBuffer = 0;
00901         if(pcbBuf)
00902             *pcbBuf = sizeof(DWORD);
00903         break;
00904 
00905     case QUERY_IS_SECURE:
00906         FIXME("not supporte QUERY_IS_SECURE\n");
00907         return E_NOTIMPL;
00908     case QUERY_IS_SAFE:
00909         FIXME("not supporte QUERY_IS_SAFE\n");
00910         return E_NOTIMPL;
00911     default:
00912         return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
00913     }
00914 
00915     return S_OK;
00916 }
00917 
00918 static const IInternetProtocolInfoVtbl ResProtocolInfoVtbl = {
00919     InternetProtocolInfo_QueryInterface,
00920     InternetProtocolInfo_AddRef,
00921     InternetProtocolInfo_Release,
00922     ResProtocolInfo_ParseUrl,
00923     InternetProtocolInfo_CombineUrl,
00924     InternetProtocolInfo_CompareUrl,
00925     ResProtocolInfo_QueryInfo
00926 };
00927 
00928 static const IClassFactoryVtbl ResProtocolFactoryVtbl = {
00929     ClassFactory_QueryInterface,
00930     ClassFactory_AddRef,
00931     ClassFactory_Release,
00932     ResProtocolFactory_CreateInstance,
00933     ClassFactory_LockServer
00934 };
00935 
00936 static ProtocolFactory ResProtocolFactory = {
00937     &ResProtocolInfoVtbl,
00938     &ResProtocolFactoryVtbl
00939 };
00940 
00941 /********************************************************************
00942  * JSProtocol implementation
00943  */
00944 
00945 static HRESULT WINAPI JSProtocolFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
00946         REFIID riid, void **ppv)
00947 {
00948     FIXME("(%p)->(%p %s %p)\n", iface, pUnkOuter, debugstr_guid(riid), ppv);
00949     return E_NOTIMPL;
00950 }
00951 
00952 static HRESULT WINAPI JSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00953         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
00954         DWORD* pcchResult, DWORD dwReserved)
00955 {
00956     TRACE("%p)->(%s %d %x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), ParseAction,
00957           dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
00958 
00959     switch(ParseAction) {
00960     case PARSE_SECURITY_URL:
00961         FIXME("PARSE_SECURITY_URL\n");
00962         return E_NOTIMPL;
00963     case PARSE_DOMAIN:
00964         FIXME("PARSE_DOMAIN\n");
00965         return E_NOTIMPL;
00966     default:
00967         return INET_E_DEFAULT_ACTION;
00968     }
00969 
00970     return S_OK;
00971 }
00972 
00973 static HRESULT WINAPI JSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00974         QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
00975         DWORD dwReserved)
00976 {
00977     TRACE("%p)->(%s %08x %08x %p %d %p %d)\n", iface, debugstr_w(pwzUrl), QueryOption, dwQueryFlags, pBuffer,
00978           cbBuffer, pcbBuf, dwReserved);
00979 
00980     switch(QueryOption) {
00981     case QUERY_USES_NETWORK:
00982         if(!pBuffer || cbBuffer < sizeof(DWORD))
00983             return E_FAIL;
00984 
00985         *(DWORD*)pBuffer = 0;
00986         if(pcbBuf)
00987             *pcbBuf = sizeof(DWORD);
00988         break;
00989 
00990     case QUERY_IS_SECURE:
00991         FIXME("not supporte QUERY_IS_SECURE\n");
00992         return E_NOTIMPL;
00993 
00994     default:
00995         return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
00996     }
00997 
00998     return S_OK;
00999 }
01000 
01001 static const IInternetProtocolInfoVtbl JSProtocolInfoVtbl = {
01002     InternetProtocolInfo_QueryInterface,
01003     InternetProtocolInfo_AddRef,
01004     InternetProtocolInfo_Release,
01005     JSProtocolInfo_ParseUrl,
01006     InternetProtocolInfo_CombineUrl,
01007     InternetProtocolInfo_CompareUrl,
01008     JSProtocolInfo_QueryInfo
01009 };
01010 
01011 static const IClassFactoryVtbl JSProtocolFactoryVtbl = {
01012     ClassFactory_QueryInterface,
01013     ClassFactory_AddRef,
01014     ClassFactory_Release,
01015     JSProtocolFactory_CreateInstance,
01016     ClassFactory_LockServer
01017 };
01018 
01019 static ProtocolFactory JSProtocolFactory = {
01020     &JSProtocolInfoVtbl,
01021     &JSProtocolFactoryVtbl
01022 };
01023 
01024 HRESULT ProtocolFactory_Create(REFCLSID rclsid, REFIID riid, void **ppv)
01025 {
01026     ProtocolFactory *cf = NULL;
01027 
01028     if(IsEqualGUID(&CLSID_AboutProtocol, rclsid))
01029         cf = &AboutProtocolFactory;
01030     else if(IsEqualGUID(&CLSID_ResProtocol, rclsid))
01031         cf = &ResProtocolFactory;
01032     else if(IsEqualGUID(&CLSID_JSProtocol, rclsid))
01033         cf = &JSProtocolFactory;
01034 
01035     if(!cf) {
01036         FIXME("not implemented protocol %s\n", debugstr_guid(rclsid));
01037         return CLASS_E_CLASSNOTAVAILABLE;
01038     }
01039  
01040     return IUnknown_QueryInterface((IUnknown*)cf, riid, ppv);
01041 }

Generated on Sun May 27 2012 04:24:17 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.