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 2006-2007 Jacek Caban for CodeWeavers
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 <stdarg.h>
00020 
00021 #define COBJMACROS
00022 
00023 #include "windef.h"
00024 #include "winbase.h"
00025 #include "winuser.h"
00026 #include "winreg.h"
00027 #include "ole2.h"
00028 #include "urlmon.h"
00029 #include "shlwapi.h"
00030 #include "itsstor.h"
00031 #include "chm_lib.h"
00032 
00033 #include "wine/debug.h"
00034 #include "wine/unicode.h"
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(itss);
00037 
00038 typedef struct {
00039     IInternetProtocol     IInternetProtocol_iface;
00040     IInternetProtocolInfo IInternetProtocolInfo_iface;
00041 
00042     LONG ref;
00043 
00044     ULONG offset;
00045     struct chmFile *chm_file;
00046     struct chmUnitInfo chm_object;
00047 } ITSProtocol;
00048 
00049 static inline ITSProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
00050 {
00051     return CONTAINING_RECORD(iface, ITSProtocol, IInternetProtocol_iface);
00052 }
00053 
00054 static inline ITSProtocol *impl_from_IInternetProtocolInfo(IInternetProtocolInfo *iface)
00055 {
00056     return CONTAINING_RECORD(iface, ITSProtocol, IInternetProtocolInfo_iface);
00057 }
00058 
00059 static void release_chm(ITSProtocol *This)
00060 {
00061     if(This->chm_file) {
00062         chm_close(This->chm_file);
00063         This->chm_file = NULL;
00064     }
00065     This->offset = 0;
00066 }
00067 
00068 static HRESULT WINAPI ITSProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
00069 {
00070     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00071 
00072     *ppv = NULL;
00073     if(IsEqualGUID(&IID_IUnknown, riid)) {
00074         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
00075         *ppv = &This->IInternetProtocol_iface;
00076     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
00077         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
00078         *ppv = &This->IInternetProtocol_iface;
00079     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
00080         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
00081         *ppv = &This->IInternetProtocol_iface;
00082     }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) {
00083         TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv);
00084         *ppv = &This->IInternetProtocolInfo_iface;
00085     }
00086 
00087     if(*ppv) {
00088         IInternetProtocol_AddRef(iface);
00089         return S_OK;
00090     }
00091 
00092     WARN("not supported interface %s\n", debugstr_guid(riid));
00093     return E_NOINTERFACE;
00094 }
00095 
00096 static ULONG WINAPI ITSProtocol_AddRef(IInternetProtocol *iface)
00097 {
00098     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00099     LONG ref = InterlockedIncrement(&This->ref);
00100     TRACE("(%p) ref=%d\n", This, ref);
00101     return ref;
00102 }
00103 
00104 static ULONG WINAPI ITSProtocol_Release(IInternetProtocol *iface)
00105 {
00106     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00107     LONG ref = InterlockedDecrement(&This->ref);
00108 
00109     TRACE("(%p) ref=%d\n", This, ref);
00110 
00111     if(!ref) {
00112         release_chm(This);
00113         HeapFree(GetProcessHeap(), 0, This);
00114 
00115         ITSS_UnlockModule();
00116     }
00117 
00118     return ref;
00119 }
00120 
00121 static LPCWSTR skip_schema(LPCWSTR url)
00122 {
00123     static const WCHAR its_schema[] = {'i','t','s',':'};
00124     static const WCHAR msits_schema[] = {'m','s','-','i','t','s',':'};
00125     static const WCHAR mk_schema[] = {'m','k',':','@','M','S','I','T','S','t','o','r','e',':'};
00126 
00127     if(!strncmpiW(its_schema, url, sizeof(its_schema)/sizeof(WCHAR)))
00128         return url+sizeof(its_schema)/sizeof(WCHAR);
00129     if(!strncmpiW(msits_schema, url, sizeof(msits_schema)/sizeof(WCHAR)))
00130         return url+sizeof(msits_schema)/sizeof(WCHAR);
00131     if(!strncmpiW(mk_schema, url, sizeof(mk_schema)/sizeof(WCHAR)))
00132         return url+sizeof(mk_schema)/sizeof(WCHAR);
00133 
00134     return NULL;
00135 }
00136 
00137 static HRESULT report_result(IInternetProtocolSink *sink, HRESULT hres)
00138 {
00139     IInternetProtocolSink_ReportResult(sink, hres, 0, NULL);
00140     return hres;
00141 }
00142 
00143 static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
00144         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
00145         DWORD grfPI, HANDLE_PTR dwReserved)
00146 {
00147     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00148     BINDINFO bindinfo;
00149     DWORD bindf = 0, len;
00150     LPWSTR file_name, mime, object_name, p;
00151     LPCWSTR ptr;
00152     struct chmFile *chm_file;
00153     struct chmUnitInfo chm_object;
00154     int res;
00155     HRESULT hres;
00156 
00157     static const WCHAR separator[] = {':',':',0};
00158 
00159     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
00160             pOIBindInfo, grfPI, dwReserved);
00161 
00162     ptr = skip_schema(szUrl);
00163     if(!ptr)
00164         return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
00165 
00166     memset(&bindinfo, 0, sizeof(bindinfo));
00167     bindinfo.cbSize = sizeof(BINDINFO);
00168     hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
00169     if(FAILED(hres)) {
00170         WARN("GetBindInfo failed: %08x\n", hres);
00171         return hres;
00172     }
00173 
00174     ReleaseBindInfo(&bindinfo);
00175 
00176     len = strlenW(ptr)+3;
00177     file_name = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
00178     memcpy(file_name, ptr, len*sizeof(WCHAR));
00179     hres = UrlUnescapeW(file_name, NULL, &len, URL_UNESCAPE_INPLACE);
00180     if(FAILED(hres)) {
00181         WARN("UrlUnescape failed: %08x\n", hres);
00182         HeapFree(GetProcessHeap(), 0, file_name);
00183         return hres;
00184     }
00185 
00186     p = strstrW(file_name, separator);
00187     if(!p) {
00188         WARN("invalid url\n");
00189         HeapFree(GetProcessHeap(), 0, file_name);
00190         return report_result(pOIProtSink, STG_E_FILENOTFOUND);
00191     }
00192 
00193     *p = 0;
00194     chm_file = chm_openW(file_name);
00195     if(!chm_file) {
00196         WARN("Could not open chm file\n");
00197         HeapFree(GetProcessHeap(), 0, file_name);
00198         return report_result(pOIProtSink, STG_E_FILENOTFOUND);
00199     }
00200 
00201     object_name = p+2;
00202     len = strlenW(object_name);
00203 
00204     if(*object_name != '/' && *object_name != '\\') {
00205         memmove(object_name+1, object_name, (len+1)*sizeof(WCHAR));
00206         *object_name = '/';
00207         len++;
00208     }
00209 
00210     if(object_name[len-1] == '/')
00211         object_name[--len] = 0;
00212 
00213     for(p=object_name; *p; p++) {
00214         if(*p == '\\')
00215             *p = '/';
00216     }
00217 
00218     TRACE("Resolving %s\n", debugstr_w(object_name));
00219 
00220     memset(&chm_object, 0, sizeof(chm_object));
00221     res = chm_resolve_object(chm_file, object_name, &chm_object);
00222     if(res != CHM_RESOLVE_SUCCESS) {
00223         WARN("Could not resolve chm object\n");
00224         HeapFree(GetProcessHeap(), 0, file_name);
00225         chm_close(chm_file);
00226         return report_result(pOIProtSink, STG_E_FILENOTFOUND);
00227     }
00228 
00229     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST,
00230                                          strrchrW(object_name, '/')+1);
00231 
00232     /* FIXME: Native doesn't use FindMimeFromData */
00233     hres = FindMimeFromData(NULL, object_name, NULL, 0, NULL, 0, &mime, 0);
00234     HeapFree(GetProcessHeap(), 0, file_name);
00235     if(SUCCEEDED(hres)) {
00236         IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
00237         CoTaskMemFree(mime);
00238     }
00239 
00240     release_chm(This); /* Native leaks handle here */
00241     This->chm_file = chm_file;
00242     This->chm_object = chm_object;
00243 
00244     hres = IInternetProtocolSink_ReportData(pOIProtSink,
00245             BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE,
00246             chm_object.length, chm_object.length);
00247     if(FAILED(hres)) {
00248         WARN("ReportData failed: %08x\n", hres);
00249         release_chm(This);
00250         return report_result(pOIProtSink, hres);
00251     }
00252 
00253     hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL);
00254 
00255     return report_result(pOIProtSink, hres);
00256 }
00257 
00258 static HRESULT WINAPI ITSProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
00259 {
00260     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00261     FIXME("(%p)->(%p)\n", This, pProtocolData);
00262     return E_NOTIMPL;
00263 }
00264 
00265 static HRESULT WINAPI ITSProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
00266         DWORD dwOptions)
00267 {
00268     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00269     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
00270     return E_NOTIMPL;
00271 }
00272 
00273 static HRESULT WINAPI ITSProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
00274 {
00275     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00276 
00277     TRACE("(%p)->(%08x)\n", This, dwOptions);
00278 
00279     return S_OK;
00280 }
00281 
00282 static HRESULT WINAPI ITSProtocol_Suspend(IInternetProtocol *iface)
00283 {
00284     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00285     FIXME("(%p)\n", This);
00286     return E_NOTIMPL;
00287 }
00288 
00289 static HRESULT WINAPI ITSProtocol_Resume(IInternetProtocol *iface)
00290 {
00291     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00292     FIXME("(%p)\n", This);
00293     return E_NOTIMPL;
00294 }
00295 
00296 static HRESULT WINAPI ITSProtocol_Read(IInternetProtocol *iface, void *pv,
00297         ULONG cb, ULONG *pcbRead)
00298 {
00299     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00300 
00301     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
00302 
00303     if(!This->chm_file)
00304         return INET_E_DATA_NOT_AVAILABLE;
00305 
00306     *pcbRead = chm_retrieve_object(This->chm_file, &This->chm_object, pv, This->offset, cb);
00307     This->offset += *pcbRead;
00308 
00309     return *pcbRead ? S_OK : S_FALSE;
00310 }
00311 
00312 static HRESULT WINAPI ITSProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
00313         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
00314 {
00315     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00316     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
00317     return E_NOTIMPL;
00318 }
00319 
00320 static HRESULT WINAPI ITSProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
00321 {
00322     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00323 
00324     TRACE("(%p)->(%08x)\n", This, dwOptions);
00325 
00326     return S_OK;
00327 }
00328 
00329 static HRESULT WINAPI ITSProtocol_UnlockRequest(IInternetProtocol *iface)
00330 {
00331     ITSProtocol *This = impl_from_IInternetProtocol(iface);
00332 
00333     TRACE("(%p)\n", This);
00334 
00335     return S_OK;
00336 }
00337 
00338 static const IInternetProtocolVtbl ITSProtocolVtbl = {
00339     ITSProtocol_QueryInterface,
00340     ITSProtocol_AddRef,
00341     ITSProtocol_Release,
00342     ITSProtocol_Start,
00343     ITSProtocol_Continue,
00344     ITSProtocol_Abort,
00345     ITSProtocol_Terminate,
00346     ITSProtocol_Suspend,
00347     ITSProtocol_Resume,
00348     ITSProtocol_Read,
00349     ITSProtocol_Seek,
00350     ITSProtocol_LockRequest,
00351     ITSProtocol_UnlockRequest
00352 };
00353 
00354 static HRESULT WINAPI ITSProtocolInfo_QueryInterface(IInternetProtocolInfo *iface,
00355                                               REFIID riid, void **ppv)
00356 {
00357     ITSProtocol *This = impl_from_IInternetProtocolInfo(iface);
00358     return IInternetProtocol_QueryInterface(&This->IInternetProtocol_iface, riid, ppv);
00359 }
00360 
00361 static ULONG WINAPI ITSProtocolInfo_AddRef(IInternetProtocolInfo *iface)
00362 {
00363     ITSProtocol *This = impl_from_IInternetProtocolInfo(iface);
00364     return IInternetProtocol_AddRef(&This->IInternetProtocol_iface);
00365 }
00366 
00367 static ULONG WINAPI ITSProtocolInfo_Release(IInternetProtocolInfo *iface)
00368 {
00369     ITSProtocol *This = impl_from_IInternetProtocolInfo(iface);
00370     return IInternetProtocol_Release(&This->IInternetProtocol_iface);
00371 }
00372 
00373 static HRESULT WINAPI ITSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00374         PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult,
00375         DWORD *pcchResult, DWORD dwReserved)
00376 {
00377     ITSProtocol *This = impl_from_IInternetProtocolInfo(iface);
00378 
00379     TRACE("(%p)->(%s %x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl), ParseAction,
00380           dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved);
00381 
00382     switch(ParseAction) {
00383     case PARSE_CANONICALIZE:
00384         FIXME("PARSE_CANONICALIZE\n");
00385         return E_NOTIMPL;
00386     case PARSE_SECURITY_URL:
00387         FIXME("PARSE_SECURITY_URL\n");
00388         return E_NOTIMPL;
00389     default:
00390         return INET_E_DEFAULT_ACTION;
00391     }
00392 
00393     return S_OK;
00394 }
00395 
00396 static HRESULT WINAPI ITSProtocolInfo_CombineUrl(IInternetProtocolInfo *iface,
00397         LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult,
00398         DWORD cchResult, DWORD* pcchResult, DWORD dwReserved)
00399 {
00400     ITSProtocol *This = impl_from_IInternetProtocolInfo(iface);
00401     LPCWSTR base_end, ptr;
00402     DWORD rel_len;
00403 
00404     static const WCHAR separator[] = {':',':',0};
00405 
00406     TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This, debugstr_w(pwzBaseUrl),
00407             debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult,
00408             pcchResult, dwReserved);
00409 
00410     base_end = strstrW(pwzBaseUrl, separator);
00411     if(!base_end)
00412         return 0x80041001;
00413     base_end += 2;
00414 
00415     if(!skip_schema(pwzBaseUrl))
00416         return INET_E_USE_DEFAULT_PROTOCOLHANDLER;
00417 
00418     if(strchrW(pwzRelativeUrl, ':'))
00419         return STG_E_INVALIDNAME;
00420 
00421     if(pwzRelativeUrl[0] != '/') {
00422         ptr = strrchrW(base_end, '/');
00423         if(ptr)
00424             base_end = ptr+1;
00425         else
00426             base_end += strlenW(base_end);
00427     }
00428 
00429     rel_len = strlenW(pwzRelativeUrl)+1;
00430 
00431     *pcchResult = rel_len + (base_end-pwzBaseUrl);
00432 
00433     if(*pcchResult > cchResult)
00434         return E_OUTOFMEMORY;
00435 
00436     memcpy(pwzResult, pwzBaseUrl, (base_end-pwzBaseUrl)*sizeof(WCHAR));
00437     strcpyW(pwzResult + (base_end-pwzBaseUrl), pwzRelativeUrl);
00438 
00439     return S_OK;
00440 }
00441 
00442 static HRESULT WINAPI ITSProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1,
00443         LPCWSTR pwzUrl2, DWORD dwCompareFlags)
00444 {
00445     ITSProtocol *This = impl_from_IInternetProtocolInfo(iface);
00446     FIXME("%p)->(%s %s %08x)\n", This, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
00447     return E_NOTIMPL;
00448 }
00449 
00450 static HRESULT WINAPI ITSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl,
00451         QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf,
00452         DWORD dwReserved)
00453 {
00454     ITSProtocol *This = impl_from_IInternetProtocolInfo(iface);
00455     FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl), QueryOption,
00456           dwQueryFlags, pBuffer, cbBuffer, pcbBuf, dwReserved);
00457     return E_NOTIMPL;
00458 }
00459 
00460 static const IInternetProtocolInfoVtbl ITSProtocolInfoVtbl = {
00461     ITSProtocolInfo_QueryInterface,
00462     ITSProtocolInfo_AddRef,
00463     ITSProtocolInfo_Release,
00464     ITSProtocolInfo_ParseUrl,
00465     ITSProtocolInfo_CombineUrl,
00466     ITSProtocolInfo_CompareUrl,
00467     ITSProtocolInfo_QueryInfo
00468 };
00469 
00470 HRESULT ITSProtocol_create(IUnknown *pUnkOuter, LPVOID *ppobj)
00471 {
00472     ITSProtocol *ret;
00473 
00474     TRACE("(%p %p)\n", pUnkOuter, ppobj);
00475 
00476     ITSS_LockModule();
00477 
00478     ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITSProtocol));
00479 
00480     ret->IInternetProtocol_iface.lpVtbl = &ITSProtocolVtbl;
00481     ret->IInternetProtocolInfo_iface.lpVtbl = &ITSProtocolInfoVtbl;
00482     ret->ref = 1;
00483 
00484     *ppobj = &ret->IInternetProtocol_iface;
00485 
00486     return S_OK;
00487 }

Generated on Fri May 25 2012 04:22:10 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.