2 * IXMLHTTPRequest implementation
4 * Copyright 2008 Alistair Leslie-Hughes
5 * Copyright 2010 Nikolay Sivov for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
34 #include "msxml_private.h"
36 #include "wine/debug.h"
37 #include "wine/list.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
43 #include <libxml/encoding.h>
45 static const WCHAR MethodGetW
[] = {'G','E','T',0};
46 static const WCHAR MethodPutW
[] = {'P','U','T',0};
47 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
49 static const WCHAR colspaceW
[] = {':',' ',0};
50 static const WCHAR crlfW
[] = {'\r','\n',0};
52 typedef struct BindStatusCallback BindStatusCallback
;
63 const struct IXMLHTTPRequestVtbl
*lpVtbl
;
73 struct list reqheaders
;
74 /* cached resulting custom request headers string length in WCHARs */
82 BindStatusCallback
*bsc
;
86 static inline httprequest
*impl_from_IXMLHTTPRequest( IXMLHTTPRequest
*iface
)
88 return (httprequest
*)((char*)iface
- FIELD_OFFSET(httprequest
, lpVtbl
));
91 static void httprequest_setreadystate(httprequest
*This
, READYSTATE state
)
99 memset(¶ms
, 0, sizeof(params
));
100 IDispatch_Invoke(This
->sink
, 0, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, ¶ms
, 0, 0, 0);
104 struct BindStatusCallback
106 const IBindStatusCallbackVtbl
*lpBindStatusCallbackVtbl
;
107 const IHttpNegotiateVtbl
*lpHttpNegotiateVtbl
;
111 httprequest
*request
;
117 static inline BindStatusCallback
*impl_from_IBindStatusCallback( IBindStatusCallback
*iface
)
119 return (BindStatusCallback
*)((char*)iface
- FIELD_OFFSET(BindStatusCallback
, lpBindStatusCallbackVtbl
));
122 static inline BindStatusCallback
*impl_from_IHttpNegotiate( IHttpNegotiate
*iface
)
124 return (BindStatusCallback
*)((char*)iface
- FIELD_OFFSET(BindStatusCallback
, lpHttpNegotiateVtbl
));
127 void BindStatusCallback_Detach(BindStatusCallback
*bsc
)
131 if (bsc
->binding
) IBinding_Abort(bsc
->binding
);
133 IBindStatusCallback_Release((IBindStatusCallback
*)bsc
);
137 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
138 REFIID riid
, void **ppv
)
140 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
144 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
146 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
147 IsEqualGUID(&IID_IBindStatusCallback
, riid
))
149 *ppv
= &This
->lpBindStatusCallbackVtbl
;
151 else if (IsEqualGUID(&IID_IHttpNegotiate
, riid
))
153 *ppv
= &This
->lpHttpNegotiateVtbl
;
155 else if (IsEqualGUID(&IID_IServiceProvider
, riid
) ||
156 IsEqualGUID(&IID_IBindStatusCallbackEx
, riid
) ||
157 IsEqualGUID(&IID_IInternetProtocol
, riid
) ||
158 IsEqualGUID(&IID_IHttpNegotiate2
, riid
))
160 return E_NOINTERFACE
;
165 IBindStatusCallback_AddRef(iface
);
169 FIXME("Unsupported riid = %s\n", debugstr_guid(riid
));
171 return E_NOINTERFACE
;
174 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
176 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
177 LONG ref
= InterlockedIncrement(&This
->ref
);
179 TRACE("(%p) ref = %d\n", This
, ref
);
184 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
186 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
187 LONG ref
= InterlockedDecrement(&This
->ref
);
189 TRACE("(%p) ref = %d\n", This
, ref
);
193 if (This
->binding
) IBinding_Release(This
->binding
);
194 if (This
->stream
) IStream_Release(This
->stream
);
201 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
202 DWORD reserved
, IBinding
*pbind
)
204 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
206 TRACE("(%p)->(%d %p)\n", This
, reserved
, pbind
);
208 if (!pbind
) return E_INVALIDARG
;
210 This
->binding
= pbind
;
211 IBinding_AddRef(pbind
);
213 httprequest_setreadystate(This
->request
, READYSTATE_LOADED
);
215 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
218 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pPriority
)
220 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
222 TRACE("(%p)->(%p)\n", This
, pPriority
);
227 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
229 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
231 TRACE("(%p)->(%d)\n", This
, reserved
);
236 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
237 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
239 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
241 TRACE("%p)->(%u %u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
242 debugstr_w(szStatusText
));
247 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
248 HRESULT hr
, LPCWSTR error
)
250 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
252 TRACE("(%p)->(0x%08x %s)\n", This
, hr
, debugstr_w(error
));
256 IBinding_Release(This
->binding
);
257 This
->binding
= NULL
;
261 httprequest_setreadystate(This
->request
, READYSTATE_COMPLETE
);
266 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
267 DWORD
*bind_flags
, BINDINFO
*pbindinfo
)
269 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
271 TRACE("(%p)->(%p %p)\n", This
, bind_flags
, pbindinfo
);
274 if (This
->request
->async
) *bind_flags
|= BINDF_ASYNCHRONOUS
;
276 if (This
->request
->verb
!= BINDVERB_GET
)
278 FIXME("only GET verb supported. Got %d\n", This
->request
->verb
);
282 pbindinfo
->dwBindVerb
= This
->request
->verb
;
287 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
288 DWORD flags
, DWORD size
, FORMATETC
*format
, STGMEDIUM
*stgmed
)
290 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
295 TRACE("(%p)->(%08x %d %p %p)\n", This
, flags
, size
, format
, stgmed
);
299 hr
= IStream_Read(stgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
300 if (hr
!= S_OK
) break;
302 hr
= IStream_Write(This
->stream
, buf
, read
, &written
);
303 } while((hr
== S_OK
) && written
!= 0 && read
!= 0);
305 httprequest_setreadystate(This
->request
, READYSTATE_INTERACTIVE
);
310 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
311 REFIID riid
, IUnknown
*punk
)
313 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
315 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
320 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
321 BindStatusCallback_QueryInterface
,
322 BindStatusCallback_AddRef
,
323 BindStatusCallback_Release
,
324 BindStatusCallback_OnStartBinding
,
325 BindStatusCallback_GetPriority
,
326 BindStatusCallback_OnLowResource
,
327 BindStatusCallback_OnProgress
,
328 BindStatusCallback_OnStopBinding
,
329 BindStatusCallback_GetBindInfo
,
330 BindStatusCallback_OnDataAvailable
,
331 BindStatusCallback_OnObjectAvailable
334 static HRESULT WINAPI
BSCHttpNegotiate_QueryInterface(IHttpNegotiate
*iface
,
335 REFIID riid
, void **ppv
)
337 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
338 return IBindStatusCallback_QueryInterface((IBindStatusCallback
*)This
, riid
, ppv
);
341 static ULONG WINAPI
BSCHttpNegotiate_AddRef(IHttpNegotiate
*iface
)
343 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
344 return IBindStatusCallback_AddRef((IBindStatusCallback
*)This
);
347 static ULONG WINAPI
BSCHttpNegotiate_Release(IHttpNegotiate
*iface
)
349 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
350 return IBindStatusCallback_Release((IBindStatusCallback
*)This
);
353 static HRESULT WINAPI
BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate
*iface
,
354 LPCWSTR url
, LPCWSTR headers
, DWORD reserved
, LPWSTR
*add_headers
)
356 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
357 const struct reqheader
*entry
;
360 TRACE("(%p)->(%s %s %d %p)\n", This
, debugstr_w(url
), debugstr_w(headers
), reserved
, add_headers
);
364 if (list_empty(&This
->request
->reqheaders
)) return S_OK
;
366 buff
= CoTaskMemAlloc(This
->request
->reqheader_size
*sizeof(WCHAR
));
367 if (!buff
) return E_OUTOFMEMORY
;
370 LIST_FOR_EACH_ENTRY(entry
, &This
->request
->reqheaders
, struct reqheader
, entry
)
372 lstrcpyW(ptr
, entry
->header
);
373 ptr
+= SysStringLen(entry
->header
);
375 lstrcpyW(ptr
, colspaceW
);
376 ptr
+= sizeof(colspaceW
)/sizeof(WCHAR
)-1;
378 lstrcpyW(ptr
, entry
->value
);
379 ptr
+= SysStringLen(entry
->value
);
381 lstrcpyW(ptr
, crlfW
);
382 ptr
+= sizeof(crlfW
)/sizeof(WCHAR
)-1;
390 static HRESULT WINAPI
BSCHttpNegotiate_OnResponse(IHttpNegotiate
*iface
, DWORD code
,
391 LPCWSTR resp_headers
, LPCWSTR req_headers
, LPWSTR
*add_reqheaders
)
393 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
395 TRACE("(%p)->(%d %s %s %p)\n", This
, code
, debugstr_w(resp_headers
),
396 debugstr_w(req_headers
), add_reqheaders
);
398 This
->request
->status
= code
;
403 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl
= {
404 BSCHttpNegotiate_QueryInterface
,
405 BSCHttpNegotiate_AddRef
,
406 BSCHttpNegotiate_Release
,
407 BSCHttpNegotiate_BeginningTransaction
,
408 BSCHttpNegotiate_OnResponse
411 static HRESULT
BindStatusCallback_create(httprequest
* This
, BindStatusCallback
**obj
)
413 BindStatusCallback
*bsc
;
417 hr
= CreateBindCtx(0, &pbc
);
418 if (hr
!= S_OK
) return hr
;
420 bsc
= heap_alloc(sizeof(*bsc
));
423 IBindCtx_Release(pbc
);
424 return E_OUTOFMEMORY
;
427 bsc
->lpBindStatusCallbackVtbl
= &BindStatusCallbackVtbl
;
428 bsc
->lpHttpNegotiateVtbl
= &BSCHttpNegotiateVtbl
;
434 hr
= RegisterBindStatusCallback(pbc
, (IBindStatusCallback
*)bsc
, NULL
, 0);
439 hr
= CreateURLMoniker(NULL
, This
->url
, &moniker
);
444 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
445 IMoniker_Release(moniker
);
446 if (stream
) IStream_Release(stream
);
448 IBindCtx_Release(pbc
);
453 IBindStatusCallback_Release((IBindStatusCallback
*)bsc
);
461 static HRESULT WINAPI
httprequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
463 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
464 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
466 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
467 IsEqualGUID( riid
, &IID_IDispatch
) ||
468 IsEqualGUID( riid
, &IID_IUnknown
) )
474 FIXME("Unsupported interface %s\n", debugstr_guid(riid
));
475 return E_NOINTERFACE
;
478 IXMLHTTPRequest_AddRef( iface
);
483 static ULONG WINAPI
httprequest_AddRef(IXMLHTTPRequest
*iface
)
485 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
486 ULONG ref
= InterlockedIncrement( &This
->ref
);
487 TRACE("(%p)->(%u)\n", This
, ref
);
491 static ULONG WINAPI
httprequest_Release(IXMLHTTPRequest
*iface
)
493 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
494 ULONG ref
= InterlockedDecrement( &This
->ref
);
496 TRACE("(%p)->(%u)\n", This
, ref
);
500 struct reqheader
*header
, *header2
;
502 SysFreeString(This
->url
);
503 SysFreeString(This
->user
);
504 SysFreeString(This
->password
);
506 /* request headers */
507 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->reqheaders
, struct reqheader
, entry
)
509 list_remove(&header
->entry
);
510 SysFreeString(header
->header
);
511 SysFreeString(header
->value
);
514 /* detach callback object */
515 BindStatusCallback_Detach(This
->bsc
);
517 if (This
->sink
) IDispatch_Release(This
->sink
);
525 static HRESULT WINAPI
httprequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
527 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
529 TRACE("(%p)->(%p)\n", This
, pctinfo
);
536 static HRESULT WINAPI
httprequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
537 LCID lcid
, ITypeInfo
**ppTInfo
)
539 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
542 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
544 hr
= get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
549 static HRESULT WINAPI
httprequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
550 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
552 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
556 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
559 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
562 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
565 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
566 ITypeInfo_Release(typeinfo
);
572 static HRESULT WINAPI
httprequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
573 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
574 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
576 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
580 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
581 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
583 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
586 hr
= ITypeInfo_Invoke(typeinfo
, &(This
->lpVtbl
), dispIdMember
, wFlags
, pDispParams
,
587 pVarResult
, pExcepInfo
, puArgErr
);
588 ITypeInfo_Release(typeinfo
);
594 static HRESULT WINAPI
httprequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
595 VARIANT async
, VARIANT user
, VARIANT password
)
597 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
601 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(method
), debugstr_w(url
));
603 if (!method
|| !url
) return E_INVALIDARG
;
605 /* free previously set data */
606 SysFreeString(This
->url
);
607 SysFreeString(This
->user
);
608 SysFreeString(This
->password
);
609 This
->url
= This
->user
= This
->password
= NULL
;
611 if (lstrcmpiW(method
, MethodGetW
) == 0)
613 This
->verb
= BINDVERB_GET
;
615 else if (lstrcmpiW(method
, MethodPutW
) == 0)
617 This
->verb
= BINDVERB_PUT
;
619 else if (lstrcmpiW(method
, MethodPostW
) == 0)
621 This
->verb
= BINDVERB_POST
;
625 FIXME("unsupported request type %s\n", debugstr_w(method
));
630 This
->url
= SysAllocString(url
);
632 hr
= VariantChangeType(&async
, &async
, 0, VT_BOOL
);
633 This
->async
= hr
== S_OK
&& V_BOOL(&async
) == VARIANT_TRUE
;
636 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
638 This
->user
= V_BSTR(&str
);
640 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
642 This
->password
= V_BSTR(&str
);
644 httprequest_setreadystate(This
, READYSTATE_LOADING
);
649 static HRESULT WINAPI
httprequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
651 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
652 struct reqheader
*entry
;
654 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
656 if (!header
|| !*header
) return E_INVALIDARG
;
657 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
658 if (!value
) return E_INVALIDARG
;
660 /* replace existing header value if already added */
661 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct reqheader
, entry
)
663 if (lstrcmpW(entry
->header
, header
) == 0)
665 LONG length
= SysStringLen(entry
->value
);
668 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
671 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
677 entry
= heap_alloc(sizeof(*entry
));
678 if (!entry
) return E_OUTOFMEMORY
;
681 entry
->header
= SysAllocString(header
);
682 entry
->value
= SysAllocString(value
);
684 /* header length including null terminator */
685 This
->reqheader_size
+= SysStringLen(entry
->header
) + sizeof(colspaceW
)/sizeof(WCHAR
) +
686 SysStringLen(entry
->value
) + sizeof(crlfW
)/sizeof(WCHAR
) - 1;
688 list_add_head(&This
->reqheaders
, &entry
->entry
);
693 static HRESULT WINAPI
httprequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR bstrHeader
, BSTR
*pbstrValue
)
695 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
697 FIXME("stub (%p) %s %p\n", This
, debugstr_w(bstrHeader
), pbstrValue
);
702 static HRESULT WINAPI
httprequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*pbstrHeaders
)
704 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
706 FIXME("stub (%p) %p\n", This
, pbstrHeaders
);
711 static HRESULT WINAPI
httprequest_send(IXMLHTTPRequest
*iface
, VARIANT varBody
)
713 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
714 BindStatusCallback
*bsc
= NULL
;
717 TRACE("(%p)\n", This
);
719 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
721 hr
= BindStatusCallback_create(This
, &bsc
);
722 if (FAILED(hr
)) return hr
;
724 BindStatusCallback_Detach(This
->bsc
);
730 static HRESULT WINAPI
httprequest_abort(IXMLHTTPRequest
*iface
)
732 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
734 TRACE("(%p)\n", This
);
736 BindStatusCallback_Detach(This
->bsc
);
739 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
744 static HRESULT WINAPI
httprequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
746 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
748 TRACE("(%p)->(%p)\n", This
, status
);
750 if (!status
) return E_INVALIDARG
;
751 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
753 *status
= This
->status
;
758 static HRESULT WINAPI
httprequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*pbstrStatus
)
760 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
762 FIXME("stub %p %p\n", This
, pbstrStatus
);
767 static HRESULT WINAPI
httprequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**ppBody
)
769 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
771 FIXME("stub %p %p\n", This
, ppBody
);
776 static HRESULT WINAPI
httprequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
778 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
782 TRACE("(%p)->(%p)\n", This
, body
);
784 if (!body
) return E_INVALIDARG
;
785 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
787 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
790 xmlChar
*ptr
= GlobalLock(hglobal
);
791 DWORD size
= GlobalSize(hglobal
);
792 xmlCharEncoding encoding
= XML_CHAR_ENCODING_UTF8
;
794 /* try to determine data encoding */
797 encoding
= xmlDetectCharEncoding(ptr
, 4);
798 TRACE("detected encoding: %s\n", xmlGetCharEncodingName(encoding
));
799 if ( encoding
!= XML_CHAR_ENCODING_UTF8
&&
800 encoding
!= XML_CHAR_ENCODING_UTF16LE
&&
801 encoding
!= XML_CHAR_ENCODING_NONE
)
803 FIXME("unsupported encoding: %s\n", xmlGetCharEncodingName(encoding
));
804 GlobalUnlock(hglobal
);
809 /* without BOM assume UTF-8 */
810 if (encoding
== XML_CHAR_ENCODING_UTF8
||
811 encoding
== XML_CHAR_ENCODING_NONE
)
813 *body
= bstr_from_xmlChar(ptr
);
816 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
818 if (!*body
) hr
= E_OUTOFMEMORY
;
819 GlobalUnlock(hglobal
);
825 static HRESULT WINAPI
httprequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*pvarBody
)
827 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
829 FIXME("stub %p %p\n", This
, pvarBody
);
834 static HRESULT WINAPI
httprequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*pvarBody
)
836 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
838 FIXME("stub %p %p\n", This
, pvarBody
);
843 static HRESULT WINAPI
httprequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
845 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
847 TRACE("(%p)->(%p)\n", This
, state
);
849 if (!state
) return E_INVALIDARG
;
851 *state
= This
->state
;
855 static HRESULT WINAPI
httprequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
857 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
859 TRACE("(%p)->(%p)\n", This
, sink
);
861 if (This
->sink
) IDispatch_Release(This
->sink
);
862 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
867 static const struct IXMLHTTPRequestVtbl dimimpl_vtbl
=
869 httprequest_QueryInterface
,
872 httprequest_GetTypeInfoCount
,
873 httprequest_GetTypeInfo
,
874 httprequest_GetIDsOfNames
,
877 httprequest_setRequestHeader
,
878 httprequest_getResponseHeader
,
879 httprequest_getAllResponseHeaders
,
882 httprequest_get_status
,
883 httprequest_get_statusText
,
884 httprequest_get_responseXML
,
885 httprequest_get_responseText
,
886 httprequest_get_responseBody
,
887 httprequest_get_responseStream
,
888 httprequest_get_readyState
,
889 httprequest_put_onreadystatechange
892 HRESULT
XMLHTTPRequest_create(IUnknown
*pUnkOuter
, void **ppObj
)
897 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
899 req
= heap_alloc( sizeof (*req
) );
901 return E_OUTOFMEMORY
;
903 req
->lpVtbl
= &dimimpl_vtbl
;
908 req
->url
= req
->user
= req
->password
= NULL
;
910 req
->state
= READYSTATE_UNINITIALIZED
;
915 req
->reqheader_size
= 0;
916 list_init(&req
->reqheaders
);
918 *ppObj
= &req
->lpVtbl
;
920 TRACE("returning iface %p\n", *ppObj
);
927 HRESULT
XMLHTTPRequest_create(IUnknown
*pUnkOuter
, void **ppObj
)
929 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
930 "libxml2 support was not present at compile time.\n");