1c2c66affSColin Finck /* 2c2c66affSColin Finck * Copyright 2006-2007 Jacek Caban for CodeWeavers 3c2c66affSColin Finck * 4c2c66affSColin Finck * This library is free software; you can redistribute it and/or 5c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public 6c2c66affSColin Finck * License as published by the Free Software Foundation; either 7c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version. 8c2c66affSColin Finck * 9c2c66affSColin Finck * This library is distributed in the hope that it will be useful, 10c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of 11c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12c2c66affSColin Finck * Lesser General Public License for more details. 13c2c66affSColin Finck * 14c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public 15c2c66affSColin Finck * License along with this library; if not, write to the Free Software 16c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17c2c66affSColin Finck */ 18c2c66affSColin Finck 19919215fdSAmine Khaldi #include <stdarg.h> 20c2c66affSColin Finck 21919215fdSAmine Khaldi #define COBJMACROS 22919215fdSAmine Khaldi 23919215fdSAmine Khaldi #include "windef.h" 24919215fdSAmine Khaldi #include "winbase.h" 25919215fdSAmine Khaldi #include "winuser.h" 26919215fdSAmine Khaldi #include "winreg.h" 27919215fdSAmine Khaldi #include "ole2.h" 28919215fdSAmine Khaldi #include "urlmon.h" 29919215fdSAmine Khaldi #include "shlwapi.h" 30919215fdSAmine Khaldi #include "itsstor.h" 31919215fdSAmine Khaldi #include "chm_lib.h" 32919215fdSAmine Khaldi 33919215fdSAmine Khaldi #include "wine/debug.h" 34919215fdSAmine Khaldi #include "wine/unicode.h" 35919215fdSAmine Khaldi 36919215fdSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(itss); 37c2c66affSColin Finck 38c2c66affSColin Finck typedef struct { 39e64b0329SAmine Khaldi IUnknown IUnknown_inner; 40c2c66affSColin Finck IInternetProtocol IInternetProtocol_iface; 41c2c66affSColin Finck IInternetProtocolInfo IInternetProtocolInfo_iface; 42c2c66affSColin Finck 43c2c66affSColin Finck LONG ref; 44e64b0329SAmine Khaldi IUnknown *outer; 45c2c66affSColin Finck 46c2c66affSColin Finck ULONG offset; 47c2c66affSColin Finck struct chmFile *chm_file; 48c2c66affSColin Finck struct chmUnitInfo chm_object; 49c2c66affSColin Finck } ITSProtocol; 50c2c66affSColin Finck 51e64b0329SAmine Khaldi static inline ITSProtocol *impl_from_IUnknown(IUnknown *iface) 52e64b0329SAmine Khaldi { 53e64b0329SAmine Khaldi return CONTAINING_RECORD(iface, ITSProtocol, IUnknown_inner); 54e64b0329SAmine Khaldi } 55e64b0329SAmine Khaldi 56c2c66affSColin Finck static inline ITSProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface) 57c2c66affSColin Finck { 58c2c66affSColin Finck return CONTAINING_RECORD(iface, ITSProtocol, IInternetProtocol_iface); 59c2c66affSColin Finck } 60c2c66affSColin Finck 61c2c66affSColin Finck static inline ITSProtocol *impl_from_IInternetProtocolInfo(IInternetProtocolInfo *iface) 62c2c66affSColin Finck { 63c2c66affSColin Finck return CONTAINING_RECORD(iface, ITSProtocol, IInternetProtocolInfo_iface); 64c2c66affSColin Finck } 65c2c66affSColin Finck 66c2c66affSColin Finck static void release_chm(ITSProtocol *This) 67c2c66affSColin Finck { 68c2c66affSColin Finck if(This->chm_file) { 69c2c66affSColin Finck chm_close(This->chm_file); 70c2c66affSColin Finck This->chm_file = NULL; 71c2c66affSColin Finck } 72c2c66affSColin Finck This->offset = 0; 73c2c66affSColin Finck } 74c2c66affSColin Finck 75e64b0329SAmine Khaldi static HRESULT WINAPI ITSProtocol_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 76c2c66affSColin Finck { 77e64b0329SAmine Khaldi ITSProtocol *This = impl_from_IUnknown(iface); 78c2c66affSColin Finck 79c2c66affSColin Finck if(IsEqualGUID(&IID_IUnknown, riid)) { 80c2c66affSColin Finck TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 81e64b0329SAmine Khaldi *ppv = &This->IUnknown_inner; 82c2c66affSColin Finck }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { 83c2c66affSColin Finck TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); 84c2c66affSColin Finck *ppv = &This->IInternetProtocol_iface; 85c2c66affSColin Finck }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { 86c2c66affSColin Finck TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv); 87c2c66affSColin Finck *ppv = &This->IInternetProtocol_iface; 88c2c66affSColin Finck }else if(IsEqualGUID(&IID_IInternetProtocolInfo, riid)) { 89c2c66affSColin Finck TRACE("(%p)->(IID_IInternetProtocolInfo %p)\n", This, ppv); 90c2c66affSColin Finck *ppv = &This->IInternetProtocolInfo_iface; 91e64b0329SAmine Khaldi }else { 92e64b0329SAmine Khaldi *ppv = NULL; 93c2c66affSColin Finck WARN("not supported interface %s\n", debugstr_guid(riid)); 94c2c66affSColin Finck return E_NOINTERFACE; 95c2c66affSColin Finck } 96c2c66affSColin Finck 97e64b0329SAmine Khaldi IUnknown_AddRef((IUnknown*)*ppv); 98e64b0329SAmine Khaldi return S_OK; 99e64b0329SAmine Khaldi } 100e64b0329SAmine Khaldi 101e64b0329SAmine Khaldi static ULONG WINAPI ITSProtocol_AddRef(IUnknown *iface) 102c2c66affSColin Finck { 103e64b0329SAmine Khaldi ITSProtocol *This = impl_from_IUnknown(iface); 104c2c66affSColin Finck LONG ref = InterlockedIncrement(&This->ref); 105c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref); 106c2c66affSColin Finck return ref; 107c2c66affSColin Finck } 108c2c66affSColin Finck 109e64b0329SAmine Khaldi static ULONG WINAPI ITSProtocol_Release(IUnknown *iface) 110c2c66affSColin Finck { 111e64b0329SAmine Khaldi ITSProtocol *This = impl_from_IUnknown(iface); 112c2c66affSColin Finck LONG ref = InterlockedDecrement(&This->ref); 113c2c66affSColin Finck 114c2c66affSColin Finck TRACE("(%p) ref=%d\n", This, ref); 115c2c66affSColin Finck 116c2c66affSColin Finck if(!ref) { 117c2c66affSColin Finck release_chm(This); 118c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, This); 119c2c66affSColin Finck 120c2c66affSColin Finck ITSS_UnlockModule(); 121c2c66affSColin Finck } 122c2c66affSColin Finck 123c2c66affSColin Finck return ref; 124c2c66affSColin Finck } 125c2c66affSColin Finck 126e64b0329SAmine Khaldi static const IUnknownVtbl ITSProtocolUnkVtbl = { 127e64b0329SAmine Khaldi ITSProtocol_QueryInterface, 128e64b0329SAmine Khaldi ITSProtocol_AddRef, 129e64b0329SAmine Khaldi ITSProtocol_Release 130e64b0329SAmine Khaldi }; 131e64b0329SAmine Khaldi 132e64b0329SAmine Khaldi static HRESULT WINAPI ITSInternetProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) 133e64b0329SAmine Khaldi { 134e64b0329SAmine Khaldi ITSProtocol *This = impl_from_IInternetProtocol(iface); 135e64b0329SAmine Khaldi return IUnknown_QueryInterface(This->outer, riid, ppv); 136e64b0329SAmine Khaldi } 137e64b0329SAmine Khaldi 138e64b0329SAmine Khaldi static ULONG WINAPI ITSInternetProtocol_AddRef(IInternetProtocol *iface) 139e64b0329SAmine Khaldi { 140e64b0329SAmine Khaldi ITSProtocol *This = impl_from_IInternetProtocol(iface); 141e64b0329SAmine Khaldi return IUnknown_AddRef(This->outer); 142e64b0329SAmine Khaldi } 143e64b0329SAmine Khaldi 144e64b0329SAmine Khaldi static ULONG WINAPI ITSInternetProtocol_Release(IInternetProtocol *iface) 145e64b0329SAmine Khaldi { 146e64b0329SAmine Khaldi ITSProtocol *This = impl_from_IInternetProtocol(iface); 147e64b0329SAmine Khaldi return IUnknown_Release(This->outer); 148e64b0329SAmine Khaldi } 149e64b0329SAmine Khaldi 150c2c66affSColin Finck static LPCWSTR skip_schema(LPCWSTR url) 151c2c66affSColin Finck { 152c2c66affSColin Finck static const WCHAR its_schema[] = {'i','t','s',':'}; 153c2c66affSColin Finck static const WCHAR msits_schema[] = {'m','s','-','i','t','s',':'}; 154c2c66affSColin Finck static const WCHAR mk_schema[] = {'m','k',':','@','M','S','I','T','S','t','o','r','e',':'}; 155c2c66affSColin Finck 156*0ccdd32fSAmine Khaldi if(!strncmpiW(its_schema, url, ARRAY_SIZE(its_schema))) 157*0ccdd32fSAmine Khaldi return url + ARRAY_SIZE(its_schema); 158*0ccdd32fSAmine Khaldi if(!strncmpiW(msits_schema, url, ARRAY_SIZE(msits_schema))) 159*0ccdd32fSAmine Khaldi return url + ARRAY_SIZE(msits_schema); 160*0ccdd32fSAmine Khaldi if(!strncmpiW(mk_schema, url, ARRAY_SIZE(mk_schema))) 161*0ccdd32fSAmine Khaldi return url + ARRAY_SIZE(mk_schema); 162c2c66affSColin Finck 163c2c66affSColin Finck return NULL; 164c2c66affSColin Finck } 165c2c66affSColin Finck 166c2c66affSColin Finck /* Adopted from urlmon */ 167c2c66affSColin Finck static void remove_dot_segments(WCHAR *path) { 168c2c66affSColin Finck const WCHAR *in = path; 169c2c66affSColin Finck WCHAR *out = path; 170c2c66affSColin Finck 171c2c66affSColin Finck while(1) { 172c2c66affSColin Finck /* Move the first path segment in the input buffer to the end of 173c2c66affSColin Finck * the output buffer, and any subsequent characters up to, including 174c2c66affSColin Finck * the next "/" character (if any) or the end of the input buffer. 175c2c66affSColin Finck */ 176c2c66affSColin Finck while(*in != '/') { 177c2c66affSColin Finck if(!(*out++ = *in++)) 178c2c66affSColin Finck return; 179c2c66affSColin Finck } 180c2c66affSColin Finck 181c2c66affSColin Finck *out++ = *in++; 182c2c66affSColin Finck 183c2c66affSColin Finck while(*in) { 184c2c66affSColin Finck if(*in != '.') 185c2c66affSColin Finck break; 186c2c66affSColin Finck 187c2c66affSColin Finck /* Handle ending "/." */ 188c2c66affSColin Finck if(!in[1]) { 189c2c66affSColin Finck ++in; 190c2c66affSColin Finck break; 191c2c66affSColin Finck } 192c2c66affSColin Finck 193c2c66affSColin Finck /* Handle "/./" */ 194c2c66affSColin Finck if(in[1] == '/') { 195c2c66affSColin Finck in += 2; 196c2c66affSColin Finck continue; 197c2c66affSColin Finck } 198c2c66affSColin Finck 199c2c66affSColin Finck /* If we don't have "/../" or ending "/.." */ 200c2c66affSColin Finck if(in[1] != '.' || (in[2] && in[2] != '/')) 201c2c66affSColin Finck break; 202c2c66affSColin Finck 203c2c66affSColin Finck in += *in ? 3 : 2; 204c2c66affSColin Finck 205c2c66affSColin Finck /* Find the slash preceding out pointer and move out pointer to it */ 206c2c66affSColin Finck if(out > path+1 && *--out == '/') 207c2c66affSColin Finck --out; 208c2c66affSColin Finck while(out > path && *(--out) != '/'); 209c2c66affSColin Finck if(*out == '/') 210c2c66affSColin Finck ++out; 211c2c66affSColin Finck } 212c2c66affSColin Finck } 213c2c66affSColin Finck } 214c2c66affSColin Finck 215c2c66affSColin Finck static HRESULT report_result(IInternetProtocolSink *sink, HRESULT hres) 216c2c66affSColin Finck { 217c2c66affSColin Finck IInternetProtocolSink_ReportResult(sink, hres, 0, NULL); 218c2c66affSColin Finck return hres; 219c2c66affSColin Finck } 220c2c66affSColin Finck 221c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, 222c2c66affSColin Finck IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, 223c2c66affSColin Finck DWORD grfPI, HANDLE_PTR dwReserved) 224c2c66affSColin Finck { 225c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 226c2c66affSColin Finck BINDINFO bindinfo; 227c2c66affSColin Finck DWORD bindf = 0, len; 228c2c66affSColin Finck LPWSTR file_name, mime, object_name, p; 229c2c66affSColin Finck LPCWSTR ptr; 230c2c66affSColin Finck struct chmFile *chm_file; 231c2c66affSColin Finck struct chmUnitInfo chm_object; 232c2c66affSColin Finck int res; 233c2c66affSColin Finck HRESULT hres; 234c2c66affSColin Finck 235c2c66affSColin Finck static const WCHAR separator[] = {':',':',0}; 236c2c66affSColin Finck 237c2c66affSColin Finck TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, 238c2c66affSColin Finck pOIBindInfo, grfPI, dwReserved); 239c2c66affSColin Finck 240c2c66affSColin Finck ptr = skip_schema(szUrl); 241c2c66affSColin Finck if(!ptr) 242c2c66affSColin Finck return INET_E_USE_DEFAULT_PROTOCOLHANDLER; 243c2c66affSColin Finck 244c2c66affSColin Finck memset(&bindinfo, 0, sizeof(bindinfo)); 245c2c66affSColin Finck bindinfo.cbSize = sizeof(BINDINFO); 246c2c66affSColin Finck hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo); 247c2c66affSColin Finck if(FAILED(hres)) { 248c2c66affSColin Finck WARN("GetBindInfo failed: %08x\n", hres); 249c2c66affSColin Finck return hres; 250c2c66affSColin Finck } 251c2c66affSColin Finck 252c2c66affSColin Finck ReleaseBindInfo(&bindinfo); 253c2c66affSColin Finck 254c2c66affSColin Finck len = strlenW(ptr)+3; 255c2c66affSColin Finck file_name = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 256c2c66affSColin Finck memcpy(file_name, ptr, len*sizeof(WCHAR)); 257c2c66affSColin Finck hres = UrlUnescapeW(file_name, NULL, &len, URL_UNESCAPE_INPLACE); 258c2c66affSColin Finck if(FAILED(hres)) { 259c2c66affSColin Finck WARN("UrlUnescape failed: %08x\n", hres); 260c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_name); 261c2c66affSColin Finck return hres; 262c2c66affSColin Finck } 263c2c66affSColin Finck 264c2c66affSColin Finck p = strstrW(file_name, separator); 265c2c66affSColin Finck if(!p) { 266c2c66affSColin Finck WARN("invalid url\n"); 267c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_name); 268c2c66affSColin Finck return report_result(pOIProtSink, STG_E_FILENOTFOUND); 269c2c66affSColin Finck } 270c2c66affSColin Finck 271c2c66affSColin Finck *p = 0; 272c2c66affSColin Finck chm_file = chm_openW(file_name); 273c2c66affSColin Finck if(!chm_file) { 274c2c66affSColin Finck WARN("Could not open chm file\n"); 275c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_name); 276c2c66affSColin Finck return report_result(pOIProtSink, STG_E_FILENOTFOUND); 277c2c66affSColin Finck } 278c2c66affSColin Finck 279c2c66affSColin Finck object_name = p+2; 280c2c66affSColin Finck len = strlenW(object_name); 281c2c66affSColin Finck 282c2c66affSColin Finck if(*object_name != '/' && *object_name != '\\') { 283c2c66affSColin Finck memmove(object_name+1, object_name, (len+1)*sizeof(WCHAR)); 284c2c66affSColin Finck *object_name = '/'; 285c2c66affSColin Finck len++; 286c2c66affSColin Finck } 287c2c66affSColin Finck 288c2c66affSColin Finck if(object_name[len-1] == '/') 289c2c66affSColin Finck object_name[--len] = 0; 290c2c66affSColin Finck 291c2c66affSColin Finck for(p=object_name; *p; p++) { 292c2c66affSColin Finck if(*p == '\\') 293c2c66affSColin Finck *p = '/'; 294c2c66affSColin Finck } 295c2c66affSColin Finck 296c2c66affSColin Finck remove_dot_segments(object_name); 297c2c66affSColin Finck 298c2c66affSColin Finck TRACE("Resolving %s\n", debugstr_w(object_name)); 299c2c66affSColin Finck 300c2c66affSColin Finck memset(&chm_object, 0, sizeof(chm_object)); 301c2c66affSColin Finck res = chm_resolve_object(chm_file, object_name, &chm_object); 302c2c66affSColin Finck if(res != CHM_RESOLVE_SUCCESS) { 303c2c66affSColin Finck WARN("Could not resolve chm object\n"); 304c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_name); 305c2c66affSColin Finck chm_close(chm_file); 306c2c66affSColin Finck return report_result(pOIProtSink, STG_E_FILENOTFOUND); 307c2c66affSColin Finck } 308c2c66affSColin Finck 309c2c66affSColin Finck IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, 310c2c66affSColin Finck strrchrW(object_name, '/')+1); 311c2c66affSColin Finck 312c2c66affSColin Finck /* FIXME: Native doesn't use FindMimeFromData */ 313c2c66affSColin Finck hres = FindMimeFromData(NULL, object_name, NULL, 0, NULL, 0, &mime, 0); 314c2c66affSColin Finck HeapFree(GetProcessHeap(), 0, file_name); 315c2c66affSColin Finck if(SUCCEEDED(hres)) { 316c2c66affSColin Finck IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); 317c2c66affSColin Finck CoTaskMemFree(mime); 318c2c66affSColin Finck } 319c2c66affSColin Finck 320c2c66affSColin Finck release_chm(This); /* Native leaks handle here */ 321c2c66affSColin Finck This->chm_file = chm_file; 322c2c66affSColin Finck This->chm_object = chm_object; 323c2c66affSColin Finck 324c2c66affSColin Finck hres = IInternetProtocolSink_ReportData(pOIProtSink, 325c2c66affSColin Finck BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE, 326c2c66affSColin Finck chm_object.length, chm_object.length); 327c2c66affSColin Finck if(FAILED(hres)) { 328c2c66affSColin Finck WARN("ReportData failed: %08x\n", hres); 329c2c66affSColin Finck release_chm(This); 330c2c66affSColin Finck return report_result(pOIProtSink, hres); 331c2c66affSColin Finck } 332c2c66affSColin Finck 333c2c66affSColin Finck hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL); 334c2c66affSColin Finck 335c2c66affSColin Finck return report_result(pOIProtSink, hres); 336c2c66affSColin Finck } 337c2c66affSColin Finck 338c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) 339c2c66affSColin Finck { 340c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 341c2c66affSColin Finck FIXME("(%p)->(%p)\n", This, pProtocolData); 342c2c66affSColin Finck return E_NOTIMPL; 343c2c66affSColin Finck } 344c2c66affSColin Finck 345c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, 346c2c66affSColin Finck DWORD dwOptions) 347c2c66affSColin Finck { 348c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 349c2c66affSColin Finck FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions); 350c2c66affSColin Finck return E_NOTIMPL; 351c2c66affSColin Finck } 352c2c66affSColin Finck 353c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) 354c2c66affSColin Finck { 355c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 356c2c66affSColin Finck 357c2c66affSColin Finck TRACE("(%p)->(%08x)\n", This, dwOptions); 358c2c66affSColin Finck 359c2c66affSColin Finck return S_OK; 360c2c66affSColin Finck } 361c2c66affSColin Finck 362c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Suspend(IInternetProtocol *iface) 363c2c66affSColin Finck { 364c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 365c2c66affSColin Finck FIXME("(%p)\n", This); 366c2c66affSColin Finck return E_NOTIMPL; 367c2c66affSColin Finck } 368c2c66affSColin Finck 369c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Resume(IInternetProtocol *iface) 370c2c66affSColin Finck { 371c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 372c2c66affSColin Finck FIXME("(%p)\n", This); 373c2c66affSColin Finck return E_NOTIMPL; 374c2c66affSColin Finck } 375c2c66affSColin Finck 376c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Read(IInternetProtocol *iface, void *pv, 377c2c66affSColin Finck ULONG cb, ULONG *pcbRead) 378c2c66affSColin Finck { 379c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 380c2c66affSColin Finck 381c2c66affSColin Finck TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); 382c2c66affSColin Finck 383c2c66affSColin Finck if(!This->chm_file) 384c2c66affSColin Finck return INET_E_DATA_NOT_AVAILABLE; 385c2c66affSColin Finck 386c2c66affSColin Finck *pcbRead = chm_retrieve_object(This->chm_file, &This->chm_object, pv, This->offset, cb); 387c2c66affSColin Finck This->offset += *pcbRead; 388c2c66affSColin Finck 389c2c66affSColin Finck return *pcbRead ? S_OK : S_FALSE; 390c2c66affSColin Finck } 391c2c66affSColin Finck 392c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, 393c2c66affSColin Finck DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 394c2c66affSColin Finck { 395c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 396c2c66affSColin Finck FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition); 397c2c66affSColin Finck return E_NOTIMPL; 398c2c66affSColin Finck } 399c2c66affSColin Finck 400c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) 401c2c66affSColin Finck { 402c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 403c2c66affSColin Finck 404c2c66affSColin Finck TRACE("(%p)->(%08x)\n", This, dwOptions); 405c2c66affSColin Finck 406c2c66affSColin Finck return S_OK; 407c2c66affSColin Finck } 408c2c66affSColin Finck 409c2c66affSColin Finck static HRESULT WINAPI ITSProtocol_UnlockRequest(IInternetProtocol *iface) 410c2c66affSColin Finck { 411c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocol(iface); 412c2c66affSColin Finck 413c2c66affSColin Finck TRACE("(%p)\n", This); 414c2c66affSColin Finck 415c2c66affSColin Finck return S_OK; 416c2c66affSColin Finck } 417c2c66affSColin Finck 418c2c66affSColin Finck static const IInternetProtocolVtbl ITSProtocolVtbl = { 419e64b0329SAmine Khaldi ITSInternetProtocol_QueryInterface, 420e64b0329SAmine Khaldi ITSInternetProtocol_AddRef, 421e64b0329SAmine Khaldi ITSInternetProtocol_Release, 422c2c66affSColin Finck ITSProtocol_Start, 423c2c66affSColin Finck ITSProtocol_Continue, 424c2c66affSColin Finck ITSProtocol_Abort, 425c2c66affSColin Finck ITSProtocol_Terminate, 426c2c66affSColin Finck ITSProtocol_Suspend, 427c2c66affSColin Finck ITSProtocol_Resume, 428c2c66affSColin Finck ITSProtocol_Read, 429c2c66affSColin Finck ITSProtocol_Seek, 430c2c66affSColin Finck ITSProtocol_LockRequest, 431c2c66affSColin Finck ITSProtocol_UnlockRequest 432c2c66affSColin Finck }; 433c2c66affSColin Finck 434c2c66affSColin Finck static HRESULT WINAPI ITSProtocolInfo_QueryInterface(IInternetProtocolInfo *iface, 435c2c66affSColin Finck REFIID riid, void **ppv) 436c2c66affSColin Finck { 437c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocolInfo(iface); 438c2c66affSColin Finck return IInternetProtocol_QueryInterface(&This->IInternetProtocol_iface, riid, ppv); 439c2c66affSColin Finck } 440c2c66affSColin Finck 441c2c66affSColin Finck static ULONG WINAPI ITSProtocolInfo_AddRef(IInternetProtocolInfo *iface) 442c2c66affSColin Finck { 443c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocolInfo(iface); 444c2c66affSColin Finck return IInternetProtocol_AddRef(&This->IInternetProtocol_iface); 445c2c66affSColin Finck } 446c2c66affSColin Finck 447c2c66affSColin Finck static ULONG WINAPI ITSProtocolInfo_Release(IInternetProtocolInfo *iface) 448c2c66affSColin Finck { 449c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocolInfo(iface); 450c2c66affSColin Finck return IInternetProtocol_Release(&This->IInternetProtocol_iface); 451c2c66affSColin Finck } 452c2c66affSColin Finck 453c2c66affSColin Finck static HRESULT WINAPI ITSProtocolInfo_ParseUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, 454c2c66affSColin Finck PARSEACTION ParseAction, DWORD dwParseFlags, LPWSTR pwzResult, DWORD cchResult, 455c2c66affSColin Finck DWORD *pcchResult, DWORD dwReserved) 456c2c66affSColin Finck { 457c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocolInfo(iface); 458c2c66affSColin Finck 459c2c66affSColin Finck TRACE("(%p)->(%s %x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl), ParseAction, 460c2c66affSColin Finck dwParseFlags, pwzResult, cchResult, pcchResult, dwReserved); 461c2c66affSColin Finck 462c2c66affSColin Finck switch(ParseAction) { 463c2c66affSColin Finck case PARSE_CANONICALIZE: 464c2c66affSColin Finck FIXME("PARSE_CANONICALIZE\n"); 465c2c66affSColin Finck return E_NOTIMPL; 466c2c66affSColin Finck case PARSE_SECURITY_URL: 467c2c66affSColin Finck FIXME("PARSE_SECURITY_URL\n"); 468c2c66affSColin Finck return E_NOTIMPL; 469c2c66affSColin Finck default: 470c2c66affSColin Finck return INET_E_DEFAULT_ACTION; 471c2c66affSColin Finck } 472c2c66affSColin Finck 473c2c66affSColin Finck return S_OK; 474c2c66affSColin Finck } 475c2c66affSColin Finck 476c2c66affSColin Finck static HRESULT WINAPI ITSProtocolInfo_CombineUrl(IInternetProtocolInfo *iface, 477c2c66affSColin Finck LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags, LPWSTR pwzResult, 478c2c66affSColin Finck DWORD cchResult, DWORD* pcchResult, DWORD dwReserved) 479c2c66affSColin Finck { 480c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocolInfo(iface); 481c2c66affSColin Finck LPCWSTR base_end, ptr; 482c2c66affSColin Finck DWORD rel_len; 483c2c66affSColin Finck 484c2c66affSColin Finck static const WCHAR separator[] = {':',':',0}; 485c2c66affSColin Finck 486c2c66affSColin Finck TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This, debugstr_w(pwzBaseUrl), 487c2c66affSColin Finck debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult, 488c2c66affSColin Finck pcchResult, dwReserved); 489c2c66affSColin Finck 490c2c66affSColin Finck base_end = strstrW(pwzBaseUrl, separator); 491c2c66affSColin Finck if(!base_end) 492c2c66affSColin Finck return 0x80041001; 493c2c66affSColin Finck base_end += 2; 494c2c66affSColin Finck 495c2c66affSColin Finck if(!skip_schema(pwzBaseUrl)) 496c2c66affSColin Finck return INET_E_USE_DEFAULT_PROTOCOLHANDLER; 497c2c66affSColin Finck 498c2c66affSColin Finck if(strchrW(pwzRelativeUrl, ':')) 499c2c66affSColin Finck return STG_E_INVALIDNAME; 500c2c66affSColin Finck 501c2c66affSColin Finck if(pwzRelativeUrl[0] == '#') { 502c2c66affSColin Finck base_end += strlenW(base_end); 503c2c66affSColin Finck }else if(pwzRelativeUrl[0] != '/') { 504c2c66affSColin Finck ptr = strrchrW(base_end, '/'); 505c2c66affSColin Finck if(ptr) 506c2c66affSColin Finck base_end = ptr+1; 507c2c66affSColin Finck else 508c2c66affSColin Finck base_end += strlenW(base_end); 509c2c66affSColin Finck } 510c2c66affSColin Finck 511c2c66affSColin Finck rel_len = strlenW(pwzRelativeUrl)+1; 512c2c66affSColin Finck 513c2c66affSColin Finck *pcchResult = rel_len + (base_end-pwzBaseUrl); 514c2c66affSColin Finck 515c2c66affSColin Finck if(*pcchResult > cchResult) 516c2c66affSColin Finck return E_OUTOFMEMORY; 517c2c66affSColin Finck 518c2c66affSColin Finck memcpy(pwzResult, pwzBaseUrl, (base_end-pwzBaseUrl)*sizeof(WCHAR)); 519c2c66affSColin Finck strcpyW(pwzResult + (base_end-pwzBaseUrl), pwzRelativeUrl); 520c2c66affSColin Finck 521c2c66affSColin Finck return S_OK; 522c2c66affSColin Finck } 523c2c66affSColin Finck 524c2c66affSColin Finck static HRESULT WINAPI ITSProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1, 525c2c66affSColin Finck LPCWSTR pwzUrl2, DWORD dwCompareFlags) 526c2c66affSColin Finck { 527c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocolInfo(iface); 528c2c66affSColin Finck FIXME("%p)->(%s %s %08x)\n", This, debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags); 529c2c66affSColin Finck return E_NOTIMPL; 530c2c66affSColin Finck } 531c2c66affSColin Finck 532c2c66affSColin Finck static HRESULT WINAPI ITSProtocolInfo_QueryInfo(IInternetProtocolInfo *iface, LPCWSTR pwzUrl, 533c2c66affSColin Finck QUERYOPTION QueryOption, DWORD dwQueryFlags, LPVOID pBuffer, DWORD cbBuffer, DWORD* pcbBuf, 534c2c66affSColin Finck DWORD dwReserved) 535c2c66affSColin Finck { 536c2c66affSColin Finck ITSProtocol *This = impl_from_IInternetProtocolInfo(iface); 537c2c66affSColin Finck FIXME("(%p)->(%s %08x %08x %p %d %p %d)\n", This, debugstr_w(pwzUrl), QueryOption, 538c2c66affSColin Finck dwQueryFlags, pBuffer, cbBuffer, pcbBuf, dwReserved); 539c2c66affSColin Finck return E_NOTIMPL; 540c2c66affSColin Finck } 541c2c66affSColin Finck 542c2c66affSColin Finck static const IInternetProtocolInfoVtbl ITSProtocolInfoVtbl = { 543c2c66affSColin Finck ITSProtocolInfo_QueryInterface, 544c2c66affSColin Finck ITSProtocolInfo_AddRef, 545c2c66affSColin Finck ITSProtocolInfo_Release, 546c2c66affSColin Finck ITSProtocolInfo_ParseUrl, 547c2c66affSColin Finck ITSProtocolInfo_CombineUrl, 548c2c66affSColin Finck ITSProtocolInfo_CompareUrl, 549c2c66affSColin Finck ITSProtocolInfo_QueryInfo 550c2c66affSColin Finck }; 551c2c66affSColin Finck 552e64b0329SAmine Khaldi HRESULT ITSProtocol_create(IUnknown *outer, void **ppv) 553c2c66affSColin Finck { 554c2c66affSColin Finck ITSProtocol *ret; 555c2c66affSColin Finck 556e64b0329SAmine Khaldi TRACE("(%p %p)\n", outer, ppv); 557c2c66affSColin Finck 558c2c66affSColin Finck ITSS_LockModule(); 559c2c66affSColin Finck 560c2c66affSColin Finck ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ITSProtocol)); 561e64b0329SAmine Khaldi if(!ret) 562e64b0329SAmine Khaldi return E_OUTOFMEMORY; 563c2c66affSColin Finck 564e64b0329SAmine Khaldi ret->IUnknown_inner.lpVtbl = &ITSProtocolUnkVtbl; 565c2c66affSColin Finck ret->IInternetProtocol_iface.lpVtbl = &ITSProtocolVtbl; 566c2c66affSColin Finck ret->IInternetProtocolInfo_iface.lpVtbl = &ITSProtocolInfoVtbl; 567c2c66affSColin Finck ret->ref = 1; 568e64b0329SAmine Khaldi ret->outer = outer ? outer : &ret->IUnknown_inner; 569c2c66affSColin Finck 570e64b0329SAmine Khaldi *ppv = &ret->IUnknown_inner; 571c2c66affSColin Finck return S_OK; 572c2c66affSColin Finck } 573