Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennavigate.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 "config.h" 00020 00021 #include <stdarg.h> 00022 00023 #define COBJMACROS 00024 #define NONAMELESSUNION 00025 #define NONAMELESSSTRUCT 00026 00027 #include "windef.h" 00028 #include "winbase.h" 00029 #include "winuser.h" 00030 #include "winreg.h" 00031 #include "ole2.h" 00032 #include "hlguids.h" 00033 #include "shlguid.h" 00034 #include "wininet.h" 00035 #include "shlwapi.h" 00036 00037 #include "wine/debug.h" 00038 #include "wine/unicode.h" 00039 00040 #include "mshtml_private.h" 00041 00042 WINE_DEFAULT_DEBUG_CHANNEL(mshtml); 00043 00044 #define CONTENT_LENGTH "Content-Length" 00045 #define UTF16_STR "utf-16" 00046 00047 typedef struct { 00048 const nsIInputStreamVtbl *lpInputStreamVtbl; 00049 00050 LONG ref; 00051 00052 char buf[1024]; 00053 DWORD buf_size; 00054 } nsProtocolStream; 00055 00056 #define NSINSTREAM(x) ((nsIInputStream*) &(x)->lpInputStreamVtbl) 00057 00058 typedef struct { 00059 void (*destroy)(BSCallback*); 00060 HRESULT (*init_bindinfo)(BSCallback*); 00061 HRESULT (*start_binding)(BSCallback*); 00062 HRESULT (*stop_binding)(BSCallback*,HRESULT); 00063 HRESULT (*read_data)(BSCallback*,IStream*); 00064 HRESULT (*on_progress)(BSCallback*,ULONG,LPCWSTR); 00065 HRESULT (*on_response)(BSCallback*,DWORD,LPCWSTR); 00066 } BSCallbackVtbl; 00067 00068 struct BSCallback { 00069 const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl; 00070 const IServiceProviderVtbl *lpServiceProviderVtbl; 00071 const IHttpNegotiate2Vtbl *lpHttpNegotiate2Vtbl; 00072 const IInternetBindInfoVtbl *lpInternetBindInfoVtbl; 00073 00074 const BSCallbackVtbl *vtbl; 00075 00076 LONG ref; 00077 00078 LPWSTR headers; 00079 HGLOBAL post_data; 00080 ULONG post_data_len; 00081 ULONG readed; 00082 DWORD bindf; 00083 BOOL bindinfo_ready; 00084 00085 IMoniker *mon; 00086 IBinding *binding; 00087 00088 HTMLDocumentNode *doc; 00089 00090 struct list entry; 00091 }; 00092 00093 #define NSINSTREAM_THIS(iface) DEFINE_THIS(nsProtocolStream, InputStream, iface) 00094 00095 static nsresult NSAPI nsInputStream_QueryInterface(nsIInputStream *iface, nsIIDRef riid, 00096 nsQIResult result) 00097 { 00098 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00099 00100 *result = NULL; 00101 00102 if(IsEqualGUID(&IID_nsISupports, riid)) { 00103 TRACE("(%p)->(IID_nsISupports %p)\n", This, result); 00104 *result = NSINSTREAM(This); 00105 }else if(IsEqualGUID(&IID_nsIInputStream, riid)) { 00106 TRACE("(%p)->(IID_nsIInputStream %p)\n", This, result); 00107 *result = NSINSTREAM(This); 00108 } 00109 00110 if(*result) { 00111 nsIInputStream_AddRef(NSINSTREAM(This)); 00112 return NS_OK; 00113 } 00114 00115 WARN("unsupported interface %s\n", debugstr_guid(riid)); 00116 return NS_NOINTERFACE; 00117 } 00118 00119 static nsrefcnt NSAPI nsInputStream_AddRef(nsIInputStream *iface) 00120 { 00121 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00122 LONG ref = InterlockedIncrement(&This->ref); 00123 00124 TRACE("(%p) ref=%d\n", This, ref); 00125 00126 return ref; 00127 } 00128 00129 00130 static nsrefcnt NSAPI nsInputStream_Release(nsIInputStream *iface) 00131 { 00132 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00133 LONG ref = InterlockedDecrement(&This->ref); 00134 00135 TRACE("(%p) ref=%d\n", This, ref); 00136 00137 if(!ref) 00138 heap_free(This); 00139 00140 return ref; 00141 } 00142 00143 static nsresult NSAPI nsInputStream_Close(nsIInputStream *iface) 00144 { 00145 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00146 FIXME("(%p)\n", This); 00147 return NS_ERROR_NOT_IMPLEMENTED; 00148 } 00149 00150 static nsresult NSAPI nsInputStream_Available(nsIInputStream *iface, PRUint32 *_retval) 00151 { 00152 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00153 FIXME("(%p)->(%p)\n", This, _retval); 00154 return NS_ERROR_NOT_IMPLEMENTED; 00155 } 00156 00157 static nsresult NSAPI nsInputStream_Read(nsIInputStream *iface, char *aBuf, PRUint32 aCount, 00158 PRUint32 *_retval) 00159 { 00160 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00161 DWORD read = aCount; 00162 00163 TRACE("(%p)->(%p %d %p)\n", This, aBuf, aCount, _retval); 00164 00165 if(read > This->buf_size) 00166 read = This->buf_size; 00167 00168 if(read) { 00169 memcpy(aBuf, This->buf, read); 00170 if(read < This->buf_size) 00171 memmove(This->buf, This->buf+read, This->buf_size-read); 00172 This->buf_size -= read; 00173 } 00174 00175 *_retval = read; 00176 return NS_OK; 00177 } 00178 00179 static nsresult NSAPI nsInputStream_ReadSegments(nsIInputStream *iface, 00180 nsresult (WINAPI *aWriter)(nsIInputStream*,void*,const char*,PRUint32,PRUint32,PRUint32*), 00181 void *aClousure, PRUint32 aCount, PRUint32 *_retval) 00182 { 00183 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00184 PRUint32 written = 0; 00185 nsresult nsres; 00186 00187 TRACE("(%p)->(%p %p %d %p)\n", This, aWriter, aClousure, aCount, _retval); 00188 00189 if(!This->buf_size) 00190 return S_OK; 00191 00192 if(aCount > This->buf_size) 00193 aCount = This->buf_size; 00194 00195 nsres = aWriter(NSINSTREAM(This), aClousure, This->buf, 0, aCount, &written); 00196 if(NS_FAILED(nsres)) 00197 TRACE("aWritter failed: %08x\n", nsres); 00198 else if(written != This->buf_size) 00199 FIXME("written %d != buf_size %d\n", written, This->buf_size); 00200 00201 This->buf_size -= written; 00202 00203 *_retval = written; 00204 return nsres; 00205 } 00206 00207 static nsresult NSAPI nsInputStream_IsNonBlocking(nsIInputStream *iface, PRBool *_retval) 00208 { 00209 nsProtocolStream *This = NSINSTREAM_THIS(iface); 00210 FIXME("(%p)->(%p)\n", This, _retval); 00211 return NS_ERROR_NOT_IMPLEMENTED; 00212 } 00213 00214 #undef NSINSTREAM_THIS 00215 00216 static const nsIInputStreamVtbl nsInputStreamVtbl = { 00217 nsInputStream_QueryInterface, 00218 nsInputStream_AddRef, 00219 nsInputStream_Release, 00220 nsInputStream_Close, 00221 nsInputStream_Available, 00222 nsInputStream_Read, 00223 nsInputStream_ReadSegments, 00224 nsInputStream_IsNonBlocking 00225 }; 00226 00227 static nsProtocolStream *create_nsprotocol_stream(void) 00228 { 00229 nsProtocolStream *ret = heap_alloc(sizeof(nsProtocolStream)); 00230 00231 ret->lpInputStreamVtbl = &nsInputStreamVtbl; 00232 ret->ref = 1; 00233 ret->buf_size = 0; 00234 00235 return ret; 00236 } 00237 00238 #define STATUSCLB_THIS(iface) DEFINE_THIS(BSCallback, BindStatusCallback, iface) 00239 00240 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, 00241 REFIID riid, void **ppv) 00242 { 00243 BSCallback *This = STATUSCLB_THIS(iface); 00244 00245 *ppv = NULL; 00246 if(IsEqualGUID(&IID_IUnknown, riid)) { 00247 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv); 00248 *ppv = STATUSCLB(This); 00249 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) { 00250 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv); 00251 *ppv = STATUSCLB(This); 00252 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { 00253 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); 00254 *ppv = SERVPROV(This); 00255 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) { 00256 TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv); 00257 *ppv = HTTPNEG(This); 00258 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) { 00259 TRACE("(%p)->(IID_IHttpNegotiate2 %p)\n", This, ppv); 00260 *ppv = HTTPNEG(This); 00261 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) { 00262 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv); 00263 *ppv = BINDINFO(This); 00264 } 00265 00266 if(*ppv) { 00267 IBindStatusCallback_AddRef(STATUSCLB(This)); 00268 return S_OK; 00269 } 00270 00271 TRACE("Unsupported riid = %s\n", debugstr_guid(riid)); 00272 return E_NOINTERFACE; 00273 } 00274 00275 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface) 00276 { 00277 BSCallback *This = STATUSCLB_THIS(iface); 00278 LONG ref = InterlockedIncrement(&This->ref); 00279 00280 TRACE("(%p) ref = %d\n", This, ref); 00281 00282 return ref; 00283 } 00284 00285 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface) 00286 { 00287 BSCallback *This = STATUSCLB_THIS(iface); 00288 LONG ref = InterlockedDecrement(&This->ref); 00289 00290 TRACE("(%p) ref = %d\n", This, ref); 00291 00292 if(!ref) { 00293 if(This->post_data) 00294 GlobalFree(This->post_data); 00295 if(This->mon) 00296 IMoniker_Release(This->mon); 00297 if(This->binding) 00298 IBinding_Release(This->binding); 00299 list_remove(&This->entry); 00300 heap_free(This->headers); 00301 00302 This->vtbl->destroy(This); 00303 } 00304 00305 return ref; 00306 } 00307 00308 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, 00309 DWORD dwReserved, IBinding *pbind) 00310 { 00311 BSCallback *This = STATUSCLB_THIS(iface); 00312 00313 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind); 00314 00315 IBinding_AddRef(pbind); 00316 This->binding = pbind; 00317 00318 if(This->doc) 00319 list_add_head(&This->doc->bindings, &This->entry); 00320 00321 return This->vtbl->start_binding(This); 00322 } 00323 00324 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) 00325 { 00326 BSCallback *This = STATUSCLB_THIS(iface); 00327 FIXME("(%p)->(%p)\n", This, pnPriority); 00328 return E_NOTIMPL; 00329 } 00330 00331 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved) 00332 { 00333 BSCallback *This = STATUSCLB_THIS(iface); 00334 FIXME("(%p)->(%d)\n", This, reserved); 00335 return E_NOTIMPL; 00336 } 00337 00338 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, 00339 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) 00340 { 00341 BSCallback *This = STATUSCLB_THIS(iface); 00342 00343 TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, 00344 debugstr_w(szStatusText)); 00345 00346 return This->vtbl->on_progress(This, ulStatusCode, szStatusText); 00347 } 00348 00349 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, 00350 HRESULT hresult, LPCWSTR szError) 00351 { 00352 BSCallback *This = STATUSCLB_THIS(iface); 00353 HRESULT hres; 00354 00355 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); 00356 00357 /* NOTE: IE7 calls GetBindResult here */ 00358 00359 hres = This->vtbl->stop_binding(This, hresult); 00360 00361 if(This->binding) { 00362 IBinding_Release(This->binding); 00363 This->binding = NULL; 00364 } 00365 00366 list_remove(&This->entry); 00367 This->doc = NULL; 00368 00369 return hres; 00370 } 00371 00372 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, 00373 DWORD *grfBINDF, BINDINFO *pbindinfo) 00374 { 00375 BSCallback *This = STATUSCLB_THIS(iface); 00376 DWORD size; 00377 00378 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); 00379 00380 if(!This->bindinfo_ready) { 00381 HRESULT hres; 00382 00383 hres = This->vtbl->init_bindinfo(This); 00384 if(FAILED(hres)) 00385 return hres; 00386 00387 This->bindinfo_ready = TRUE; 00388 } 00389 00390 *grfBINDF = This->bindf; 00391 00392 size = pbindinfo->cbSize; 00393 memset(pbindinfo, 0, size); 00394 pbindinfo->cbSize = size; 00395 00396 pbindinfo->cbstgmedData = This->post_data_len; 00397 pbindinfo->dwCodePage = CP_UTF8; 00398 pbindinfo->dwOptions = 0x80000; 00399 00400 if(This->post_data) { 00401 pbindinfo->dwBindVerb = BINDVERB_POST; 00402 00403 pbindinfo->stgmedData.tymed = TYMED_HGLOBAL; 00404 pbindinfo->stgmedData.u.hGlobal = This->post_data; 00405 pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)STATUSCLB(This); 00406 IBindStatusCallback_AddRef(STATUSCLB(This)); 00407 } 00408 00409 return S_OK; 00410 } 00411 00412 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, 00413 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) 00414 { 00415 BSCallback *This = STATUSCLB_THIS(iface); 00416 00417 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); 00418 00419 return This->vtbl->read_data(This, pstgmed->u.pstm); 00420 } 00421 00422 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, 00423 REFIID riid, IUnknown *punk) 00424 { 00425 BSCallback *This = STATUSCLB_THIS(iface); 00426 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk); 00427 return E_NOTIMPL; 00428 } 00429 00430 #undef STATUSCLB_THIS 00431 00432 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { 00433 BindStatusCallback_QueryInterface, 00434 BindStatusCallback_AddRef, 00435 BindStatusCallback_Release, 00436 BindStatusCallback_OnStartBinding, 00437 BindStatusCallback_GetPriority, 00438 BindStatusCallback_OnLowResource, 00439 BindStatusCallback_OnProgress, 00440 BindStatusCallback_OnStopBinding, 00441 BindStatusCallback_GetBindInfo, 00442 BindStatusCallback_OnDataAvailable, 00443 BindStatusCallback_OnObjectAvailable 00444 }; 00445 00446 #define HTTPNEG_THIS(iface) DEFINE_THIS(BSCallback, HttpNegotiate2, iface) 00447 00448 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, 00449 REFIID riid, void **ppv) 00450 { 00451 BSCallback *This = HTTPNEG_THIS(iface); 00452 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); 00453 } 00454 00455 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface) 00456 { 00457 BSCallback *This = HTTPNEG_THIS(iface); 00458 return IBindStatusCallback_AddRef(STATUSCLB(This)); 00459 } 00460 00461 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface) 00462 { 00463 BSCallback *This = HTTPNEG_THIS(iface); 00464 return IBindStatusCallback_Release(STATUSCLB(This)); 00465 } 00466 00467 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, 00468 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) 00469 { 00470 BSCallback *This = HTTPNEG_THIS(iface); 00471 DWORD size; 00472 00473 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), 00474 dwReserved, pszAdditionalHeaders); 00475 00476 if(!This->headers) { 00477 *pszAdditionalHeaders = NULL; 00478 return S_OK; 00479 } 00480 00481 size = (strlenW(This->headers)+1)*sizeof(WCHAR); 00482 *pszAdditionalHeaders = CoTaskMemAlloc(size); 00483 memcpy(*pszAdditionalHeaders, This->headers, size); 00484 00485 return S_OK; 00486 } 00487 00488 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode, 00489 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) 00490 { 00491 BSCallback *This = HTTPNEG_THIS(iface); 00492 00493 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders), 00494 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders); 00495 00496 return This->vtbl->on_response(This, dwResponseCode, szResponseHeaders); 00497 } 00498 00499 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface, 00500 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved) 00501 { 00502 BSCallback *This = HTTPNEG_THIS(iface); 00503 FIXME("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved); 00504 return E_NOTIMPL; 00505 } 00506 00507 #undef HTTPNEG 00508 00509 static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl = { 00510 HttpNegotiate_QueryInterface, 00511 HttpNegotiate_AddRef, 00512 HttpNegotiate_Release, 00513 HttpNegotiate_BeginningTransaction, 00514 HttpNegotiate_OnResponse, 00515 HttpNegotiate_GetRootSecurityId 00516 }; 00517 00518 #define BINDINFO_THIS(iface) DEFINE_THIS(BSCallback, InternetBindInfo, iface) 00519 00520 static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface, 00521 REFIID riid, void **ppv) 00522 { 00523 BSCallback *This = BINDINFO_THIS(iface); 00524 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); 00525 } 00526 00527 static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface) 00528 { 00529 BSCallback *This = BINDINFO_THIS(iface); 00530 return IBindStatusCallback_AddRef(STATUSCLB(This)); 00531 } 00532 00533 static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface) 00534 { 00535 BSCallback *This = BINDINFO_THIS(iface); 00536 return IBindStatusCallback_Release(STATUSCLB(This)); 00537 } 00538 00539 static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface, 00540 DWORD *grfBINDF, BINDINFO *pbindinfo) 00541 { 00542 BSCallback *This = BINDINFO_THIS(iface); 00543 FIXME("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); 00544 return E_NOTIMPL; 00545 } 00546 00547 static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface, 00548 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched) 00549 { 00550 BSCallback *This = BINDINFO_THIS(iface); 00551 FIXME("(%p)->(%u %p %u %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched); 00552 return E_NOTIMPL; 00553 } 00554 00555 #undef BINDINFO_THIS 00556 00557 static const IInternetBindInfoVtbl InternetBindInfoVtbl = { 00558 InternetBindInfo_QueryInterface, 00559 InternetBindInfo_AddRef, 00560 InternetBindInfo_Release, 00561 InternetBindInfo_GetBindInfo, 00562 InternetBindInfo_GetBindString 00563 }; 00564 00565 #define SERVPROV_THIS(iface) DEFINE_THIS(BSCallback, ServiceProvider, iface) 00566 00567 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface, 00568 REFIID riid, void **ppv) 00569 { 00570 BSCallback *This = SERVPROV_THIS(iface); 00571 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); 00572 } 00573 00574 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface) 00575 { 00576 BSCallback *This = SERVPROV_THIS(iface); 00577 return IBindStatusCallback_AddRef(STATUSCLB(This)); 00578 } 00579 00580 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface) 00581 { 00582 BSCallback *This = SERVPROV_THIS(iface); 00583 return IBindStatusCallback_Release(STATUSCLB(This)); 00584 } 00585 00586 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface, 00587 REFGUID guidService, REFIID riid, void **ppv) 00588 { 00589 BSCallback *This = SERVPROV_THIS(iface); 00590 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); 00591 return E_NOINTERFACE; 00592 } 00593 00594 #undef SERVPROV_THIS 00595 00596 static const IServiceProviderVtbl ServiceProviderVtbl = { 00597 BSCServiceProvider_QueryInterface, 00598 BSCServiceProvider_AddRef, 00599 BSCServiceProvider_Release, 00600 BSCServiceProvider_QueryService 00601 }; 00602 00603 static void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMoniker *mon, DWORD bindf) 00604 { 00605 This->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl; 00606 This->lpServiceProviderVtbl = &ServiceProviderVtbl; 00607 This->lpHttpNegotiate2Vtbl = &HttpNegotiate2Vtbl; 00608 This->lpInternetBindInfoVtbl = &InternetBindInfoVtbl; 00609 This->vtbl = vtbl; 00610 This->ref = 1; 00611 This->bindf = bindf; 00612 00613 list_init(&This->entry); 00614 00615 if(mon) 00616 IMoniker_AddRef(mon); 00617 This->mon = mon; 00618 } 00619 00620 /* Calls undocumented 84 cmd of CGID_ShellDocView */ 00621 static void call_docview_84(HTMLDocumentObj *doc) 00622 { 00623 IOleCommandTarget *olecmd; 00624 VARIANT var; 00625 HRESULT hres; 00626 00627 if(!doc->client) 00628 return; 00629 00630 hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd); 00631 if(FAILED(hres)) 00632 return; 00633 00634 VariantInit(&var); 00635 hres = IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 84, 0, NULL, &var); 00636 IOleCommandTarget_Release(olecmd); 00637 if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL) 00638 FIXME("handle result\n"); 00639 } 00640 00641 static void parse_post_data(nsIInputStream *post_data_stream, LPWSTR *headers_ret, 00642 HGLOBAL *post_data_ret, ULONG *post_data_len_ret) 00643 { 00644 PRUint32 post_data_len = 0, available = 0; 00645 HGLOBAL post_data = NULL; 00646 LPWSTR headers = NULL; 00647 DWORD headers_len = 0, len; 00648 const char *ptr, *ptr2, *post_data_end; 00649 00650 nsIInputStream_Available(post_data_stream, &available); 00651 post_data = GlobalAlloc(0, available+1); 00652 nsIInputStream_Read(post_data_stream, post_data, available, &post_data_len); 00653 00654 TRACE("post_data = %s\n", debugstr_an(post_data, post_data_len)); 00655 00656 ptr = ptr2 = post_data; 00657 post_data_end = (const char*)post_data+post_data_len; 00658 00659 while(ptr < post_data_end && (*ptr != '\r' || ptr[1] != '\n')) { 00660 while(ptr < post_data_end && (*ptr != '\r' || ptr[1] != '\n')) 00661 ptr++; 00662 00663 if(!*ptr) { 00664 FIXME("*ptr = 0\n"); 00665 return; 00666 } 00667 00668 ptr += 2; 00669 00670 if(ptr-ptr2 >= sizeof(CONTENT_LENGTH) 00671 && CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, 00672 CONTENT_LENGTH, sizeof(CONTENT_LENGTH)-1, 00673 ptr2, sizeof(CONTENT_LENGTH)-1) == CSTR_EQUAL) { 00674 ptr2 = ptr; 00675 continue; 00676 } 00677 00678 len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, NULL, 0); 00679 00680 if(headers) 00681 headers = heap_realloc(headers,(headers_len+len+1)*sizeof(WCHAR)); 00682 else 00683 headers = heap_alloc((len+1)*sizeof(WCHAR)); 00684 00685 len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, headers+headers_len, len); 00686 headers_len += len; 00687 00688 ptr2 = ptr; 00689 } 00690 00691 headers[headers_len] = 0; 00692 *headers_ret = headers; 00693 00694 if(ptr >= post_data_end-2) { 00695 GlobalFree(post_data); 00696 return; 00697 } 00698 00699 ptr += 2; 00700 00701 if(headers_len) { 00702 post_data_len -= ptr-(const char*)post_data; 00703 memmove(post_data, ptr, post_data_len); 00704 post_data = GlobalReAlloc(post_data, post_data_len+1, 0); 00705 } 00706 00707 *post_data_ret = post_data; 00708 *post_data_len_ret = post_data_len; 00709 } 00710 00711 HRESULT start_binding(HTMLWindow *window, HTMLDocumentNode *doc, BSCallback *bscallback, IBindCtx *bctx) 00712 { 00713 IStream *str = NULL; 00714 HRESULT hres; 00715 00716 bscallback->doc = doc; 00717 00718 /* NOTE: IE7 calls IsSystemMoniker here*/ 00719 00720 if(window) { 00721 if(bscallback->mon != window->mon) 00722 set_current_mon(window, bscallback->mon); 00723 call_docview_84(window->doc_obj); 00724 } 00725 00726 if(bctx) { 00727 RegisterBindStatusCallback(bctx, STATUSCLB(bscallback), NULL, 0); 00728 IBindCtx_AddRef(bctx); 00729 }else { 00730 hres = CreateAsyncBindCtx(0, STATUSCLB(bscallback), NULL, &bctx); 00731 if(FAILED(hres)) { 00732 WARN("CreateAsyncBindCtx failed: %08x\n", hres); 00733 bscallback->vtbl->stop_binding(bscallback, hres); 00734 return hres; 00735 } 00736 } 00737 00738 hres = IMoniker_BindToStorage(bscallback->mon, bctx, NULL, &IID_IStream, (void**)&str); 00739 IBindCtx_Release(bctx); 00740 if(FAILED(hres)) { 00741 WARN("BindToStorage failed: %08x\n", hres); 00742 bscallback->vtbl->stop_binding(bscallback, hres); 00743 return hres; 00744 } 00745 00746 if(str) 00747 IStream_Release(str); 00748 00749 IMoniker_Release(bscallback->mon); 00750 bscallback->mon = NULL; 00751 00752 return S_OK; 00753 } 00754 00755 typedef struct { 00756 BSCallback bsc; 00757 00758 DWORD size; 00759 BYTE *buf; 00760 HRESULT hres; 00761 } BufferBSC; 00762 00763 #define BUFFERBSC_THIS(bsc) ((BufferBSC*) bsc) 00764 00765 static void BufferBSC_destroy(BSCallback *bsc) 00766 { 00767 BufferBSC *This = BUFFERBSC_THIS(bsc); 00768 00769 heap_free(This->buf); 00770 heap_free(This); 00771 } 00772 00773 static HRESULT BufferBSC_init_bindinfo(BSCallback *bsc) 00774 { 00775 return S_OK; 00776 } 00777 00778 static HRESULT BufferBSC_start_binding(BSCallback *bsc) 00779 { 00780 return S_OK; 00781 } 00782 00783 static HRESULT BufferBSC_stop_binding(BSCallback *bsc, HRESULT result) 00784 { 00785 BufferBSC *This = BUFFERBSC_THIS(bsc); 00786 00787 This->hres = result; 00788 00789 if(FAILED(result)) { 00790 heap_free(This->buf); 00791 This->buf = NULL; 00792 This->size = 0; 00793 } 00794 00795 return S_OK; 00796 } 00797 00798 static HRESULT BufferBSC_read_data(BSCallback *bsc, IStream *stream) 00799 { 00800 BufferBSC *This = BUFFERBSC_THIS(bsc); 00801 DWORD readed; 00802 HRESULT hres; 00803 00804 if(!This->buf) { 00805 This->size = 128; 00806 This->buf = heap_alloc(This->size); 00807 } 00808 00809 do { 00810 if(This->bsc.readed == This->size) { 00811 This->size <<= 1; 00812 This->buf = heap_realloc(This->buf, This->size); 00813 } 00814 00815 readed = 0; 00816 hres = IStream_Read(stream, This->buf+This->bsc.readed, This->size-This->bsc.readed, &readed); 00817 This->bsc.readed += readed; 00818 }while(hres == S_OK); 00819 00820 return S_OK; 00821 } 00822 00823 static HRESULT BufferBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text) 00824 { 00825 return S_OK; 00826 } 00827 00828 static HRESULT BufferBSC_on_response(BSCallback *bsc, DWORD response_code, 00829 LPCWSTR response_headers) 00830 { 00831 return S_OK; 00832 } 00833 00834 #undef BUFFERBSC_THIS 00835 00836 static const BSCallbackVtbl BufferBSCVtbl = { 00837 BufferBSC_destroy, 00838 BufferBSC_init_bindinfo, 00839 BufferBSC_start_binding, 00840 BufferBSC_stop_binding, 00841 BufferBSC_read_data, 00842 BufferBSC_on_progress, 00843 BufferBSC_on_response 00844 }; 00845 00846 00847 static BufferBSC *create_bufferbsc(IMoniker *mon) 00848 { 00849 BufferBSC *ret = heap_alloc_zero(sizeof(*ret)); 00850 00851 init_bscallback(&ret->bsc, &BufferBSCVtbl, mon, 0); 00852 ret->hres = E_FAIL; 00853 00854 return ret; 00855 } 00856 00857 HRESULT bind_mon_to_buffer(HTMLDocumentNode *doc, IMoniker *mon, void **buf, DWORD *size) 00858 { 00859 BufferBSC *bsc = create_bufferbsc(mon); 00860 HRESULT hres; 00861 00862 *buf = NULL; 00863 00864 hres = start_binding(NULL, doc, &bsc->bsc, NULL); 00865 if(SUCCEEDED(hres)) { 00866 hres = bsc->hres; 00867 if(SUCCEEDED(hres)) { 00868 *buf = bsc->buf; 00869 bsc->buf = NULL; 00870 *size = bsc->bsc.readed; 00871 bsc->size = 0; 00872 } 00873 } 00874 00875 IBindStatusCallback_Release(STATUSCLB(&bsc->bsc)); 00876 00877 return hres; 00878 } 00879 00880 struct nsChannelBSC { 00881 BSCallback bsc; 00882 00883 HTMLWindow *window; 00884 00885 nsChannel *nschannel; 00886 nsIStreamListener *nslistener; 00887 nsISupports *nscontext; 00888 00889 nsProtocolStream *nsstream; 00890 }; 00891 00892 static void on_start_nsrequest(nsChannelBSC *This) 00893 { 00894 nsresult nsres; 00895 00896 /* FIXME: it's needed for http connections from BindToObject. */ 00897 if(!This->nschannel->response_status) 00898 This->nschannel->response_status = 200; 00899 00900 nsres = nsIStreamListener_OnStartRequest(This->nslistener, 00901 (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext); 00902 if(NS_FAILED(nsres)) 00903 FIXME("OnStartRequest failed: %08x\n", nsres); 00904 } 00905 00906 static void on_stop_nsrequest(nsChannelBSC *This, HRESULT result) 00907 { 00908 nsresult nsres; 00909 00910 if(!This->nslistener) 00911 return; 00912 00913 if(!This->bsc.readed && SUCCEEDED(result)) { 00914 TRACE("No data read! Calling OnStartRequest\n"); 00915 on_start_nsrequest(This); 00916 } 00917 00918 nsres = nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel), 00919 This->nscontext, SUCCEEDED(result) ? NS_OK : NS_ERROR_FAILURE); 00920 if(NS_FAILED(nsres)) 00921 WARN("OnStopRequest failed: %08x\n", nsres); 00922 } 00923 00924 static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) 00925 { 00926 DWORD read; 00927 nsresult nsres; 00928 HRESULT hres; 00929 00930 if(!This->nslistener) { 00931 BYTE buf[1024]; 00932 00933 do { 00934 read = 0; 00935 hres = IStream_Read(stream, buf, sizeof(buf), &read); 00936 }while(hres == S_OK && read); 00937 00938 return S_OK; 00939 } 00940 00941 if(!This->nsstream) 00942 This->nsstream = create_nsprotocol_stream(); 00943 00944 do { 00945 read = 0; 00946 hres = IStream_Read(stream, This->nsstream->buf+This->nsstream->buf_size, 00947 sizeof(This->nsstream->buf)-This->nsstream->buf_size, &read); 00948 if(!read) 00949 break; 00950 00951 This->nsstream->buf_size += read; 00952 00953 if(!This->bsc.readed) { 00954 if(This->nsstream->buf_size >= 2 00955 && (BYTE)This->nsstream->buf[0] == 0xff 00956 && (BYTE)This->nsstream->buf[1] == 0xfe) 00957 This->nschannel->charset = heap_strdupA(UTF16_STR); 00958 00959 if(!This->nschannel->content_type) { 00960 WCHAR *mime; 00961 00962 hres = FindMimeFromData(NULL, NULL, This->nsstream->buf, This->nsstream->buf_size, NULL, 0, &mime, 0); 00963 if(FAILED(hres)) 00964 return hres; 00965 00966 TRACE("Found MIME %s\n", debugstr_w(mime)); 00967 00968 This->nschannel->content_type = heap_strdupWtoA(mime); 00969 CoTaskMemFree(mime); 00970 if(!This->nschannel->content_type) 00971 return E_OUTOFMEMORY; 00972 } 00973 00974 on_start_nsrequest(This); 00975 00976 if(This->window) { 00977 update_window_doc(This->window); 00978 if(This->window->readystate != READYSTATE_LOADING) 00979 set_ready_state(This->window, READYSTATE_LOADING); 00980 } 00981 } 00982 00983 This->bsc.readed += This->nsstream->buf_size; 00984 00985 nsres = nsIStreamListener_OnDataAvailable(This->nslistener, 00986 (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext, 00987 NSINSTREAM(This->nsstream), This->bsc.readed-This->nsstream->buf_size, 00988 This->nsstream->buf_size); 00989 if(NS_FAILED(nsres)) 00990 ERR("OnDataAvailable failed: %08x\n", nsres); 00991 00992 if(This->nsstream->buf_size == sizeof(This->nsstream->buf)) { 00993 ERR("buffer is full\n"); 00994 break; 00995 } 00996 }while(hres == S_OK); 00997 00998 return S_OK; 00999 } 01000 01001 static void add_nsrequest(nsChannelBSC *This) 01002 { 01003 nsresult nsres; 01004 01005 if(!This->nschannel || !This->nschannel->load_group) 01006 return; 01007 01008 nsres = nsILoadGroup_AddRequest(This->nschannel->load_group, 01009 (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext); 01010 01011 if(NS_FAILED(nsres)) 01012 ERR("AddRequest failed:%08x\n", nsres); 01013 } 01014 01015 #define NSCHANNELBSC_THIS(bsc) ((nsChannelBSC*) bsc) 01016 01017 static void nsChannelBSC_destroy(BSCallback *bsc) 01018 { 01019 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); 01020 01021 if(This->nschannel) 01022 nsIChannel_Release(NSCHANNEL(This->nschannel)); 01023 if(This->nslistener) 01024 nsIStreamListener_Release(This->nslistener); 01025 if(This->nscontext) 01026 nsISupports_Release(This->nscontext); 01027 if(This->nsstream) 01028 nsIInputStream_Release(NSINSTREAM(This->nsstream)); 01029 heap_free(This); 01030 } 01031 01032 static HRESULT nsChannelBSC_start_binding(BSCallback *bsc) 01033 { 01034 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); 01035 01036 add_nsrequest(This); 01037 01038 return S_OK; 01039 } 01040 01041 static HRESULT nsChannelBSC_init_bindinfo(BSCallback *bsc) 01042 { 01043 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); 01044 01045 if(This->nschannel && This->nschannel->post_data_stream) { 01046 parse_post_data(This->nschannel->post_data_stream, &This->bsc.headers, &This->bsc.post_data, &This->bsc.post_data_len); 01047 TRACE("headers = %s post_data = %s\n", debugstr_w(This->bsc.headers), 01048 debugstr_an(This->bsc.post_data, This->bsc.post_data_len)); 01049 } 01050 01051 return S_OK; 01052 } 01053 01054 static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result) 01055 { 01056 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); 01057 01058 on_stop_nsrequest(This, result); 01059 01060 if(This->nslistener) { 01061 if(This->nschannel->load_group) { 01062 nsresult nsres; 01063 01064 nsres = nsILoadGroup_RemoveRequest(This->nschannel->load_group, 01065 (nsIRequest*)NSCHANNEL(This->nschannel), NULL, NS_OK); 01066 if(NS_FAILED(nsres)) 01067 ERR("RemoveRequest failed: %08x\n", nsres); 01068 } 01069 } 01070 01071 return S_OK; 01072 } 01073 01074 static HRESULT nsChannelBSC_read_data(BSCallback *bsc, IStream *stream) 01075 { 01076 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); 01077 01078 return read_stream_data(This, stream); 01079 } 01080 01081 static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text) 01082 { 01083 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); 01084 01085 switch(status_code) { 01086 case BINDSTATUS_MIMETYPEAVAILABLE: 01087 if(!This->nschannel) 01088 return S_OK; 01089 01090 heap_free(This->nschannel->content_type); 01091 This->nschannel->content_type = heap_strdupWtoA(status_text); 01092 break; 01093 case BINDSTATUS_REDIRECTING: 01094 TRACE("redirect to %s\n", debugstr_w(status_text)); 01095 01096 /* FIXME: We should find a better way to handle this */ 01097 set_wine_url(This->nschannel->uri, status_text); 01098 } 01099 01100 return S_OK; 01101 } 01102 01103 static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code, 01104 LPCWSTR response_headers) 01105 { 01106 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc); 01107 01108 This->nschannel->response_status = response_code; 01109 01110 if(response_headers) { 01111 const WCHAR *hdr_start, *hdr_end; 01112 01113 hdr_start = strchrW(response_headers, '\r'); 01114 while(hdr_start) { 01115 const WCHAR *colon; 01116 struct ResponseHeader *new_header; 01117 int len; 01118 01119 hdr_start += 2; 01120 hdr_end = strchrW(hdr_start, '\r'); 01121 if(!hdr_end) { 01122 WARN("Header doesn't end with CRLF: %s\n", wine_dbgstr_w(hdr_start)); 01123 break; 01124 } 01125 if(hdr_end == hdr_start) 01126 break; 01127 01128 for(colon = hdr_start; *colon != ':' && colon != hdr_end; ++colon); 01129 if(*colon != ':') { 01130 WARN("Header missing colon: %s\n", wine_dbgstr_w(hdr_start)); 01131 hdr_start = strchrW(hdr_start, '\r'); 01132 continue; 01133 } 01134 01135 new_header = heap_alloc(sizeof(struct ResponseHeader)); 01136 if(!new_header) 01137 return E_OUTOFMEMORY; 01138 01139 len = colon - hdr_start; 01140 new_header->header = heap_alloc((len + 1) * sizeof(WCHAR)); 01141 if(!new_header->header) { 01142 heap_free(new_header); 01143 return E_OUTOFMEMORY; 01144 } 01145 memcpy(new_header->header, hdr_start, len * sizeof(WCHAR)); 01146 new_header->header[len] = 0; 01147 01148 colon++; 01149 while(*colon == ' ') 01150 colon++; 01151 01152 len = hdr_end - colon; 01153 new_header->data = heap_alloc((len + 1) * sizeof(WCHAR)); 01154 if(!new_header->data) { 01155 heap_free(new_header->header); 01156 heap_free(new_header); 01157 return E_OUTOFMEMORY; 01158 } 01159 memcpy(new_header->data, colon, len * sizeof(WCHAR)); 01160 new_header->data[len] = 0; 01161 01162 list_add_head(&This->nschannel->response_headers, &new_header->entry); 01163 TRACE("Adding header to list: (%s):(%s)\n", wine_dbgstr_w(new_header->header), wine_dbgstr_w(new_header->data)); 01164 01165 hdr_start = strchrW(hdr_start, '\r'); 01166 } 01167 } 01168 01169 return S_OK; 01170 } 01171 01172 #undef NSCHANNELBSC_THIS 01173 01174 static const BSCallbackVtbl nsChannelBSCVtbl = { 01175 nsChannelBSC_destroy, 01176 nsChannelBSC_init_bindinfo, 01177 nsChannelBSC_start_binding, 01178 nsChannelBSC_stop_binding, 01179 nsChannelBSC_read_data, 01180 nsChannelBSC_on_progress, 01181 nsChannelBSC_on_response 01182 }; 01183 01184 HRESULT create_channelbsc(IMoniker *mon, WCHAR *headers, BYTE *post_data, DWORD post_data_size, nsChannelBSC **retval) 01185 { 01186 nsChannelBSC *ret; 01187 01188 ret = heap_alloc_zero(sizeof(*ret)); 01189 if(!ret) 01190 return E_OUTOFMEMORY; 01191 01192 init_bscallback(&ret->bsc, &nsChannelBSCVtbl, mon, BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA); 01193 01194 if(headers) { 01195 ret->bsc.headers = heap_strdupW(headers); 01196 if(!ret->bsc.headers) { 01197 IBindStatusCallback_Release(STATUSCLB(&ret->bsc)); 01198 return E_OUTOFMEMORY; 01199 } 01200 } 01201 01202 if(post_data) { 01203 ret->bsc.post_data = GlobalAlloc(0, post_data_size); 01204 if(!ret->bsc.post_data) { 01205 heap_free(ret->bsc.headers); 01206 IBindStatusCallback_Release(STATUSCLB(&ret->bsc)); 01207 return E_OUTOFMEMORY; 01208 } 01209 01210 memcpy(ret->bsc.post_data, post_data, post_data_size); 01211 ret->bsc.post_data_len = post_data_size; 01212 } 01213 01214 *retval = ret; 01215 return S_OK; 01216 } 01217 01218 IMoniker *get_channelbsc_mon(nsChannelBSC *This) 01219 { 01220 if(This->bsc.mon) 01221 IMoniker_AddRef(This->bsc.mon); 01222 return This->bsc.mon; 01223 } 01224 01225 void set_window_bscallback(HTMLWindow *window, nsChannelBSC *callback) 01226 { 01227 if(window->bscallback) { 01228 if(window->bscallback->bsc.binding) 01229 IBinding_Abort(window->bscallback->bsc.binding); 01230 window->bscallback->bsc.doc = NULL; 01231 window->bscallback->window = NULL; 01232 IBindStatusCallback_Release(STATUSCLB(&window->bscallback->bsc)); 01233 } 01234 01235 window->bscallback = callback; 01236 01237 if(callback) { 01238 callback->window = window; 01239 IBindStatusCallback_AddRef(STATUSCLB(&callback->bsc)); 01240 callback->bsc.doc = window->doc; 01241 } 01242 } 01243 01244 typedef struct { 01245 task_t header; 01246 HTMLWindow *window; 01247 nsChannelBSC *bscallback; 01248 } start_doc_binding_task_t; 01249 01250 static void start_doc_binding_proc(task_t *_task) 01251 { 01252 start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task; 01253 01254 start_binding(task->window, NULL, (BSCallback*)task->bscallback, NULL); 01255 IBindStatusCallback_Release(STATUSCLB(&task->bscallback->bsc)); 01256 } 01257 01258 HRESULT async_start_doc_binding(HTMLWindow *window, nsChannelBSC *bscallback) 01259 { 01260 start_doc_binding_task_t *task; 01261 01262 task = heap_alloc(sizeof(start_doc_binding_task_t)); 01263 if(!task) 01264 return E_OUTOFMEMORY; 01265 01266 task->window = window; 01267 task->bscallback = bscallback; 01268 IBindStatusCallback_AddRef(STATUSCLB(&bscallback->bsc)); 01269 01270 push_task(&task->header, start_doc_binding_proc, window->task_magic); 01271 return S_OK; 01272 } 01273 01274 void abort_document_bindings(HTMLDocumentNode *doc) 01275 { 01276 BSCallback *iter; 01277 01278 LIST_FOR_EACH_ENTRY(iter, &doc->bindings, BSCallback, entry) { 01279 if(iter->binding) 01280 IBinding_Abort(iter->binding); 01281 iter->doc = NULL; 01282 list_remove(&iter->entry); 01283 } 01284 } 01285 01286 HRESULT channelbsc_load_stream(nsChannelBSC *bscallback, IStream *stream) 01287 { 01288 HRESULT hres; 01289 01290 if(!bscallback->nschannel) { 01291 ERR("NULL nschannel\n"); 01292 return E_FAIL; 01293 } 01294 01295 bscallback->nschannel->content_type = heap_strdupA("text/html"); 01296 if(!bscallback->nschannel->content_type) 01297 return E_OUTOFMEMORY; 01298 01299 add_nsrequest(bscallback); 01300 01301 hres = read_stream_data(bscallback, stream); 01302 IBindStatusCallback_OnStopBinding(STATUSCLB(&bscallback->bsc), hres, ERROR_SUCCESS); 01303 01304 return hres; 01305 } 01306 01307 void channelbsc_set_channel(nsChannelBSC *This, nsChannel *channel, nsIStreamListener *listener, nsISupports *context) 01308 { 01309 nsIChannel_AddRef(NSCHANNEL(channel)); 01310 This->nschannel = channel; 01311 01312 nsIStreamListener_AddRef(listener); 01313 This->nslistener = listener; 01314 01315 if(context) { 01316 nsISupports_AddRef(context); 01317 This->nscontext = context; 01318 } 01319 } 01320 01321 HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url, 01322 nsIInputStream *post_data_stream, DWORD hlnf, BOOL *cancel) 01323 { 01324 IHlinkFrame *hlink_frame; 01325 nsChannelBSC *callback; 01326 IServiceProvider *sp; 01327 IBindCtx *bindctx; 01328 IMoniker *mon; 01329 IHlink *hlink; 01330 HRESULT hres; 01331 01332 *cancel = FALSE; 01333 01334 hres = IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IServiceProvider, 01335 (void**)&sp); 01336 if(FAILED(hres)) 01337 return S_OK; 01338 01339 hres = IServiceProvider_QueryService(sp, &IID_IHlinkFrame, &IID_IHlinkFrame, 01340 (void**)&hlink_frame); 01341 IServiceProvider_Release(sp); 01342 if(FAILED(hres)) 01343 return S_OK; 01344 01345 hres = create_channelbsc(NULL, NULL, NULL, 0, &callback); 01346 if(FAILED(hres)) { 01347 IHlinkFrame_Release(hlink_frame); 01348 return hres; 01349 } 01350 01351 if(post_data_stream) { 01352 parse_post_data(post_data_stream, &callback->bsc.headers, &callback->bsc.post_data, 01353 &callback->bsc.post_data_len); 01354 TRACE("headers = %s post_data = %s\n", debugstr_w(callback->bsc.headers), 01355 debugstr_an(callback->bsc.post_data, callback->bsc.post_data_len)); 01356 } 01357 01358 hres = CreateAsyncBindCtx(0, STATUSCLB(&callback->bsc), NULL, &bindctx); 01359 if(SUCCEEDED(hres)) 01360 hres = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER, 01361 &IID_IHlink, (LPVOID*)&hlink); 01362 01363 if(SUCCEEDED(hres)) 01364 hres = CreateURLMoniker(NULL, url, &mon); 01365 01366 if(SUCCEEDED(hres)) { 01367 IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, mon, NULL); 01368 01369 if(hlnf & HLNF_OPENINNEWWINDOW) { 01370 static const WCHAR wszBlank[] = {'_','b','l','a','n','k',0}; 01371 IHlink_SetTargetFrameName(hlink, wszBlank); /* FIXME */ 01372 } 01373 01374 hres = IHlinkFrame_Navigate(hlink_frame, hlnf, bindctx, STATUSCLB(&callback->bsc), hlink); 01375 IMoniker_Release(mon); 01376 *cancel = hres == S_OK; 01377 hres = S_OK; 01378 } 01379 01380 IHlinkFrame_Release(hlink_frame); 01381 IBindCtx_Release(bindctx); 01382 IBindStatusCallback_Release(STATUSCLB(&callback->bsc)); 01383 return hres; 01384 } 01385 01386 HRESULT navigate_url(HTMLWindow *window, const WCHAR *new_url, const WCHAR *base_url) 01387 { 01388 WCHAR url[INTERNET_MAX_URL_LENGTH]; 01389 nsWineURI *uri; 01390 HRESULT hres; 01391 01392 if(!new_url) { 01393 *url = 0; 01394 }else if(base_url) { 01395 DWORD len = 0; 01396 01397 hres = CoInternetCombineUrl(base_url, new_url, URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO, 01398 url, sizeof(url)/sizeof(WCHAR), &len, 0); 01399 if(FAILED(hres)) 01400 return hres; 01401 }else { 01402 strcpyW(url, new_url); 01403 } 01404 01405 if(window->doc_obj && window->doc_obj->hostui) { 01406 OLECHAR *translated_url = NULL; 01407 01408 hres = IDocHostUIHandler_TranslateUrl(window->doc_obj->hostui, 0, url, 01409 &translated_url); 01410 if(hres == S_OK) { 01411 TRACE("%08x %s -> %s\n", hres, debugstr_w(url), debugstr_w(translated_url)); 01412 strcpyW(url, translated_url); 01413 CoTaskMemFree(translated_url); 01414 } 01415 } 01416 01417 if(window->doc_obj && window == window->doc_obj->basedoc.window) { 01418 BOOL cancel; 01419 01420 hres = hlink_frame_navigate(&window->doc->basedoc, url, NULL, 0, &cancel); 01421 if(FAILED(hres)) 01422 return hres; 01423 01424 if(cancel) { 01425 TRACE("Navigation handled by hlink frame\n"); 01426 return S_OK; 01427 } 01428 } 01429 01430 hres = create_doc_uri(window, url, &uri); 01431 if(FAILED(hres)) 01432 return hres; 01433 01434 hres = load_nsuri(window, uri, NULL, LOAD_FLAGS_NONE); 01435 nsISupports_Release((nsISupports*)uri); 01436 return hres; 01437 } Generated on Sat May 26 2012 04:23:38 for ReactOS by
1.7.6.1
|