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 #undef STATUSCLB_THIS
322 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
323 BindStatusCallback_QueryInterface,
324 BindStatusCallback_AddRef,
325 BindStatusCallback_Release,
326 BindStatusCallback_OnStartBinding,
327 BindStatusCallback_GetPriority,
328 BindStatusCallback_OnLowResource,
329 BindStatusCallback_OnProgress,
330 BindStatusCallback_OnStopBinding,
331 BindStatusCallback_GetBindInfo,
332 BindStatusCallback_OnDataAvailable,
333 BindStatusCallback_OnObjectAvailable
336 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate *iface,
337 REFIID riid, void **ppv)
339 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
340 return IBindStatusCallback_QueryInterface((IBindStatusCallback*)This, riid, ppv);
343 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate *iface)
345 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
346 return IBindStatusCallback_AddRef((IBindStatusCallback*)This);
349 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate *iface)
351 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
352 return IBindStatusCallback_Release((IBindStatusCallback*)This);
355 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *iface,
356 LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR *add_headers)
358 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
359 const struct reqheader *entry;
362 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(url), debugstr_w(headers), reserved, add_headers);
366 if (list_empty(&This->request->reqheaders)) return S_OK;
368 buff = CoTaskMemAlloc(This->request->reqheader_size*sizeof(WCHAR));
369 if (!buff) return E_OUTOFMEMORY;
372 LIST_FOR_EACH_ENTRY(entry, &This->request->reqheaders, struct reqheader, entry)
374 lstrcpyW(ptr, entry->header);
375 ptr += SysStringLen(entry->header);
377 lstrcpyW(ptr, colspaceW);
378 ptr += sizeof(colspaceW)/sizeof(WCHAR)-1;
380 lstrcpyW(ptr, entry->value);
381 ptr += SysStringLen(entry->value);
383 lstrcpyW(ptr, crlfW);
384 ptr += sizeof(crlfW)/sizeof(WCHAR)-1;
392 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD code,
393 LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders)
395 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
397 TRACE("(%p)->(%d %s %s %p)\n", This, code, debugstr_w(resp_headers),
398 debugstr_w(req_headers), add_reqheaders);
400 This->request->status = code;
407 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl = {
408 BSCHttpNegotiate_QueryInterface,
409 BSCHttpNegotiate_AddRef,
410 BSCHttpNegotiate_Release,
411 BSCHttpNegotiate_BeginningTransaction,
412 BSCHttpNegotiate_OnResponse
415 static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback **obj)
417 BindStatusCallback *bsc;
421 hr = CreateBindCtx(0, &pbc);
422 if (hr != S_OK) return hr;
424 bsc = heap_alloc(sizeof(*bsc));
427 IBindCtx_Release(pbc);
428 return E_OUTOFMEMORY;
431 bsc->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
432 bsc->lpHttpNegotiateVtbl = &BSCHttpNegotiateVtbl;
438 hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)bsc, NULL, 0);
443 hr = CreateURLMoniker(NULL, This->url, &moniker);
448 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (void**)&stream);
449 IMoniker_Release(moniker);
450 if (stream) IStream_Release(stream);
452 IBindCtx_Release(pbc);
457 IBindStatusCallback_Release((IBindStatusCallback*)bsc);
465 static HRESULT WINAPI httprequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject)
467 httprequest *This = impl_from_IXMLHTTPRequest( iface );
468 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
470 if ( IsEqualGUID( riid, &IID_IXMLHTTPRequest) ||
471 IsEqualGUID( riid, &IID_IDispatch) ||
472 IsEqualGUID( riid, &IID_IUnknown) )
478 FIXME("Unsupported interface %s\n", debugstr_guid(riid));
479 return E_NOINTERFACE;
482 IXMLHTTPRequest_AddRef( iface );
487 static ULONG WINAPI httprequest_AddRef(IXMLHTTPRequest *iface)
489 httprequest *This = impl_from_IXMLHTTPRequest( iface );
490 ULONG ref = InterlockedIncrement( &This->ref );
491 TRACE("(%p)->(%u)\n", This, ref );
495 static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
497 httprequest *This = impl_from_IXMLHTTPRequest( iface );
498 ULONG ref = InterlockedDecrement( &This->ref );
500 TRACE("(%p)->(%u)\n", This, ref );
504 struct reqheader *header, *header2;
506 SysFreeString(This->url);
507 SysFreeString(This->user);
508 SysFreeString(This->password);
510 /* request headers */
511 LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct reqheader, entry)
513 list_remove(&header->entry);
514 SysFreeString(header->header);
515 SysFreeString(header->value);
518 /* detach callback object */
519 BindStatusCallback_Detach(This->bsc);
521 if (This->sink) IDispatch_Release(This->sink);
529 static HRESULT WINAPI httprequest_GetTypeInfoCount(IXMLHTTPRequest *iface, UINT *pctinfo)
531 httprequest *This = impl_from_IXMLHTTPRequest( iface );
533 TRACE("(%p)->(%p)\n", This, pctinfo);
540 static HRESULT WINAPI httprequest_GetTypeInfo(IXMLHTTPRequest *iface, UINT iTInfo,
541 LCID lcid, ITypeInfo **ppTInfo)
543 httprequest *This = impl_from_IXMLHTTPRequest( iface );
546 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
548 hr = get_typeinfo(IXMLHTTPRequest_tid, ppTInfo);
553 static HRESULT WINAPI httprequest_GetIDsOfNames(IXMLHTTPRequest *iface, REFIID riid,
554 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
556 httprequest *This = impl_from_IXMLHTTPRequest( iface );
560 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
563 if(!rgszNames || cNames == 0 || !rgDispId)
566 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
569 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
570 ITypeInfo_Release(typeinfo);
576 static HRESULT WINAPI httprequest_Invoke(IXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid,
577 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
578 EXCEPINFO *pExcepInfo, UINT *puArgErr)
580 httprequest *This = impl_from_IXMLHTTPRequest( iface );
584 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
585 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
587 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
590 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
591 pVarResult, pExcepInfo, puArgErr);
592 ITypeInfo_Release(typeinfo);
598 static HRESULT WINAPI httprequest_open(IXMLHTTPRequest *iface, BSTR method, BSTR url,
599 VARIANT async, VARIANT user, VARIANT password)
601 httprequest *This = impl_from_IXMLHTTPRequest( iface );
605 TRACE("(%p)->(%s %s)\n", This, debugstr_w(method), debugstr_w(url));
607 if (!method || !url) return E_INVALIDARG;
609 /* free previously set data */
610 SysFreeString(This->url);
611 SysFreeString(This->user);
612 SysFreeString(This->password);
613 This->url = This->user = This->password = NULL;
615 if (lstrcmpiW(method, MethodGetW) == 0)
617 This->verb = BINDVERB_GET;
619 else if (lstrcmpiW(method, MethodPutW) == 0)
621 This->verb = BINDVERB_PUT;
623 else if (lstrcmpiW(method, MethodPostW) == 0)
625 This->verb = BINDVERB_POST;
629 FIXME("unsupported request type %s\n", debugstr_w(method));
634 This->url = SysAllocString(url);
636 hr = VariantChangeType(&async, &async, 0, VT_BOOL);
637 This->async = hr == S_OK && V_BOOL(&async) == VARIANT_TRUE;
640 hr = VariantChangeType(&str, &user, 0, VT_BSTR);
642 This->user = V_BSTR(&str);
644 hr = VariantChangeType(&str, &password, 0, VT_BSTR);
646 This->password = V_BSTR(&str);
648 httprequest_setreadystate(This, READYSTATE_LOADING);
653 static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR header, BSTR value)
655 httprequest *This = impl_from_IXMLHTTPRequest( iface );
656 struct reqheader *entry;
658 TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
660 if (!header || !*header) return E_INVALIDARG;
661 if (This->state != READYSTATE_LOADING) return E_FAIL;
662 if (!value) return E_INVALIDARG;
664 /* replace existing header value if already added */
665 LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct reqheader, entry)
667 if (lstrcmpW(entry->header, header) == 0)
669 LONG length = SysStringLen(entry->value);
672 hr = SysReAllocString(&entry->value, value) ? S_OK : E_OUTOFMEMORY;
675 This->reqheader_size += (SysStringLen(entry->value) - length);
681 entry = heap_alloc(sizeof(*entry));
682 if (!entry) return E_OUTOFMEMORY;
685 entry->header = SysAllocString(header);
686 entry->value = SysAllocString(value);
688 /* header length including null terminator */
689 This->reqheader_size += SysStringLen(entry->header) + sizeof(colspaceW)/sizeof(WCHAR) +
690 SysStringLen(entry->value) + sizeof(crlfW)/sizeof(WCHAR) - 1;
692 list_add_head(&This->reqheaders, &entry->entry);
697 static HRESULT WINAPI httprequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR *pbstrValue)
699 httprequest *This = impl_from_IXMLHTTPRequest( iface );
701 FIXME("stub (%p) %s %p\n", This, debugstr_w(bstrHeader), pbstrValue);
706 static HRESULT WINAPI httprequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *pbstrHeaders)
708 httprequest *This = impl_from_IXMLHTTPRequest( iface );
710 FIXME("stub (%p) %p\n", This, pbstrHeaders);
715 static HRESULT WINAPI httprequest_send(IXMLHTTPRequest *iface, VARIANT varBody)
717 httprequest *This = impl_from_IXMLHTTPRequest( iface );
718 BindStatusCallback *bsc = NULL;
721 TRACE("(%p)\n", This);
723 if (This->state != READYSTATE_LOADING) return E_FAIL;
725 hr = BindStatusCallback_create(This, &bsc);
726 if (FAILED(hr)) return hr;
728 BindStatusCallback_Detach(This->bsc);
734 static HRESULT WINAPI httprequest_abort(IXMLHTTPRequest *iface)
736 httprequest *This = impl_from_IXMLHTTPRequest( iface );
738 FIXME("stub (%p)\n", This);
743 static HRESULT WINAPI httprequest_get_status(IXMLHTTPRequest *iface, LONG *status)
745 httprequest *This = impl_from_IXMLHTTPRequest( iface );
747 TRACE("(%p)->(%p)\n", This, status);
749 if (!status) return E_INVALIDARG;
750 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
752 *status = This->status;
757 static HRESULT WINAPI httprequest_get_statusText(IXMLHTTPRequest *iface, BSTR *pbstrStatus)
759 httprequest *This = impl_from_IXMLHTTPRequest( iface );
761 FIXME("stub %p %p\n", This, pbstrStatus);
766 static HRESULT WINAPI httprequest_get_responseXML(IXMLHTTPRequest *iface, IDispatch **ppBody)
768 httprequest *This = impl_from_IXMLHTTPRequest( iface );
770 FIXME("stub %p %p\n", This, ppBody);
775 static HRESULT WINAPI httprequest_get_responseText(IXMLHTTPRequest *iface, BSTR *body)
777 httprequest *This = impl_from_IXMLHTTPRequest( iface );
781 TRACE("(%p)->(%p)\n", This, body);
783 if (!body) return E_INVALIDARG;
784 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
786 hr = GetHGlobalFromStream(This->bsc->stream, &hglobal);
789 xmlChar *ptr = GlobalLock(hglobal);
790 DWORD size = GlobalSize(hglobal);
791 xmlCharEncoding encoding = XML_CHAR_ENCODING_UTF8;
793 /* try to determine data encoding */
796 encoding = xmlDetectCharEncoding(ptr, 4);
797 TRACE("detected encoding: %s\n", xmlGetCharEncodingName(encoding));
798 if ( encoding != XML_CHAR_ENCODING_UTF8 &&
799 encoding != XML_CHAR_ENCODING_UTF16LE &&
800 encoding != XML_CHAR_ENCODING_NONE )
802 FIXME("unsupported encoding: %s\n", xmlGetCharEncodingName(encoding));
803 GlobalUnlock(hglobal);
808 /* without BOM assume UTF-8 */
809 if (encoding == XML_CHAR_ENCODING_UTF8 ||
810 encoding == XML_CHAR_ENCODING_NONE )
812 *body = bstr_from_xmlChar(ptr);
815 *body = SysAllocStringByteLen((LPCSTR)ptr, size);
817 if (!*body) hr = E_OUTOFMEMORY;
818 GlobalUnlock(hglobal);
824 static HRESULT WINAPI httprequest_get_responseBody(IXMLHTTPRequest *iface, VARIANT *pvarBody)
826 httprequest *This = impl_from_IXMLHTTPRequest( iface );
828 FIXME("stub %p %p\n", This, pvarBody);
833 static HRESULT WINAPI httprequest_get_responseStream(IXMLHTTPRequest *iface, VARIANT *pvarBody)
835 httprequest *This = impl_from_IXMLHTTPRequest( iface );
837 FIXME("stub %p %p\n", This, pvarBody);
842 static HRESULT WINAPI httprequest_get_readyState(IXMLHTTPRequest *iface, LONG *state)
844 httprequest *This = impl_from_IXMLHTTPRequest( iface );
846 TRACE("(%p)->(%p)\n", This, state);
848 if (!state) return E_INVALIDARG;
850 *state = This->state;
854 static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *sink)
856 httprequest *This = impl_from_IXMLHTTPRequest( iface );
858 TRACE("(%p)->(%p)\n", This, sink);
860 if (This->sink) IDispatch_Release(This->sink);
861 if ((This->sink = sink)) IDispatch_AddRef(This->sink);
866 static const struct IXMLHTTPRequestVtbl dimimpl_vtbl =
868 httprequest_QueryInterface,
871 httprequest_GetTypeInfoCount,
872 httprequest_GetTypeInfo,
873 httprequest_GetIDsOfNames,
876 httprequest_setRequestHeader,
877 httprequest_getResponseHeader,
878 httprequest_getAllResponseHeaders,
881 httprequest_get_status,
882 httprequest_get_statusText,
883 httprequest_get_responseXML,
884 httprequest_get_responseText,
885 httprequest_get_responseBody,
886 httprequest_get_responseStream,
887 httprequest_get_readyState,
888 httprequest_put_onreadystatechange
891 HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
896 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
898 req = heap_alloc( sizeof (*req) );
900 return E_OUTOFMEMORY;
902 req->lpVtbl = &dimimpl_vtbl;
907 req->url = req->user = req->password = NULL;
909 req->state = READYSTATE_UNINITIALIZED;
914 req->reqheader_size = 0;
915 list_init(&req->reqheaders);
917 *ppObj = &req->lpVtbl;
919 TRACE("returning iface %p\n", *ppObj);
926 HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
928 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
929 "libxml2 support was not present at compile time.\n");