2 * Copyright 2006-2007 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "mshtml_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
41 #define CONTENT_LENGTH "Content-Length"
42 #define UTF16_STR "utf-16"
45 const nsIInputStreamVtbl *lpInputStreamVtbl;
53 #define NSINSTREAM(x) ((nsIInputStream*) &(x)->lpInputStreamVtbl)
56 void (*destroy)(BSCallback*);
57 HRESULT (*start_binding)(BSCallback*);
58 HRESULT (*stop_binding)(BSCallback*,HRESULT);
59 HRESULT (*read_data)(BSCallback*,IStream*);
60 HRESULT (*on_progress)(BSCallback*,ULONG,LPCWSTR);
61 HRESULT (*on_response)(BSCallback*,DWORD);
65 const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl;
66 const IServiceProviderVtbl *lpServiceProviderVtbl;
67 const IHttpNegotiate2Vtbl *lpHttpNegotiate2Vtbl;
68 const IInternetBindInfoVtbl *lpInternetBindInfoVtbl;
70 const BSCallbackVtbl *vtbl;
88 #define NSINSTREAM_THIS(iface) DEFINE_THIS(nsProtocolStream, InputStream, iface)
90 static nsresult NSAPI nsInputStream_QueryInterface(nsIInputStream *iface, nsIIDRef riid,
93 nsProtocolStream *This = NSINSTREAM_THIS(iface);
97 if(IsEqualGUID(&IID_nsISupports, riid)) {
98 TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
99 *result = NSINSTREAM(This);
100 }else if(IsEqualGUID(&IID_nsIInputStream, riid)) {
101 TRACE("(%p)->(IID_nsIInputStream %p)\n", This, result);
102 *result = NSINSTREAM(This);
106 nsIInputStream_AddRef(NSINSTREAM(This));
110 WARN("unsupported interface %s\n", debugstr_guid(riid));
111 return NS_NOINTERFACE;
114 static nsrefcnt NSAPI nsInputStream_AddRef(nsIInputStream *iface)
116 nsProtocolStream *This = NSINSTREAM_THIS(iface);
117 LONG ref = InterlockedIncrement(&This->ref);
119 TRACE("(%p) ref=%d\n", This, ref);
125 static nsrefcnt NSAPI nsInputStream_Release(nsIInputStream *iface)
127 nsProtocolStream *This = NSINSTREAM_THIS(iface);
128 LONG ref = InterlockedDecrement(&This->ref);
130 TRACE("(%p) ref=%d\n", This, ref);
138 static nsresult NSAPI nsInputStream_Close(nsIInputStream *iface)
140 nsProtocolStream *This = NSINSTREAM_THIS(iface);
141 FIXME("(%p)\n", This);
142 return NS_ERROR_NOT_IMPLEMENTED;
145 static nsresult NSAPI nsInputStream_Available(nsIInputStream *iface, PRUint32 *_retval)
147 nsProtocolStream *This = NSINSTREAM_THIS(iface);
148 FIXME("(%p)->(%p)\n", This, _retval);
149 return NS_ERROR_NOT_IMPLEMENTED;
152 static nsresult NSAPI nsInputStream_Read(nsIInputStream *iface, char *aBuf, PRUint32 aCount,
155 nsProtocolStream *This = NSINSTREAM_THIS(iface);
158 TRACE("(%p)->(%p %d %p)\n", This, aBuf, aCount, _retval);
160 if(read > This->buf_size)
161 read = This->buf_size;
164 memcpy(aBuf, This->buf, read);
165 if(read < This->buf_size)
166 memmove(This->buf, This->buf+read, This->buf_size-read);
167 This->buf_size -= read;
174 static nsresult NSAPI nsInputStream_ReadSegments(nsIInputStream *iface,
175 nsresult (WINAPI *aWriter)(nsIInputStream*,void*,const char*,PRUint32,PRUint32,PRUint32*),
176 void *aClousure, PRUint32 aCount, PRUint32 *_retval)
178 nsProtocolStream *This = NSINSTREAM_THIS(iface);
179 PRUint32 written = 0;
182 TRACE("(%p)->(%p %p %d %p)\n", This, aWriter, aClousure, aCount, _retval);
187 if(aCount > This->buf_size)
188 aCount = This->buf_size;
190 nsres = aWriter(NSINSTREAM(This), aClousure, This->buf, 0, aCount, &written);
192 TRACE("aWritter failed: %08x\n", nsres);
193 else if(written != This->buf_size)
194 FIXME("written %d != buf_size %d\n", written, This->buf_size);
196 This->buf_size -= written;
202 static nsresult NSAPI nsInputStream_IsNonBlocking(nsIInputStream *iface, PRBool *_retval)
204 nsProtocolStream *This = NSINSTREAM_THIS(iface);
205 FIXME("(%p)->(%p)\n", This, _retval);
206 return NS_ERROR_NOT_IMPLEMENTED;
209 #undef NSINSTREAM_THIS
211 static const nsIInputStreamVtbl nsInputStreamVtbl = {
212 nsInputStream_QueryInterface,
213 nsInputStream_AddRef,
214 nsInputStream_Release,
216 nsInputStream_Available,
218 nsInputStream_ReadSegments,
219 nsInputStream_IsNonBlocking
222 static nsProtocolStream *create_nsprotocol_stream(void)
224 nsProtocolStream *ret = heap_alloc(sizeof(nsProtocolStream));
226 ret->lpInputStreamVtbl = &nsInputStreamVtbl;
233 #define STATUSCLB_THIS(iface) DEFINE_THIS(BSCallback, BindStatusCallback, iface)
235 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
236 REFIID riid, void **ppv)
238 BSCallback *This = STATUSCLB_THIS(iface);
241 if(IsEqualGUID(&IID_IUnknown, riid)) {
242 TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
243 *ppv = STATUSCLB(This);
244 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
245 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
246 *ppv = STATUSCLB(This);
247 }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
248 TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
249 *ppv = SERVPROV(This);
250 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
251 TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv);
252 *ppv = HTTPNEG(This);
253 }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
254 TRACE("(%p)->(IID_IHttpNegotiate2 %p)\n", This, ppv);
255 *ppv = HTTPNEG(This);
256 }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
257 TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
258 *ppv = BINDINFO(This);
262 IBindStatusCallback_AddRef(STATUSCLB(This));
266 TRACE("Unsupported riid = %s\n", debugstr_guid(riid));
267 return E_NOINTERFACE;
270 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
272 BSCallback *This = STATUSCLB_THIS(iface);
273 LONG ref = InterlockedIncrement(&This->ref);
275 TRACE("(%p) ref = %d\n", This, ref);
280 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
282 BSCallback *This = STATUSCLB_THIS(iface);
283 LONG ref = InterlockedDecrement(&This->ref);
285 TRACE("(%p) ref = %d\n", This, ref);
289 GlobalFree(This->post_data);
291 IMoniker_Release(This->mon);
293 IBinding_Release(This->binding);
294 list_remove(&This->entry);
295 heap_free(This->headers);
297 This->vtbl->destroy(This);
303 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
304 DWORD dwReserved, IBinding *pbind)
306 BSCallback *This = STATUSCLB_THIS(iface);
308 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
310 IBinding_AddRef(pbind);
311 This->binding = pbind;
314 list_add_head(&This->doc->bindings, &This->entry);
316 return This->vtbl->start_binding(This);
319 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
321 BSCallback *This = STATUSCLB_THIS(iface);
322 FIXME("(%p)->(%p)\n", This, pnPriority);
326 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
328 BSCallback *This = STATUSCLB_THIS(iface);
329 FIXME("(%p)->(%d)\n", This, reserved);
333 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
334 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
336 BSCallback *This = STATUSCLB_THIS(iface);
338 TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
339 debugstr_w(szStatusText));
341 return This->vtbl->on_progress(This, ulStatusCode, szStatusText);
344 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
345 HRESULT hresult, LPCWSTR szError)
347 BSCallback *This = STATUSCLB_THIS(iface);
350 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
352 /* NOTE: IE7 calls GetBindResult here */
354 hres = This->vtbl->stop_binding(This, hresult);
357 IBinding_Release(This->binding);
358 This->binding = NULL;
361 list_remove(&This->entry);
367 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
368 DWORD *grfBINDF, BINDINFO *pbindinfo)
370 BSCallback *This = STATUSCLB_THIS(iface);
373 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
375 *grfBINDF = This->bindf;
377 size = pbindinfo->cbSize;
378 memset(pbindinfo, 0, size);
379 pbindinfo->cbSize = size;
381 pbindinfo->cbstgmedData = This->post_data_len;
382 pbindinfo->dwCodePage = CP_UTF8;
383 pbindinfo->dwOptions = 0x80000;
385 if(This->post_data) {
386 pbindinfo->dwBindVerb = BINDVERB_POST;
388 pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
389 pbindinfo->stgmedData.u.hGlobal = This->post_data;
390 pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)STATUSCLB(This);
391 IBindStatusCallback_AddRef(STATUSCLB(This));
397 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
398 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
400 BSCallback *This = STATUSCLB_THIS(iface);
402 TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
404 return This->vtbl->read_data(This, pstgmed->u.pstm);
407 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
408 REFIID riid, IUnknown *punk)
410 BSCallback *This = STATUSCLB_THIS(iface);
411 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
415 #undef STATUSCLB_THIS
417 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
418 BindStatusCallback_QueryInterface,
419 BindStatusCallback_AddRef,
420 BindStatusCallback_Release,
421 BindStatusCallback_OnStartBinding,
422 BindStatusCallback_GetPriority,
423 BindStatusCallback_OnLowResource,
424 BindStatusCallback_OnProgress,
425 BindStatusCallback_OnStopBinding,
426 BindStatusCallback_GetBindInfo,
427 BindStatusCallback_OnDataAvailable,
428 BindStatusCallback_OnObjectAvailable
431 #define HTTPNEG_THIS(iface) DEFINE_THIS(BSCallback, HttpNegotiate2, iface)
433 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
434 REFIID riid, void **ppv)
436 BSCallback *This = HTTPNEG_THIS(iface);
437 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
440 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface)
442 BSCallback *This = HTTPNEG_THIS(iface);
443 return IBindStatusCallback_AddRef(STATUSCLB(This));
446 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface)
448 BSCallback *This = HTTPNEG_THIS(iface);
449 return IBindStatusCallback_Release(STATUSCLB(This));
452 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
453 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
455 BSCallback *This = HTTPNEG_THIS(iface);
458 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders),
459 dwReserved, pszAdditionalHeaders);
462 *pszAdditionalHeaders = NULL;
466 size = (strlenW(This->headers)+1)*sizeof(WCHAR);
467 *pszAdditionalHeaders = CoTaskMemAlloc(size);
468 memcpy(*pszAdditionalHeaders, This->headers, size);
473 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode,
474 LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
476 BSCallback *This = HTTPNEG_THIS(iface);
478 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
479 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
481 return This->vtbl->on_response(This, dwResponseCode);
484 static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
485 BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
487 BSCallback *This = HTTPNEG_THIS(iface);
488 FIXME("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved);
494 static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl = {
495 HttpNegotiate_QueryInterface,
496 HttpNegotiate_AddRef,
497 HttpNegotiate_Release,
498 HttpNegotiate_BeginningTransaction,
499 HttpNegotiate_OnResponse,
500 HttpNegotiate_GetRootSecurityId
503 #define BINDINFO_THIS(iface) DEFINE_THIS(BSCallback, InternetBindInfo, iface)
505 static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface,
506 REFIID riid, void **ppv)
508 BSCallback *This = BINDINFO_THIS(iface);
509 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
512 static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface)
514 BSCallback *This = BINDINFO_THIS(iface);
515 return IBindStatusCallback_AddRef(STATUSCLB(This));
518 static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface)
520 BSCallback *This = BINDINFO_THIS(iface);
521 return IBindStatusCallback_Release(STATUSCLB(This));
524 static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface,
525 DWORD *grfBINDF, BINDINFO *pbindinfo)
527 BSCallback *This = BINDINFO_THIS(iface);
528 FIXME("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
532 static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface,
533 ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
535 BSCallback *This = BINDINFO_THIS(iface);
536 FIXME("(%p)->(%u %p %u %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
542 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
543 InternetBindInfo_QueryInterface,
544 InternetBindInfo_AddRef,
545 InternetBindInfo_Release,
546 InternetBindInfo_GetBindInfo,
547 InternetBindInfo_GetBindString
550 #define SERVPROV_THIS(iface) DEFINE_THIS(BSCallback, ServiceProvider, iface)
552 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
553 REFIID riid, void **ppv)
555 BSCallback *This = SERVPROV_THIS(iface);
556 return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
559 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
561 BSCallback *This = SERVPROV_THIS(iface);
562 return IBindStatusCallback_AddRef(STATUSCLB(This));
565 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
567 BSCallback *This = SERVPROV_THIS(iface);
568 return IBindStatusCallback_Release(STATUSCLB(This));
571 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
572 REFGUID guidService, REFIID riid, void **ppv)
574 BSCallback *This = SERVPROV_THIS(iface);
575 TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
576 return E_NOINTERFACE;
581 static const IServiceProviderVtbl ServiceProviderVtbl = {
582 BSCServiceProvider_QueryInterface,
583 BSCServiceProvider_AddRef,
584 BSCServiceProvider_Release,
585 BSCServiceProvider_QueryService
588 static void init_bscallback(BSCallback *This, const BSCallbackVtbl *vtbl, IMoniker *mon, DWORD bindf)
590 This->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
591 This->lpServiceProviderVtbl = &ServiceProviderVtbl;
592 This->lpHttpNegotiate2Vtbl = &HttpNegotiate2Vtbl;
593 This->lpInternetBindInfoVtbl = &InternetBindInfoVtbl;
598 list_init(&This->entry);
601 IMoniker_AddRef(mon);
605 /* Calls undocumented 84 cmd of CGID_ShellDocView */
606 static void call_docview_84(HTMLDocument *doc)
608 IOleCommandTarget *olecmd;
615 hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
620 hres = IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 84, 0, NULL, &var);
621 IOleCommandTarget_Release(olecmd);
622 if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL)
623 FIXME("handle result\n");
626 static void parse_post_data(nsIInputStream *post_data_stream, LPWSTR *headers_ret,
627 HGLOBAL *post_data_ret, ULONG *post_data_len_ret)
629 PRUint32 post_data_len = 0, available = 0;
630 HGLOBAL post_data = NULL;
631 LPWSTR headers = NULL;
632 DWORD headers_len = 0, len;
633 const char *ptr, *ptr2, *post_data_end;
635 nsIInputStream_Available(post_data_stream, &available);
636 post_data = GlobalAlloc(0, available+1);
637 nsIInputStream_Read(post_data_stream, post_data, available, &post_data_len);
639 TRACE("post_data = %s\n", debugstr_an(post_data, post_data_len));
641 ptr = ptr2 = post_data;
642 post_data_end = (const char*)post_data+post_data_len;
644 while(ptr < post_data_end && (*ptr != '\r' || ptr[1] != '\n')) {
645 while(ptr < post_data_end && (*ptr != '\r' || ptr[1] != '\n'))
655 if(ptr-ptr2 >= sizeof(CONTENT_LENGTH)
656 && CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
657 CONTENT_LENGTH, sizeof(CONTENT_LENGTH)-1,
658 ptr2, sizeof(CONTENT_LENGTH)-1) == CSTR_EQUAL) {
663 len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, NULL, 0);
666 headers = heap_realloc(headers,(headers_len+len+1)*sizeof(WCHAR));
668 headers = heap_alloc((len+1)*sizeof(WCHAR));
670 len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, headers+headers_len, len);
676 headers[headers_len] = 0;
677 *headers_ret = headers;
679 if(ptr >= post_data_end-2) {
680 GlobalFree(post_data);
687 post_data_len -= ptr-(const char*)post_data;
688 memmove(post_data, ptr, post_data_len);
689 post_data = GlobalReAlloc(post_data, post_data_len+1, 0);
692 *post_data_ret = post_data;
693 *post_data_len_ret = post_data_len;
696 HRESULT start_binding(HTMLDocument *doc, BSCallback *bscallback, IBindCtx *bctx)
701 bscallback->doc = doc;
703 /* NOTE: IE7 calls IsSystemMoniker here*/
705 call_docview_84(doc);
708 RegisterBindStatusCallback(bctx, STATUSCLB(bscallback), NULL, 0);
709 IBindCtx_AddRef(bctx);
711 hres = CreateAsyncBindCtx(0, STATUSCLB(bscallback), NULL, &bctx);
713 WARN("CreateAsyncBindCtx failed: %08x\n", hres);
714 bscallback->vtbl->stop_binding(bscallback, hres);
719 hres = IMoniker_BindToStorage(bscallback->mon, bctx, NULL, &IID_IStream, (void**)&str);
720 IBindCtx_Release(bctx);
722 WARN("BindToStorage failed: %08x\n", hres);
723 bscallback->vtbl->stop_binding(bscallback, hres);
728 IStream_Release(str);
730 IMoniker_Release(bscallback->mon);
731 bscallback->mon = NULL;
744 #define BUFFERBSC_THIS(bsc) ((BufferBSC*) bsc)
746 static void BufferBSC_destroy(BSCallback *bsc)
748 BufferBSC *This = BUFFERBSC_THIS(bsc);
750 heap_free(This->buf);
754 static HRESULT BufferBSC_start_binding(BSCallback *bsc)
759 static HRESULT BufferBSC_stop_binding(BSCallback *bsc, HRESULT result)
761 BufferBSC *This = BUFFERBSC_THIS(bsc);
766 heap_free(This->buf);
774 static HRESULT BufferBSC_read_data(BSCallback *bsc, IStream *stream)
776 BufferBSC *This = BUFFERBSC_THIS(bsc);
782 This->buf = heap_alloc(This->size);
786 if(This->bsc.readed == This->size) {
788 This->buf = heap_realloc(This->buf, This->size);
792 hres = IStream_Read(stream, This->buf+This->bsc.readed, This->size-This->bsc.readed, &readed);
793 This->bsc.readed += readed;
794 }while(hres == S_OK);
799 static HRESULT BufferBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text)
804 static HRESULT BufferBSC_on_response(BSCallback *bsc, DWORD response_code)
809 #undef BUFFERBSC_THIS
811 static const BSCallbackVtbl BufferBSCVtbl = {
813 BufferBSC_start_binding,
814 BufferBSC_stop_binding,
816 BufferBSC_on_progress,
817 BufferBSC_on_response
821 static BufferBSC *create_bufferbsc(IMoniker *mon)
823 BufferBSC *ret = heap_alloc_zero(sizeof(*ret));
825 init_bscallback(&ret->bsc, &BufferBSCVtbl, mon, 0);
831 HRESULT bind_mon_to_buffer(HTMLDocument *doc, IMoniker *mon, void **buf, DWORD *size)
833 BufferBSC *bsc = create_bufferbsc(mon);
838 hres = start_binding(doc, &bsc->bsc, NULL);
839 if(SUCCEEDED(hres)) {
841 if(SUCCEEDED(hres)) {
844 *size = bsc->bsc.readed;
849 IBindStatusCallback_Release(STATUSCLB(&bsc->bsc));
854 struct nsChannelBSC {
857 nsChannel *nschannel;
858 nsIStreamListener *nslistener;
859 nsISupports *nscontext;
861 nsProtocolStream *nsstream;
864 static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream)
870 if(!This->nslistener) {
875 hres = IStream_Read(stream, buf, sizeof(buf), &read);
876 }while(hres == S_OK && read);
882 This->nsstream = create_nsprotocol_stream();
886 hres = IStream_Read(stream, This->nsstream->buf+This->nsstream->buf_size,
887 sizeof(This->nsstream->buf)-This->nsstream->buf_size, &read);
891 This->nsstream->buf_size += read;
893 if(!This->bsc.readed) {
894 if(This->nsstream->buf_size >= 2
895 && (BYTE)This->nsstream->buf[0] == 0xff
896 && (BYTE)This->nsstream->buf[1] == 0xfe)
897 This->nschannel->charset = heap_strdupA(UTF16_STR);
899 /* FIXME: it's needed for http connections from BindToObject. */
900 if(!This->nschannel->response_status)
901 This->nschannel->response_status = 200;
903 nsres = nsIStreamListener_OnStartRequest(This->nslistener,
904 (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
906 FIXME("OnStartRequest failed: %08x\n", nsres);
908 /* events are reset when a new document URI is loaded, so re-initialise them here */
909 if(This->bsc.doc && This->bsc.doc->bscallback == This && This->bsc.doc->nscontainer) {
910 update_nsdocument(This->bsc.doc);
911 init_nsevents(This->bsc.doc->nscontainer);
915 This->bsc.readed += This->nsstream->buf_size;
917 nsres = nsIStreamListener_OnDataAvailable(This->nslistener,
918 (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext,
919 NSINSTREAM(This->nsstream), This->bsc.readed-This->nsstream->buf_size,
920 This->nsstream->buf_size);
922 ERR("OnDataAvailable failed: %08x\n", nsres);
924 if(This->nsstream->buf_size == sizeof(This->nsstream->buf)) {
925 ERR("buffer is full\n");
928 }while(hres == S_OK);
933 static void on_stop_nsrequest(nsChannelBSC *This)
935 if(!This->nslistener)
938 nsIStreamListener_OnStopRequest(This->nslistener, (nsIRequest*)NSCHANNEL(This->nschannel),
939 This->nscontext, NS_OK);
942 static void add_nsrequest(nsChannelBSC *This)
946 if(!This->nschannel || !This->nschannel->load_group)
949 nsres = nsILoadGroup_AddRequest(This->nschannel->load_group,
950 (nsIRequest*)NSCHANNEL(This->nschannel), This->nscontext);
953 ERR("AddRequest failed:%08x\n", nsres);
956 #define NSCHANNELBSC_THIS(bsc) ((nsChannelBSC*) bsc)
958 static void nsChannelBSC_destroy(BSCallback *bsc)
960 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
963 nsIChannel_Release(NSCHANNEL(This->nschannel));
965 nsIStreamListener_Release(This->nslistener);
967 nsISupports_Release(This->nscontext);
969 nsIInputStream_Release(NSINSTREAM(This->nsstream));
973 static HRESULT nsChannelBSC_start_binding(BSCallback *bsc)
975 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
982 static HRESULT nsChannelBSC_stop_binding(BSCallback *bsc, HRESULT result)
984 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
986 on_stop_nsrequest(This);
988 if(This->nslistener) {
989 if(This->nschannel->load_group) {
992 nsres = nsILoadGroup_RemoveRequest(This->nschannel->load_group,
993 (nsIRequest*)NSCHANNEL(This->nschannel), NULL, NS_OK);
995 ERR("RemoveRequest failed: %08x\n", nsres);
1002 static HRESULT nsChannelBSC_read_data(BSCallback *bsc, IStream *stream)
1004 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
1006 return read_stream_data(This, stream);
1009 static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR status_text)
1011 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
1013 switch(status_code) {
1014 case BINDSTATUS_MIMETYPEAVAILABLE:
1015 if(!This->nschannel)
1018 heap_free(This->nschannel->content_type);
1019 This->nschannel->content_type = heap_strdupWtoA(status_text);
1025 static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code)
1027 nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
1029 This->nschannel->response_status = response_code;
1033 #undef NSCHANNELBSC_THIS
1035 static const BSCallbackVtbl nsChannelBSCVtbl = {
1036 nsChannelBSC_destroy,
1037 nsChannelBSC_start_binding,
1038 nsChannelBSC_stop_binding,
1039 nsChannelBSC_read_data,
1040 nsChannelBSC_on_progress,
1041 nsChannelBSC_on_response
1044 nsChannelBSC *create_channelbsc(IMoniker *mon)
1046 nsChannelBSC *ret = heap_alloc_zero(sizeof(*ret));
1048 init_bscallback(&ret->bsc, &nsChannelBSCVtbl, mon, BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA);
1053 IMoniker *get_channelbsc_mon(nsChannelBSC *This)
1056 IMoniker_AddRef(This->bsc.mon);
1057 return This->bsc.mon;
1060 void set_document_bscallback(HTMLDocument *doc, nsChannelBSC *callback)
1064 if(doc->bscallback) {
1065 if(doc->bscallback->bsc.binding)
1066 IBinding_Abort(doc->bscallback->bsc.binding);
1067 doc->bscallback->bsc.doc = NULL;
1068 IBindStatusCallback_Release(STATUSCLB(&doc->bscallback->bsc));
1071 LIST_FOR_EACH_ENTRY(iter, &doc->bindings, BSCallback, entry) {
1073 list_remove(&iter->entry);
1076 doc->bscallback = callback;
1079 IBindStatusCallback_AddRef(STATUSCLB(&callback->bsc));
1080 callback->bsc.doc = doc;
1084 HRESULT channelbsc_load_stream(nsChannelBSC *bscallback, IStream *stream)
1088 const char text_html[] = "text/html";
1090 add_nsrequest(bscallback);
1092 if(bscallback->nschannel)
1093 bscallback->nschannel->content_type = heap_strdupA(text_html);
1095 hres = read_stream_data(bscallback, stream);
1096 IBindStatusCallback_OnStopBinding(STATUSCLB(&bscallback->bsc), hres, ERROR_SUCCESS);
1101 void channelbsc_set_channel(nsChannelBSC *This, nsChannel *channel, nsIStreamListener *listener, nsISupports *context)
1103 nsIChannel_AddRef(NSCHANNEL(channel));
1104 This->nschannel = channel;
1106 nsIStreamListener_AddRef(listener);
1107 This->nslistener = listener;
1110 nsISupports_AddRef(context);
1111 This->nscontext = context;
1114 if(channel->post_data_stream) {
1115 parse_post_data(channel->post_data_stream, &This->bsc.headers, &This->bsc.post_data, &This->bsc.post_data_len);
1116 TRACE("headers = %s post_data = %s\n", debugstr_w(This->bsc.headers),
1117 debugstr_an(This->bsc.post_data, This->bsc.post_data_len));
1121 void hlink_frame_navigate(HTMLDocument *doc, IHlinkFrame *hlink_frame,
1122 LPCWSTR uri, nsIInputStream *post_data_stream, DWORD hlnf)
1124 BSCallback *callback;
1130 callback = &create_channelbsc(NULL)->bsc;
1132 if(post_data_stream) {
1133 parse_post_data(post_data_stream, &callback->headers, &callback->post_data,
1134 &callback->post_data_len);
1135 TRACE("headers = %s post_data = %s\n", debugstr_w(callback->headers),
1136 debugstr_an(callback->post_data, callback->post_data_len));
1139 hr = CreateAsyncBindCtx(0, STATUSCLB(callback), NULL, &bindctx);
1141 IBindStatusCallback_Release(STATUSCLB(callback));
1145 hr = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER, &IID_IHlink, (LPVOID*)&hlink);
1147 IBindCtx_Release(bindctx);
1148 IBindStatusCallback_Release(STATUSCLB(callback));
1152 hr = CreateURLMoniker(NULL, uri, &mon);
1153 if (SUCCEEDED(hr)) {
1154 IHlink_SetMonikerReference(hlink, 0, mon, NULL);
1156 if(hlnf & HLNF_OPENINNEWWINDOW) {
1157 static const WCHAR wszBlank[] = {'_','b','l','a','n','k',0};
1158 IHlink_SetTargetFrameName(hlink, wszBlank); /* FIXME */
1161 IHlinkFrame_Navigate(hlink_frame, hlnf, bindctx, STATUSCLB(callback), hlink);
1163 IMoniker_Release(mon);
1166 IBindCtx_Release(bindctx);
1167 IBindStatusCallback_Release(STATUSCLB(callback));