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 static 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
);
669 VARIANT str
, is_async
;
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 VariantInit(&is_async
);
704 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
705 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
) == VARIANT_TRUE
;
708 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
710 This
->user
= V_BSTR(&str
);
712 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
714 This
->password
= V_BSTR(&str
);
716 httprequest_setreadystate(This
, READYSTATE_LOADING
);
721 static HRESULT WINAPI
httprequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
723 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
724 struct reqheader
*entry
;
726 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
728 if (!header
|| !*header
) return E_INVALIDARG
;
729 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
730 if (!value
) return E_INVALIDARG
;
732 /* replace existing header value if already added */
733 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct reqheader
, entry
)
735 if (lstrcmpW(entry
->header
, header
) == 0)
737 LONG length
= SysStringLen(entry
->value
);
740 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
743 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
749 entry
= heap_alloc(sizeof(*entry
));
750 if (!entry
) return E_OUTOFMEMORY
;
753 entry
->header
= SysAllocString(header
);
754 entry
->value
= SysAllocString(value
);
756 /* header length including null terminator */
757 This
->reqheader_size
+= SysStringLen(entry
->header
) + sizeof(colspaceW
)/sizeof(WCHAR
) +
758 SysStringLen(entry
->value
) + sizeof(crlfW
)/sizeof(WCHAR
) - 1;
760 list_add_head(&This
->reqheaders
, &entry
->entry
);
765 static HRESULT WINAPI
httprequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR bstrHeader
, BSTR
*pbstrValue
)
767 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
769 FIXME("stub (%p) %s %p\n", This
, debugstr_w(bstrHeader
), pbstrValue
);
774 static HRESULT WINAPI
httprequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*pbstrHeaders
)
776 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
778 FIXME("stub (%p) %p\n", This
, pbstrHeaders
);
783 static HRESULT WINAPI
httprequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
785 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
786 BindStatusCallback
*bsc
= NULL
;
789 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
791 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
793 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
794 if (FAILED(hr
)) return hr
;
796 BindStatusCallback_Detach(This
->bsc
);
802 static HRESULT WINAPI
httprequest_abort(IXMLHTTPRequest
*iface
)
804 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
806 TRACE("(%p)\n", This
);
808 BindStatusCallback_Detach(This
->bsc
);
811 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
816 static HRESULT WINAPI
httprequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
818 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
820 TRACE("(%p)->(%p)\n", This
, status
);
822 if (!status
) return E_INVALIDARG
;
823 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
825 *status
= This
->status
;
830 static HRESULT WINAPI
httprequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*pbstrStatus
)
832 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
834 FIXME("stub %p %p\n", This
, pbstrStatus
);
839 static HRESULT WINAPI
httprequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
841 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
842 IXMLDOMDocument3
*doc
;
846 TRACE("(%p)->(%p)\n", This
, body
);
848 if (!body
) return E_INVALIDARG
;
849 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
851 hr
= DOMDocument_create(MSXML_DEFAULT
, NULL
, (void**)&doc
);
852 if (hr
!= S_OK
) return hr
;
854 hr
= IXMLHTTPRequest_get_responseText(iface
, &str
);
859 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
863 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
864 IXMLDOMDocument3_Release(doc
);
869 static HRESULT WINAPI
httprequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
871 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
875 TRACE("(%p)->(%p)\n", This
, body
);
877 if (!body
) return E_INVALIDARG
;
878 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
880 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
883 xmlChar
*ptr
= GlobalLock(hglobal
);
884 DWORD size
= GlobalSize(hglobal
);
885 xmlCharEncoding encoding
= XML_CHAR_ENCODING_UTF8
;
887 /* try to determine data encoding */
890 encoding
= xmlDetectCharEncoding(ptr
, 4);
891 TRACE("detected encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
892 if ( encoding
!= XML_CHAR_ENCODING_UTF8
&&
893 encoding
!= XML_CHAR_ENCODING_UTF16LE
&&
894 encoding
!= XML_CHAR_ENCODING_NONE
)
896 FIXME("unsupported encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
897 GlobalUnlock(hglobal
);
902 /* without BOM assume UTF-8 */
903 if (encoding
== XML_CHAR_ENCODING_UTF8
||
904 encoding
== XML_CHAR_ENCODING_NONE
)
906 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)ptr
, size
, NULL
, 0);
908 *body
= SysAllocStringLen(NULL
, length
);
910 MultiByteToWideChar( CP_UTF8
, 0, (LPCSTR
)ptr
, size
, *body
, length
);
913 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
915 if (!*body
) hr
= E_OUTOFMEMORY
;
916 GlobalUnlock(hglobal
);
922 static HRESULT WINAPI
httprequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
924 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
928 TRACE("(%p)->(%p)\n", This
, body
);
930 if (!body
) return E_INVALIDARG
;
931 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
933 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
936 void *ptr
= GlobalLock(hglobal
);
937 DWORD size
= GlobalSize(hglobal
);
939 SAFEARRAYBOUND bound
;
943 bound
.cElements
= size
;
944 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
950 V_VT(body
) = VT_ARRAY
| VT_UI1
;
951 V_ARRAY(body
) = array
;
953 hr
= SafeArrayAccessData(array
, &dest
);
956 memcpy(dest
, ptr
, size
);
957 SafeArrayUnaccessData(array
);
967 GlobalUnlock(hglobal
);
973 static HRESULT WINAPI
httprequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*pvarBody
)
975 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
977 FIXME("stub %p %p\n", This
, pvarBody
);
982 static HRESULT WINAPI
httprequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
984 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
986 TRACE("(%p)->(%p)\n", This
, state
);
988 if (!state
) return E_INVALIDARG
;
990 *state
= This
->state
;
994 static HRESULT WINAPI
httprequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
996 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
998 TRACE("(%p)->(%p)\n", This
, sink
);
1000 if (This
->sink
) IDispatch_Release(This
->sink
);
1001 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1006 static const struct IXMLHTTPRequestVtbl dimimpl_vtbl
=
1008 httprequest_QueryInterface
,
1010 httprequest_Release
,
1011 httprequest_GetTypeInfoCount
,
1012 httprequest_GetTypeInfo
,
1013 httprequest_GetIDsOfNames
,
1016 httprequest_setRequestHeader
,
1017 httprequest_getResponseHeader
,
1018 httprequest_getAllResponseHeaders
,
1021 httprequest_get_status
,
1022 httprequest_get_statusText
,
1023 httprequest_get_responseXML
,
1024 httprequest_get_responseText
,
1025 httprequest_get_responseBody
,
1026 httprequest_get_responseStream
,
1027 httprequest_get_readyState
,
1028 httprequest_put_onreadystatechange
1031 /* IObjectWithSite */
1032 static HRESULT WINAPI
1033 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1035 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1036 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest
*)This
, riid
, ppvObject
);
1039 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1041 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1042 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest
*)This
);
1045 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1047 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1048 return IXMLHTTPRequest_Release((IXMLHTTPRequest
*)This
);
1051 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1053 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1055 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1060 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1063 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1065 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1067 TRACE("(%p)->(%p)\n", iface
, punk
);
1070 IUnknown_AddRef( punk
);
1073 IUnknown_Release( This
->site
);
1080 static const IObjectWithSiteVtbl httprequestObjectSite
=
1082 httprequest_ObjectWithSite_QueryInterface
,
1083 httprequest_ObjectWithSite_AddRef
,
1084 httprequest_ObjectWithSite_Release
,
1085 httprequest_ObjectWithSite_SetSite
,
1086 httprequest_ObjectWithSite_GetSite
1090 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1092 httprequest
*This
= impl_from_IObjectSafety(iface
);
1093 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest
*)This
, riid
, ppv
);
1096 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1098 httprequest
*This
= impl_from_IObjectSafety(iface
);
1099 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest
*)This
);
1102 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1104 httprequest
*This
= impl_from_IObjectSafety(iface
);
1105 return IXMLHTTPRequest_Release((IXMLHTTPRequest
*)This
);
1108 #define SAFETY_SUPPORTED_OPTIONS (INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER)
1110 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1111 DWORD
*supported
, DWORD
*enabled
)
1113 httprequest
*This
= impl_from_IObjectSafety(iface
);
1115 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1117 if(!supported
|| !enabled
) return E_POINTER
;
1119 *supported
= SAFETY_SUPPORTED_OPTIONS
;
1120 *enabled
= This
->safeopt
;
1125 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1126 DWORD mask
, DWORD enabled
)
1128 httprequest
*This
= impl_from_IObjectSafety(iface
);
1129 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
1131 if ((mask
& ~SAFETY_SUPPORTED_OPTIONS
) != 0)
1134 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
1139 #undef SAFETY_SUPPORTED_OPTIONS
1141 static const IObjectSafetyVtbl httprequestObjectSafety
= {
1142 httprequest_Safety_QueryInterface
,
1143 httprequest_Safety_AddRef
,
1144 httprequest_Safety_Release
,
1145 httprequest_Safety_GetInterfaceSafetyOptions
,
1146 httprequest_Safety_SetInterfaceSafetyOptions
1149 HRESULT
XMLHTTPRequest_create(IUnknown
*pUnkOuter
, void **ppObj
)
1154 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
1156 req
= heap_alloc( sizeof (*req
) );
1158 return E_OUTOFMEMORY
;
1160 req
->IXMLHTTPRequest_iface
.lpVtbl
= &dimimpl_vtbl
;
1161 req
->IObjectWithSite_iface
.lpVtbl
= &httprequestObjectSite
;
1162 req
->IObjectSafety_iface
.lpVtbl
= &httprequestObjectSafety
;
1167 req
->url
= req
->user
= req
->password
= NULL
;
1169 req
->state
= READYSTATE_UNINITIALIZED
;
1174 req
->reqheader_size
= 0;
1175 list_init(&req
->reqheaders
);
1179 *ppObj
= &req
->IXMLHTTPRequest_iface
;
1181 TRACE("returning iface %p\n", *ppObj
);
1188 HRESULT
XMLHTTPRequest_create(IUnknown
*pUnkOuter
, void **ppObj
)
1190 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
1191 "libxml2 support was not present at compile time.\n");