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
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/encoding.h>
41 #include "msxml_private.h"
43 #include "wine/debug.h"
44 #include "wine/list.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
50 static const WCHAR MethodGetW[] = {'G','E','T',0};
51 static const WCHAR MethodPutW[] = {'P','U','T',0};
52 static const WCHAR MethodPostW[] = {'P','O','S','T',0};
54 static const WCHAR colspaceW[] = {':',' ',0};
55 static const WCHAR crlfW[] = {'\r','\n',0};
57 typedef struct BindStatusCallback BindStatusCallback;
68 IXMLHTTPRequest IXMLHTTPRequest_iface;
69 IObjectWithSite IObjectWithSite_iface;
70 IObjectSafety IObjectSafety_iface;
80 struct list reqheaders;
81 /* cached resulting custom request headers string length in WCHARs */
89 BindStatusCallback *bsc;
99 static inline httprequest *impl_from_IXMLHTTPRequest( IXMLHTTPRequest *iface )
101 return CONTAINING_RECORD(iface, httprequest, IXMLHTTPRequest_iface);
104 static inline httprequest *impl_from_IObjectWithSite(IObjectWithSite *iface)
106 return CONTAINING_RECORD(iface, httprequest, IObjectWithSite_iface);
109 static inline httprequest *impl_from_IObjectSafety(IObjectSafety *iface)
111 return CONTAINING_RECORD(iface, httprequest, IObjectSafety_iface);
114 static void httprequest_setreadystate(httprequest *This, READYSTATE state)
116 READYSTATE last = This->state;
120 if (This->sink && last != state)
124 memset(¶ms, 0, sizeof(params));
125 IDispatch_Invoke(This->sink, 0, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, 0, 0, 0);
129 struct BindStatusCallback
131 IBindStatusCallback IBindStatusCallback_iface;
132 IHttpNegotiate IHttpNegotiate_iface;
136 httprequest *request;
141 /* request body data */
145 static inline BindStatusCallback *impl_from_IBindStatusCallback( IBindStatusCallback *iface )
147 return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallback_iface);
150 static inline BindStatusCallback *impl_from_IHttpNegotiate( IHttpNegotiate *iface )
152 return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate_iface);
155 void BindStatusCallback_Detach(BindStatusCallback *bsc)
159 if (bsc->binding) IBinding_Abort(bsc->binding);
161 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
165 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
166 REFIID riid, void **ppv)
168 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
172 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
174 if (IsEqualGUID(&IID_IUnknown, riid) ||
175 IsEqualGUID(&IID_IBindStatusCallback, riid))
177 *ppv = &This->IBindStatusCallback_iface;
179 else if (IsEqualGUID(&IID_IHttpNegotiate, riid))
181 *ppv = &This->IHttpNegotiate_iface;
183 else if (IsEqualGUID(&IID_IServiceProvider, riid) ||
184 IsEqualGUID(&IID_IBindStatusCallbackEx, riid) ||
185 IsEqualGUID(&IID_IInternetProtocol, riid) ||
186 IsEqualGUID(&IID_IHttpNegotiate2, riid))
188 return E_NOINTERFACE;
193 IBindStatusCallback_AddRef(iface);
197 FIXME("Unsupported riid = %s\n", debugstr_guid(riid));
199 return E_NOINTERFACE;
202 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
204 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
205 LONG ref = InterlockedIncrement(&This->ref);
207 TRACE("(%p) ref = %d\n", This, ref);
212 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
214 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
215 LONG ref = InterlockedDecrement(&This->ref);
217 TRACE("(%p) ref = %d\n", This, ref);
221 if (This->binding) IBinding_Release(This->binding);
222 if (This->stream) IStream_Release(This->stream);
223 if (This->body) GlobalFree(This->body);
230 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
231 DWORD reserved, IBinding *pbind)
233 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
235 TRACE("(%p)->(%d %p)\n", This, reserved, pbind);
237 if (!pbind) return E_INVALIDARG;
239 This->binding = pbind;
240 IBinding_AddRef(pbind);
242 httprequest_setreadystate(This->request, READYSTATE_LOADED);
244 return CreateStreamOnHGlobal(NULL, TRUE, &This->stream);
247 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pPriority)
249 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
251 TRACE("(%p)->(%p)\n", This, pPriority);
256 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
258 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
260 TRACE("(%p)->(%d)\n", This, reserved);
265 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
266 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
268 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
270 TRACE("(%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
271 debugstr_w(szStatusText));
276 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
277 HRESULT hr, LPCWSTR error)
279 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
281 TRACE("(%p)->(0x%08x %s)\n", This, hr, debugstr_w(error));
285 IBinding_Release(This->binding);
286 This->binding = NULL;
290 httprequest_setreadystate(This->request, READYSTATE_COMPLETE);
295 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
296 DWORD *bind_flags, BINDINFO *pbindinfo)
298 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
300 TRACE("(%p)->(%p %p)\n", This, bind_flags, pbindinfo);
303 if (This->request->async) *bind_flags |= BINDF_ASYNCHRONOUS;
305 if (This->request->verb != BINDVERB_GET && This->body)
307 pbindinfo->stgmedData.tymed = TYMED_HGLOBAL;
308 pbindinfo->stgmedData.u.hGlobal = This->body;
309 pbindinfo->cbstgmedData = GlobalSize(This->body);
310 /* callback owns passed body pointer */
311 IBindStatusCallback_QueryInterface(iface, &IID_IUnknown, (void**)&pbindinfo->stgmedData.pUnkForRelease);
314 pbindinfo->dwBindVerb = This->request->verb;
319 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
320 DWORD flags, DWORD size, FORMATETC *format, STGMEDIUM *stgmed)
322 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
327 TRACE("(%p)->(%08x %d %p %p)\n", This, flags, size, format, stgmed);
331 hr = IStream_Read(stgmed->u.pstm, buf, sizeof(buf), &read);
332 if (hr != S_OK) break;
334 hr = IStream_Write(This->stream, buf, read, &written);
335 } while((hr == S_OK) && written != 0 && read != 0);
337 httprequest_setreadystate(This->request, READYSTATE_INTERACTIVE);
342 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
343 REFIID riid, IUnknown *punk)
345 BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
347 FIXME("(%p)->(%s %p): stub\n", This, debugstr_guid(riid), punk);
352 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
353 BindStatusCallback_QueryInterface,
354 BindStatusCallback_AddRef,
355 BindStatusCallback_Release,
356 BindStatusCallback_OnStartBinding,
357 BindStatusCallback_GetPriority,
358 BindStatusCallback_OnLowResource,
359 BindStatusCallback_OnProgress,
360 BindStatusCallback_OnStopBinding,
361 BindStatusCallback_GetBindInfo,
362 BindStatusCallback_OnDataAvailable,
363 BindStatusCallback_OnObjectAvailable
366 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate *iface,
367 REFIID riid, void **ppv)
369 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
370 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
373 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate *iface)
375 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
376 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
379 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate *iface)
381 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
382 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
385 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *iface,
386 LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR *add_headers)
388 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
389 const struct reqheader *entry;
392 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(url), debugstr_w(headers), reserved, add_headers);
396 if (list_empty(&This->request->reqheaders)) return S_OK;
398 buff = CoTaskMemAlloc(This->request->reqheader_size*sizeof(WCHAR));
399 if (!buff) return E_OUTOFMEMORY;
402 LIST_FOR_EACH_ENTRY(entry, &This->request->reqheaders, struct reqheader, entry)
404 lstrcpyW(ptr, entry->header);
405 ptr += SysStringLen(entry->header);
407 lstrcpyW(ptr, colspaceW);
408 ptr += sizeof(colspaceW)/sizeof(WCHAR)-1;
410 lstrcpyW(ptr, entry->value);
411 ptr += SysStringLen(entry->value);
413 lstrcpyW(ptr, crlfW);
414 ptr += sizeof(crlfW)/sizeof(WCHAR)-1;
422 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD code,
423 LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders)
425 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
427 TRACE("(%p)->(%d %s %s %p)\n", This, code, debugstr_w(resp_headers),
428 debugstr_w(req_headers), add_reqheaders);
430 This->request->status = code;
435 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl = {
436 BSCHttpNegotiate_QueryInterface,
437 BSCHttpNegotiate_AddRef,
438 BSCHttpNegotiate_Release,
439 BSCHttpNegotiate_BeginningTransaction,
440 BSCHttpNegotiate_OnResponse
443 static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback **obj, const VARIANT *body)
445 BindStatusCallback *bsc;
449 hr = CreateBindCtx(0, &pbc);
450 if (hr != S_OK) return hr;
452 bsc = heap_alloc(sizeof(*bsc));
455 IBindCtx_Release(pbc);
456 return E_OUTOFMEMORY;
459 bsc->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
460 bsc->IHttpNegotiate_iface.lpVtbl = &BSCHttpNegotiateVtbl;
467 TRACE("created callback %p\n", bsc);
469 if (This->verb != BINDVERB_GET)
471 if (V_VT(body) == VT_BSTR)
473 LONG size = SysStringLen(V_BSTR(body)) * sizeof(WCHAR);
476 bsc->body = GlobalAlloc(GMEM_FIXED, size);
480 return E_OUTOFMEMORY;
483 ptr = GlobalLock(bsc->body);
484 memcpy(ptr, V_BSTR(body), size);
485 GlobalUnlock(bsc->body);
488 FIXME("unsupported body data type %d\n", V_VT(body));
491 hr = RegisterBindStatusCallback(pbc, &bsc->IBindStatusCallback_iface, NULL, 0);
496 hr = CreateURLMoniker(NULL, This->url, &moniker);
501 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (void**)&stream);
502 IMoniker_Release(moniker);
503 if (stream) IStream_Release(stream);
505 IBindCtx_Release(pbc);
510 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
518 static HRESULT WINAPI httprequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject)
520 httprequest *This = impl_from_IXMLHTTPRequest( iface );
521 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
523 if ( IsEqualGUID( riid, &IID_IXMLHTTPRequest) ||
524 IsEqualGUID( riid, &IID_IDispatch) ||
525 IsEqualGUID( riid, &IID_IUnknown) )
529 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
531 *ppvObject = &This->IObjectWithSite_iface;
533 else if (IsEqualGUID(&IID_IObjectSafety, riid))
535 *ppvObject = &This->IObjectSafety_iface;
539 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
541 return E_NOINTERFACE;
544 IXMLHTTPRequest_AddRef( iface );
549 static ULONG WINAPI httprequest_AddRef(IXMLHTTPRequest *iface)
551 httprequest *This = impl_from_IXMLHTTPRequest( iface );
552 ULONG ref = InterlockedIncrement( &This->ref );
553 TRACE("(%p)->(%u)\n", This, ref );
557 static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
559 httprequest *This = impl_from_IXMLHTTPRequest( iface );
560 ULONG ref = InterlockedDecrement( &This->ref );
562 TRACE("(%p)->(%u)\n", This, ref );
566 struct reqheader *header, *header2;
569 IUnknown_Release( This->site );
571 SysFreeString(This->url);
572 SysFreeString(This->user);
573 SysFreeString(This->password);
575 /* request headers */
576 LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct reqheader, entry)
578 list_remove(&header->entry);
579 SysFreeString(header->header);
580 SysFreeString(header->value);
584 /* detach callback object */
585 BindStatusCallback_Detach(This->bsc);
587 if (This->sink) IDispatch_Release(This->sink);
595 static HRESULT WINAPI httprequest_GetTypeInfoCount(IXMLHTTPRequest *iface, UINT *pctinfo)
597 httprequest *This = impl_from_IXMLHTTPRequest( iface );
599 TRACE("(%p)->(%p)\n", This, pctinfo);
606 static HRESULT WINAPI httprequest_GetTypeInfo(IXMLHTTPRequest *iface, UINT iTInfo,
607 LCID lcid, ITypeInfo **ppTInfo)
609 httprequest *This = impl_from_IXMLHTTPRequest( iface );
612 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
614 hr = get_typeinfo(IXMLHTTPRequest_tid, ppTInfo);
619 static HRESULT WINAPI httprequest_GetIDsOfNames(IXMLHTTPRequest *iface, REFIID riid,
620 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
622 httprequest *This = impl_from_IXMLHTTPRequest( iface );
626 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
629 if(!rgszNames || cNames == 0 || !rgDispId)
632 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
635 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
636 ITypeInfo_Release(typeinfo);
642 static HRESULT WINAPI httprequest_Invoke(IXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid,
643 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
644 EXCEPINFO *pExcepInfo, UINT *puArgErr)
646 httprequest *This = impl_from_IXMLHTTPRequest( iface );
650 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
651 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
653 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
656 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLHTTPRequest_iface, dispIdMember, wFlags,
657 pDispParams, pVarResult, pExcepInfo, puArgErr);
658 ITypeInfo_Release(typeinfo);
664 static HRESULT WINAPI httprequest_open(IXMLHTTPRequest *iface, BSTR method, BSTR url,
665 VARIANT async, VARIANT user, VARIANT password)
667 httprequest *This = impl_from_IXMLHTTPRequest( iface );
671 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(method), debugstr_w(url),
672 debugstr_variant(&async));
674 if (!method || !url) return E_INVALIDARG;
676 /* free previously set data */
677 SysFreeString(This->url);
678 SysFreeString(This->user);
679 SysFreeString(This->password);
680 This->url = This->user = This->password = NULL;
682 if (lstrcmpiW(method, MethodGetW) == 0)
684 This->verb = BINDVERB_GET;
686 else if (lstrcmpiW(method, MethodPutW) == 0)
688 This->verb = BINDVERB_PUT;
690 else if (lstrcmpiW(method, MethodPostW) == 0)
692 This->verb = BINDVERB_POST;
696 FIXME("unsupported request type %s\n", debugstr_w(method));
701 This->url = SysAllocString(url);
703 hr = VariantChangeType(&async, &async, 0, VT_BOOL);
704 This->async = hr == S_OK && V_BOOL(&async) == VARIANT_TRUE;
707 hr = VariantChangeType(&str, &user, 0, VT_BSTR);
709 This->user = V_BSTR(&str);
711 hr = VariantChangeType(&str, &password, 0, VT_BSTR);
713 This->password = V_BSTR(&str);
715 httprequest_setreadystate(This, READYSTATE_LOADING);
720 static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR header, BSTR value)
722 httprequest *This = impl_from_IXMLHTTPRequest( iface );
723 struct reqheader *entry;
725 TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
727 if (!header || !*header) return E_INVALIDARG;
728 if (This->state != READYSTATE_LOADING) return E_FAIL;
729 if (!value) return E_INVALIDARG;
731 /* replace existing header value if already added */
732 LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct reqheader, entry)
734 if (lstrcmpW(entry->header, header) == 0)
736 LONG length = SysStringLen(entry->value);
739 hr = SysReAllocString(&entry->value, value) ? S_OK : E_OUTOFMEMORY;
742 This->reqheader_size += (SysStringLen(entry->value) - length);
748 entry = heap_alloc(sizeof(*entry));
749 if (!entry) return E_OUTOFMEMORY;
752 entry->header = SysAllocString(header);
753 entry->value = SysAllocString(value);
755 /* header length including null terminator */
756 This->reqheader_size += SysStringLen(entry->header) + sizeof(colspaceW)/sizeof(WCHAR) +
757 SysStringLen(entry->value) + sizeof(crlfW)/sizeof(WCHAR) - 1;
759 list_add_head(&This->reqheaders, &entry->entry);
764 static HRESULT WINAPI httprequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR *pbstrValue)
766 httprequest *This = impl_from_IXMLHTTPRequest( iface );
768 FIXME("stub (%p) %s %p\n", This, debugstr_w(bstrHeader), pbstrValue);
773 static HRESULT WINAPI httprequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *pbstrHeaders)
775 httprequest *This = impl_from_IXMLHTTPRequest( iface );
777 FIXME("stub (%p) %p\n", This, pbstrHeaders);
782 static HRESULT WINAPI httprequest_send(IXMLHTTPRequest *iface, VARIANT body)
784 httprequest *This = impl_from_IXMLHTTPRequest( iface );
785 BindStatusCallback *bsc = NULL;
788 TRACE("(%p)->(%s)\n", This, debugstr_variant(&body));
790 if (This->state != READYSTATE_LOADING) return E_FAIL;
792 hr = BindStatusCallback_create(This, &bsc, &body);
793 if (FAILED(hr)) return hr;
795 BindStatusCallback_Detach(This->bsc);
801 static HRESULT WINAPI httprequest_abort(IXMLHTTPRequest *iface)
803 httprequest *This = impl_from_IXMLHTTPRequest( iface );
805 TRACE("(%p)\n", This);
807 BindStatusCallback_Detach(This->bsc);
810 httprequest_setreadystate(This, READYSTATE_UNINITIALIZED);
815 static HRESULT WINAPI httprequest_get_status(IXMLHTTPRequest *iface, LONG *status)
817 httprequest *This = impl_from_IXMLHTTPRequest( iface );
819 TRACE("(%p)->(%p)\n", This, status);
821 if (!status) return E_INVALIDARG;
822 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
824 *status = This->status;
829 static HRESULT WINAPI httprequest_get_statusText(IXMLHTTPRequest *iface, BSTR *pbstrStatus)
831 httprequest *This = impl_from_IXMLHTTPRequest( iface );
833 FIXME("stub %p %p\n", This, pbstrStatus);
838 static HRESULT WINAPI httprequest_get_responseXML(IXMLHTTPRequest *iface, IDispatch **body)
840 httprequest *This = impl_from_IXMLHTTPRequest( iface );
841 IXMLDOMDocument3 *doc;
845 TRACE("(%p)->(%p)\n", This, body);
847 if (!body) return E_INVALIDARG;
848 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
850 hr = DOMDocument_create(&CLSID_DOMDocument, NULL, (void**)&doc);
851 if (hr != S_OK) return hr;
853 hr = IXMLHTTPRequest_get_responseText(iface, &str);
858 hr = IXMLDOMDocument3_loadXML(doc, str, &ok);
862 IXMLDOMDocument3_QueryInterface(doc, &IID_IDispatch, (void**)body);
863 IXMLDOMDocument3_Release(doc);
868 static HRESULT WINAPI httprequest_get_responseText(IXMLHTTPRequest *iface, BSTR *body)
870 httprequest *This = impl_from_IXMLHTTPRequest( iface );
874 TRACE("(%p)->(%p)\n", This, body);
876 if (!body) return E_INVALIDARG;
877 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
879 hr = GetHGlobalFromStream(This->bsc->stream, &hglobal);
882 xmlChar *ptr = GlobalLock(hglobal);
883 DWORD size = GlobalSize(hglobal);
884 xmlCharEncoding encoding = XML_CHAR_ENCODING_UTF8;
886 /* try to determine data encoding */
889 encoding = xmlDetectCharEncoding(ptr, 4);
890 TRACE("detected encoding: %s\n", xmlGetCharEncodingName(encoding));
891 if ( encoding != XML_CHAR_ENCODING_UTF8 &&
892 encoding != XML_CHAR_ENCODING_UTF16LE &&
893 encoding != XML_CHAR_ENCODING_NONE )
895 FIXME("unsupported encoding: %s\n", xmlGetCharEncodingName(encoding));
896 GlobalUnlock(hglobal);
901 /* without BOM assume UTF-8 */
902 if (encoding == XML_CHAR_ENCODING_UTF8 ||
903 encoding == XML_CHAR_ENCODING_NONE )
905 DWORD length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)ptr, size, NULL, 0);
907 *body = SysAllocStringLen(NULL, length);
909 MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)ptr, size, *body, length);
912 *body = SysAllocStringByteLen((LPCSTR)ptr, size);
914 if (!*body) hr = E_OUTOFMEMORY;
915 GlobalUnlock(hglobal);
921 static HRESULT WINAPI httprequest_get_responseBody(IXMLHTTPRequest *iface, VARIANT *body)
923 httprequest *This = impl_from_IXMLHTTPRequest( iface );
927 TRACE("(%p)->(%p)\n", This, body);
929 if (!body) return E_INVALIDARG;
930 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
932 hr = GetHGlobalFromStream(This->bsc->stream, &hglobal);
935 void *ptr = GlobalLock(hglobal);
936 DWORD size = GlobalSize(hglobal);
938 SAFEARRAYBOUND bound;
942 bound.cElements = size;
943 array = SafeArrayCreate(VT_UI1, 1, &bound);
949 V_VT(body) = VT_ARRAY | VT_UI1;
950 V_ARRAY(body) = array;
952 hr = SafeArrayAccessData(array, &dest);
955 memcpy(dest, ptr, size);
956 SafeArrayUnaccessData(array);
966 GlobalUnlock(hglobal);
972 static HRESULT WINAPI httprequest_get_responseStream(IXMLHTTPRequest *iface, VARIANT *pvarBody)
974 httprequest *This = impl_from_IXMLHTTPRequest( iface );
976 FIXME("stub %p %p\n", This, pvarBody);
981 static HRESULT WINAPI httprequest_get_readyState(IXMLHTTPRequest *iface, LONG *state)
983 httprequest *This = impl_from_IXMLHTTPRequest( iface );
985 TRACE("(%p)->(%p)\n", This, state);
987 if (!state) return E_INVALIDARG;
989 *state = This->state;
993 static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *sink)
995 httprequest *This = impl_from_IXMLHTTPRequest( iface );
997 TRACE("(%p)->(%p)\n", This, sink);
999 if (This->sink) IDispatch_Release(This->sink);
1000 if ((This->sink = sink)) IDispatch_AddRef(This->sink);
1005 static const struct IXMLHTTPRequestVtbl dimimpl_vtbl =
1007 httprequest_QueryInterface,
1009 httprequest_Release,
1010 httprequest_GetTypeInfoCount,
1011 httprequest_GetTypeInfo,
1012 httprequest_GetIDsOfNames,
1015 httprequest_setRequestHeader,
1016 httprequest_getResponseHeader,
1017 httprequest_getAllResponseHeaders,
1020 httprequest_get_status,
1021 httprequest_get_statusText,
1022 httprequest_get_responseXML,
1023 httprequest_get_responseText,
1024 httprequest_get_responseBody,
1025 httprequest_get_responseStream,
1026 httprequest_get_readyState,
1027 httprequest_put_onreadystatechange
1030 /* IObjectWithSite */
1031 static HRESULT WINAPI
1032 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1034 httprequest *This = impl_from_IObjectWithSite(iface);
1035 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest *)This, riid, ppvObject );
1038 static ULONG WINAPI httprequest_ObjectWithSite_AddRef( IObjectWithSite* iface )
1040 httprequest *This = impl_from_IObjectWithSite(iface);
1041 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest *)This);
1044 static ULONG WINAPI httprequest_ObjectWithSite_Release( IObjectWithSite* iface )
1046 httprequest *This = impl_from_IObjectWithSite(iface);
1047 return IXMLHTTPRequest_Release((IXMLHTTPRequest *)This);
1050 static HRESULT WINAPI httprequest_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
1052 httprequest *This = impl_from_IObjectWithSite(iface);
1054 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
1059 return IUnknown_QueryInterface( This->site, iid, ppvSite );
1062 static HRESULT WINAPI httprequest_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
1064 httprequest *This = impl_from_IObjectWithSite(iface);
1066 TRACE("(%p)->(%p)\n", iface, punk);
1069 IUnknown_AddRef( punk );
1072 IUnknown_Release( This->site );
1079 static const IObjectWithSiteVtbl httprequestObjectSite =
1081 httprequest_ObjectWithSite_QueryInterface,
1082 httprequest_ObjectWithSite_AddRef,
1083 httprequest_ObjectWithSite_Release,
1084 httprequest_ObjectWithSite_SetSite,
1085 httprequest_ObjectWithSite_GetSite
1089 static HRESULT WINAPI httprequest_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
1091 httprequest *This = impl_from_IObjectSafety(iface);
1092 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest *)This, riid, ppv );
1095 static ULONG WINAPI httprequest_Safety_AddRef(IObjectSafety *iface)
1097 httprequest *This = impl_from_IObjectSafety(iface);
1098 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest *)This);
1101 static ULONG WINAPI httprequest_Safety_Release(IObjectSafety *iface)
1103 httprequest *This = impl_from_IObjectSafety(iface);
1104 return IXMLHTTPRequest_Release((IXMLHTTPRequest *)This);
1107 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
1109 static HRESULT WINAPI httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1110 DWORD *supported, DWORD *enabled)
1112 httprequest *This = impl_from_IObjectSafety(iface);
1114 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
1116 if(!supported || !enabled) return E_POINTER;
1118 *supported = SAFETY_SUPPORTED_OPTIONS;
1119 *enabled = This->safeopt;
1124 static HRESULT WINAPI httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1125 DWORD mask, DWORD enabled)
1127 httprequest *This = impl_from_IObjectSafety(iface);
1128 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
1130 if ((mask & ~SAFETY_SUPPORTED_OPTIONS) != 0)
1133 This->safeopt = enabled & mask & SAFETY_SUPPORTED_OPTIONS;
1137 #undef SAFETY_SUPPORTED_OPTIONS
1139 static const IObjectSafetyVtbl httprequestObjectSafety = {
1140 httprequest_Safety_QueryInterface,
1141 httprequest_Safety_AddRef,
1142 httprequest_Safety_Release,
1143 httprequest_Safety_GetInterfaceSafetyOptions,
1144 httprequest_Safety_SetInterfaceSafetyOptions
1147 HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
1152 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
1154 req = heap_alloc( sizeof (*req) );
1156 return E_OUTOFMEMORY;
1158 req->IXMLHTTPRequest_iface.lpVtbl = &dimimpl_vtbl;
1159 req->IObjectWithSite_iface.lpVtbl = &httprequestObjectSite;
1160 req->IObjectSafety_iface.lpVtbl = &httprequestObjectSafety;
1165 req->url = req->user = req->password = NULL;
1167 req->state = READYSTATE_UNINITIALIZED;
1172 req->reqheader_size = 0;
1173 list_init(&req->reqheaders);
1177 *ppObj = &req->IXMLHTTPRequest_iface;
1179 TRACE("returning iface %p\n", *ppObj);
1186 HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
1188 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
1189 "libxml2 support was not present at compile time.\n");