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

navigate.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 doxygen 1.7.6.1

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