2 * IXMLHTTPRequest implementation
4 * Copyright 2008 Alistair Leslie-Hughes
5 * Copyright 2010-2012 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
40 #include "msxml_dispex.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
46 static const WCHAR colspaceW
[] = {':',' ',0};
47 static const WCHAR crlfW
[] = {'\r','\n',0};
48 static const DWORD safety_supported_options
=
49 INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
50 INTERFACESAFE_FOR_UNTRUSTED_DATA
|
51 INTERFACE_USES_SECURITY_MANAGER
;
53 typedef struct BindStatusCallback BindStatusCallback
;
64 IXMLHTTPRequest IXMLHTTPRequest_iface
;
65 IObjectWithSite IObjectWithSite_iface
;
66 IObjectSafety IObjectSafety_iface
;
67 ISupportErrorInfo ISupportErrorInfo_iface
;
79 struct list reqheaders
;
80 /* cached resulting custom request headers string length in WCHARs */
82 /* use UTF-8 content type */
83 BOOL use_utf8_content
;
85 /* response headers */
86 struct list respheaders
;
94 BindStatusCallback
*bsc
;
108 IServerXMLHTTPRequest IServerXMLHTTPRequest_iface
;
111 static inline httprequest
*impl_from_IXMLHTTPRequest( IXMLHTTPRequest
*iface
)
113 return CONTAINING_RECORD(iface
, httprequest
, IXMLHTTPRequest_iface
);
116 static inline httprequest
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
118 return CONTAINING_RECORD(iface
, httprequest
, IObjectWithSite_iface
);
121 static inline httprequest
*impl_from_IObjectSafety(IObjectSafety
*iface
)
123 return CONTAINING_RECORD(iface
, httprequest
, IObjectSafety_iface
);
126 static inline httprequest
*impl_from_ISupportErrorInfo(ISupportErrorInfo
*iface
)
128 return CONTAINING_RECORD(iface
, httprequest
, ISupportErrorInfo_iface
);
131 static inline serverhttp
*impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest
*iface
)
133 return CONTAINING_RECORD(iface
, serverhttp
, IServerXMLHTTPRequest_iface
);
136 static void httprequest_setreadystate(httprequest
*This
, READYSTATE state
)
138 READYSTATE last
= This
->state
;
139 static const char* readystates
[] = {
140 "READYSTATE_UNINITIALIZED",
141 "READYSTATE_LOADING",
143 "READYSTATE_INTERACTIVE",
144 "READYSTATE_COMPLETE"};
148 TRACE("state %s\n", readystates
[state
]);
150 if (This
->sink
&& last
!= state
)
154 memset(¶ms
, 0, sizeof(params
));
155 IDispatch_Invoke(This
->sink
, 0, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, ¶ms
, 0, 0, 0);
159 static void free_response_headers(httprequest
*This
)
161 struct httpheader
*header
, *header2
;
163 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->respheaders
, struct httpheader
, entry
)
165 list_remove(&header
->entry
);
166 SysFreeString(header
->header
);
167 SysFreeString(header
->value
);
171 SysFreeString(This
->raw_respheaders
);
172 This
->raw_respheaders
= NULL
;
175 static void free_request_headers(httprequest
*This
)
177 struct httpheader
*header
, *header2
;
179 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->reqheaders
, struct httpheader
, entry
)
181 list_remove(&header
->entry
);
182 SysFreeString(header
->header
);
183 SysFreeString(header
->value
);
188 struct BindStatusCallback
190 IBindStatusCallback IBindStatusCallback_iface
;
191 IHttpNegotiate IHttpNegotiate_iface
;
192 IAuthenticate IAuthenticate_iface
;
196 httprequest
*request
;
201 /* request body data */
205 static inline BindStatusCallback
*impl_from_IBindStatusCallback( IBindStatusCallback
*iface
)
207 return CONTAINING_RECORD(iface
, BindStatusCallback
, IBindStatusCallback_iface
);
210 static inline BindStatusCallback
*impl_from_IHttpNegotiate( IHttpNegotiate
*iface
)
212 return CONTAINING_RECORD(iface
, BindStatusCallback
, IHttpNegotiate_iface
);
215 static inline BindStatusCallback
*impl_from_IAuthenticate( IAuthenticate
*iface
)
217 return CONTAINING_RECORD(iface
, BindStatusCallback
, IAuthenticate_iface
);
220 static void BindStatusCallback_Detach(BindStatusCallback
*bsc
)
224 if (bsc
->binding
) IBinding_Abort(bsc
->binding
);
225 bsc
->request
->bsc
= NULL
;
227 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
231 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
232 REFIID riid
, void **ppv
)
234 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
238 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
240 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
241 IsEqualGUID(&IID_IBindStatusCallback
, riid
))
243 *ppv
= &This
->IBindStatusCallback_iface
;
245 else if (IsEqualGUID(&IID_IHttpNegotiate
, riid
))
247 *ppv
= &This
->IHttpNegotiate_iface
;
249 else if (IsEqualGUID(&IID_IAuthenticate
, riid
))
251 *ppv
= &This
->IAuthenticate_iface
;
253 else if (IsEqualGUID(&IID_IServiceProvider
, riid
) ||
254 IsEqualGUID(&IID_IBindStatusCallbackEx
, riid
) ||
255 IsEqualGUID(&IID_IInternetProtocol
, riid
) ||
256 IsEqualGUID(&IID_IHttpNegotiate2
, riid
))
258 return E_NOINTERFACE
;
263 IBindStatusCallback_AddRef(iface
);
267 FIXME("Unsupported riid = %s\n", debugstr_guid(riid
));
269 return E_NOINTERFACE
;
272 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
274 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
275 LONG ref
= InterlockedIncrement(&This
->ref
);
277 TRACE("%p, refcount %ld.\n", iface
, ref
);
282 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
284 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
285 LONG ref
= InterlockedDecrement(&This
->ref
);
287 TRACE("%p, refcount %ld.\n", iface
, ref
);
291 if (This
->binding
) IBinding_Release(This
->binding
);
292 if (This
->stream
) IStream_Release(This
->stream
);
293 if (This
->body
) GlobalFree(This
->body
);
300 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
301 DWORD reserved
, IBinding
*pbind
)
303 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
305 TRACE("%p, %ld, %p.\n", iface
, reserved
, pbind
);
307 if (!pbind
) return E_INVALIDARG
;
309 This
->binding
= pbind
;
310 IBinding_AddRef(pbind
);
312 httprequest_setreadystate(This
->request
, READYSTATE_LOADED
);
314 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
317 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pPriority
)
319 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
321 TRACE("(%p)->(%p)\n", This
, pPriority
);
326 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
328 TRACE("%p, %ld.\n", iface
, reserved
);
333 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
334 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
336 TRACE("%p, %lu, %lu, %lu, %s.\n", iface
, ulProgress
, ulProgressMax
, ulStatusCode
,
337 debugstr_w(szStatusText
));
342 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
343 HRESULT hr
, LPCWSTR error
)
345 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
347 TRACE("%p, %#lx, %s.\n", iface
, hr
, debugstr_w(error
));
351 IBinding_Release(This
->binding
);
352 This
->binding
= NULL
;
357 BindStatusCallback_Detach(This
->request
->bsc
);
358 This
->request
->bsc
= This
;
359 httprequest_setreadystate(This
->request
, READYSTATE_COMPLETE
);
365 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
366 DWORD
*bind_flags
, BINDINFO
*pbindinfo
)
368 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
370 TRACE("(%p)->(%p %p)\n", This
, bind_flags
, pbindinfo
);
373 if (This
->request
->async
) *bind_flags
|= BINDF_ASYNCHRONOUS
;
375 if (This
->request
->verb
!= BINDVERB_GET
&& This
->body
)
377 pbindinfo
->stgmedData
.tymed
= TYMED_HGLOBAL
;
378 pbindinfo
->stgmedData
.u
.hGlobal
= This
->body
;
379 pbindinfo
->cbstgmedData
= GlobalSize(This
->body
);
380 /* callback owns passed body pointer */
381 IBindStatusCallback_QueryInterface(iface
, &IID_IUnknown
, (void**)&pbindinfo
->stgmedData
.pUnkForRelease
);
384 pbindinfo
->dwBindVerb
= This
->request
->verb
;
385 if (This
->request
->verb
== BINDVERB_CUSTOM
)
387 pbindinfo
->szCustomVerb
= CoTaskMemAlloc(SysStringByteLen(This
->request
->custom
)+sizeof(WCHAR
));
388 lstrcpyW(pbindinfo
->szCustomVerb
, This
->request
->custom
);
394 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
395 DWORD flags
, DWORD size
, FORMATETC
*format
, STGMEDIUM
*stgmed
)
397 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
402 TRACE("%p, %#lx, %lu, %p, %p.\n", iface
, flags
, size
, format
, stgmed
);
406 hr
= IStream_Read(stgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
407 if (hr
!= S_OK
) break;
409 hr
= IStream_Write(This
->stream
, buf
, read
, &written
);
410 } while((hr
== S_OK
) && written
!= 0 && read
!= 0);
412 httprequest_setreadystate(This
->request
, READYSTATE_INTERACTIVE
);
417 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
418 REFIID riid
, IUnknown
*punk
)
420 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
422 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
427 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
428 BindStatusCallback_QueryInterface
,
429 BindStatusCallback_AddRef
,
430 BindStatusCallback_Release
,
431 BindStatusCallback_OnStartBinding
,
432 BindStatusCallback_GetPriority
,
433 BindStatusCallback_OnLowResource
,
434 BindStatusCallback_OnProgress
,
435 BindStatusCallback_OnStopBinding
,
436 BindStatusCallback_GetBindInfo
,
437 BindStatusCallback_OnDataAvailable
,
438 BindStatusCallback_OnObjectAvailable
441 static HRESULT WINAPI
BSCHttpNegotiate_QueryInterface(IHttpNegotiate
*iface
,
442 REFIID riid
, void **ppv
)
444 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
445 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
448 static ULONG WINAPI
BSCHttpNegotiate_AddRef(IHttpNegotiate
*iface
)
450 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
451 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
454 static ULONG WINAPI
BSCHttpNegotiate_Release(IHttpNegotiate
*iface
)
456 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
457 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
460 static HRESULT WINAPI
BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate
*iface
,
461 LPCWSTR url
, LPCWSTR headers
, DWORD reserved
, LPWSTR
*add_headers
)
463 static const WCHAR content_type_utf8W
[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
464 't','e','x','t','/','p','l','a','i','n',';','c','h','a','r','s','e','t','=','u','t','f','-','8','\r','\n',0};
465 static const WCHAR refererW
[] = {'R','e','f','e','r','e','r',':',' ',0};
467 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
468 const struct httpheader
*entry
;
469 BSTR base_uri
= NULL
;
473 TRACE("%p, %s, %s, %ld, %p.\n", iface
, debugstr_w(url
), debugstr_w(headers
), reserved
, add_headers
);
477 if (This
->request
->use_utf8_content
)
478 size
= sizeof(content_type_utf8W
);
480 if (!list_empty(&This
->request
->reqheaders
))
481 size
+= This
->request
->reqheader_size
*sizeof(WCHAR
);
483 if (This
->request
->base_uri
)
485 IUri_GetRawUri(This
->request
->base_uri
, &base_uri
);
486 size
+= SysStringLen(base_uri
)*sizeof(WCHAR
) + sizeof(refererW
) + sizeof(crlfW
);
491 SysFreeString(base_uri
);
495 buff
= CoTaskMemAlloc(size
);
498 SysFreeString(base_uri
);
499 return E_OUTOFMEMORY
;
503 if (This
->request
->use_utf8_content
)
505 lstrcpyW(ptr
, content_type_utf8W
);
506 ptr
+= ARRAY_SIZE(content_type_utf8W
) - 1;
511 lstrcpyW(ptr
, refererW
);
512 lstrcatW(ptr
, base_uri
);
513 lstrcatW(ptr
, crlfW
);
514 ptr
+= lstrlenW(refererW
) + SysStringLen(base_uri
) + lstrlenW(crlfW
);
515 SysFreeString(base_uri
);
519 LIST_FOR_EACH_ENTRY(entry
, &This
->request
->reqheaders
, struct httpheader
, entry
)
521 lstrcpyW(ptr
, entry
->header
);
522 ptr
+= SysStringLen(entry
->header
);
524 lstrcpyW(ptr
, colspaceW
);
525 ptr
+= ARRAY_SIZE(colspaceW
) - 1;
527 lstrcpyW(ptr
, entry
->value
);
528 ptr
+= SysStringLen(entry
->value
);
530 lstrcpyW(ptr
, crlfW
);
531 ptr
+= ARRAY_SIZE(crlfW
) - 1;
539 static void add_response_header(httprequest
*This
, const WCHAR
*data
, int len
)
541 struct httpheader
*entry
;
542 const WCHAR
*ptr
= data
;
549 header
= SysAllocStringLen(data
, ptr
-data
);
550 /* skip leading spaces for a value */
551 while (*++ptr
== ' ')
553 value
= SysAllocStringLen(ptr
, len
-(ptr
-data
));
562 TRACE("got header %s:%s\n", debugstr_w(header
), debugstr_w(value
));
564 entry
= heap_alloc(sizeof(*entry
));
565 entry
->header
= header
;
566 entry
->value
= value
;
567 list_add_head(&This
->respheaders
, &entry
->entry
);
570 static HRESULT WINAPI
BSCHttpNegotiate_OnResponse(IHttpNegotiate
*iface
, DWORD code
,
571 LPCWSTR resp_headers
, LPCWSTR req_headers
, LPWSTR
*add_reqheaders
)
573 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
575 TRACE("%p, %ld, %s, %s, %p.\n", iface
, code
, debugstr_w(resp_headers
),
576 debugstr_w(req_headers
), add_reqheaders
);
578 This
->request
->status
= code
;
579 /* store headers and status text */
580 free_response_headers(This
->request
);
581 SysFreeString(This
->request
->status_text
);
582 This
->request
->status_text
= NULL
;
585 const WCHAR
*ptr
, *line
, *status_text
;
587 ptr
= line
= resp_headers
;
589 /* skip HTTP-Version */
590 ptr
= wcschr(ptr
, ' ');
593 /* skip Status-Code */
594 ptr
= wcschr(++ptr
, ' ');
598 /* now it supposed to end with CRLF */
601 if (*ptr
== '\r' && *(ptr
+1) == '\n')
604 This
->request
->status_text
= SysAllocStringLen(status_text
, ptr
-status_text
);
605 TRACE("status text %s\n", debugstr_w(This
->request
->status_text
));
613 /* store as unparsed string for now */
614 This
->request
->raw_respheaders
= SysAllocString(line
);
620 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl
= {
621 BSCHttpNegotiate_QueryInterface
,
622 BSCHttpNegotiate_AddRef
,
623 BSCHttpNegotiate_Release
,
624 BSCHttpNegotiate_BeginningTransaction
,
625 BSCHttpNegotiate_OnResponse
628 static HRESULT WINAPI
Authenticate_QueryInterface(IAuthenticate
*iface
,
629 REFIID riid
, void **ppv
)
631 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
632 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
635 static ULONG WINAPI
Authenticate_AddRef(IAuthenticate
*iface
)
637 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
638 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
641 static ULONG WINAPI
Authenticate_Release(IAuthenticate
*iface
)
643 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
644 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
647 static HRESULT WINAPI
Authenticate_Authenticate(IAuthenticate
*iface
,
648 HWND
*hwnd
, LPWSTR
*username
, LPWSTR
*password
)
650 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
651 httprequest
*request
= This
->request
;
653 TRACE("(%p)->(%p %p %p)\n", This
, hwnd
, username
, password
);
655 if (request
->user
&& *request
->user
)
657 if (hwnd
) *hwnd
= NULL
;
658 *username
= CoTaskMemAlloc(SysStringByteLen(request
->user
)+sizeof(WCHAR
));
659 *password
= CoTaskMemAlloc(SysStringByteLen(request
->password
)+sizeof(WCHAR
));
660 if (!*username
|| !*password
)
662 CoTaskMemFree(*username
);
663 CoTaskMemFree(*password
);
664 return E_OUTOFMEMORY
;
667 memcpy(*username
, request
->user
, SysStringByteLen(request
->user
)+sizeof(WCHAR
));
668 memcpy(*password
, request
->password
, SysStringByteLen(request
->password
)+sizeof(WCHAR
));
674 static const IAuthenticateVtbl AuthenticateVtbl
= {
675 Authenticate_QueryInterface
,
677 Authenticate_Release
,
678 Authenticate_Authenticate
681 static HRESULT
BindStatusCallback_create(httprequest
* This
, BindStatusCallback
**obj
, const VARIANT
*body
)
683 BindStatusCallback
*bsc
;
688 hr
= CreateBindCtx(0, &pbc
);
689 if (hr
!= S_OK
) return hr
;
691 bsc
= heap_alloc(sizeof(*bsc
));
694 IBindCtx_Release(pbc
);
695 return E_OUTOFMEMORY
;
698 bsc
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
699 bsc
->IHttpNegotiate_iface
.lpVtbl
= &BSCHttpNegotiateVtbl
;
700 bsc
->IAuthenticate_iface
.lpVtbl
= &AuthenticateVtbl
;
707 TRACE("(%p)->(%p)\n", This
, bsc
);
709 This
->use_utf8_content
= FALSE
;
711 if (This
->verb
!= BINDVERB_GET
)
713 void *send_data
, *ptr
;
714 SAFEARRAY
*sa
= NULL
;
716 if (V_VT(body
) == (VT_VARIANT
|VT_BYREF
))
717 body
= V_VARIANTREF(body
);
723 int len
= SysStringLen(V_BSTR(body
));
724 const WCHAR
*str
= V_BSTR(body
);
727 for (i
= 0; i
< len
; i
++)
736 size
= WideCharToMultiByte(cp
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
737 if (!(ptr
= heap_alloc(size
)))
740 return E_OUTOFMEMORY
;
742 WideCharToMultiByte(cp
, 0, str
, len
, ptr
, size
, NULL
, NULL
);
743 if (cp
== CP_UTF8
) This
->use_utf8_content
= TRUE
;
746 case VT_ARRAY
|VT_UI1
:
749 if ((hr
= SafeArrayAccessData(sa
, &ptr
)) != S_OK
)
754 if ((hr
= SafeArrayGetUBound(sa
, 1, &size
)) != S_OK
)
756 SafeArrayUnaccessData(sa
);
764 FIXME("unsupported body data type %d\n", V_VT(body
));
776 bsc
->body
= GlobalAlloc(GMEM_FIXED
, size
);
779 if (V_VT(body
) == VT_BSTR
)
781 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
782 SafeArrayUnaccessData(sa
);
785 return E_OUTOFMEMORY
;
788 send_data
= GlobalLock(bsc
->body
);
789 memcpy(send_data
, ptr
, size
);
790 GlobalUnlock(bsc
->body
);
793 if (V_VT(body
) == VT_BSTR
)
795 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
796 SafeArrayUnaccessData(sa
);
799 hr
= RegisterBindStatusCallback(pbc
, &bsc
->IBindStatusCallback_iface
, NULL
, 0);
804 hr
= CreateURLMonikerEx2(NULL
, This
->uri
, &moniker
, URL_MK_UNIFORM
);
809 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
810 IMoniker_Release(moniker
);
811 if (stream
) IStream_Release(stream
);
813 IBindCtx_Release(pbc
);
818 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
826 static HRESULT
verify_uri(httprequest
*This
, IUri
*uri
)
828 DWORD scheme
, base_scheme
;
829 BSTR host
, base_host
;
832 if(!(This
->safeopt
& INTERFACESAFE_FOR_UNTRUSTED_DATA
))
836 return E_ACCESSDENIED
;
838 hr
= IUri_GetScheme(uri
, &scheme
);
842 hr
= IUri_GetScheme(This
->base_uri
, &base_scheme
);
846 if(scheme
!= base_scheme
) {
847 WARN("Schemes don't match\n");
848 return E_ACCESSDENIED
;
851 if(scheme
== INTERNET_SCHEME_UNKNOWN
) {
852 FIXME("Unknown scheme\n");
853 return E_ACCESSDENIED
;
856 hr
= IUri_GetHost(uri
, &host
);
860 hr
= IUri_GetHost(This
->base_uri
, &base_host
);
862 if(wcsicmp(host
, base_host
)) {
863 WARN("Hosts don't match\n");
866 SysFreeString(base_host
);
873 static HRESULT
httprequest_open(httprequest
*This
, BSTR method
, BSTR url
,
874 VARIANT async
, VARIANT user
, VARIANT password
)
876 static const WCHAR MethodHeadW
[] = {'H','E','A','D',0};
877 static const WCHAR MethodGetW
[] = {'G','E','T',0};
878 static const WCHAR MethodPutW
[] = {'P','U','T',0};
879 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
880 static const WCHAR MethodDeleteW
[] = {'D','E','L','E','T','E',0};
881 static const WCHAR MethodPropFindW
[] = {'P','R','O','P','F','I','N','D',0};
882 VARIANT str
, is_async
;
886 if (!method
|| !url
) return E_INVALIDARG
;
888 /* free previously set data */
890 IUri_Release(This
->uri
);
894 SysFreeString(This
->user
);
895 SysFreeString(This
->password
);
896 This
->user
= This
->password
= NULL
;
897 free_request_headers(This
);
899 if (!wcsicmp(method
, MethodGetW
))
901 This
->verb
= BINDVERB_GET
;
903 else if (!wcsicmp(method
, MethodPutW
))
905 This
->verb
= BINDVERB_PUT
;
907 else if (!wcsicmp(method
, MethodPostW
))
909 This
->verb
= BINDVERB_POST
;
911 else if (!wcsicmp(method
, MethodDeleteW
) ||
912 !wcsicmp(method
, MethodHeadW
) ||
913 !wcsicmp(method
, MethodPropFindW
))
915 This
->verb
= BINDVERB_CUSTOM
;
916 SysReAllocString(&This
->custom
, method
);
920 FIXME("unsupported request type %s\n", debugstr_w(method
));
926 hr
= CoInternetCombineUrlEx(This
->base_uri
, url
, 0, &uri
, 0);
928 hr
= CreateUri(url
, 0, 0, &uri
);
930 WARN("Could not create IUri object, hr %#lx.\n", hr
);
934 hr
= verify_uri(This
, uri
);
941 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
943 This
->user
= V_BSTR(&str
);
946 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
948 This
->password
= V_BSTR(&str
);
950 /* add authentication info */
951 if (This
->user
&& *This
->user
)
953 IUriBuilder
*builder
;
955 hr
= CreateIUriBuilder(uri
, 0, 0, &builder
);
960 IUriBuilder_SetUserName(builder
, This
->user
);
961 IUriBuilder_SetPassword(builder
, This
->password
);
962 hr
= IUriBuilder_CreateUri(builder
, -1, 0, 0, &full_uri
);
969 WARN("failed to create modified uri, hr %#lx.\n", hr
);
970 IUriBuilder_Release(builder
);
973 WARN("IUriBuilder creation failed, hr %#lx.\n", hr
);
978 VariantInit(&is_async
);
979 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
980 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
);
982 httprequest_setreadystate(This
, READYSTATE_LOADING
);
987 static HRESULT
httprequest_setRequestHeader(httprequest
*This
, BSTR header
, BSTR value
)
989 struct httpheader
*entry
;
991 if (!header
|| !*header
) return E_INVALIDARG
;
992 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
993 if (!value
) return E_INVALIDARG
;
995 /* replace existing header value if already added */
996 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct httpheader
, entry
)
998 if (wcscmp(entry
->header
, header
) == 0)
1000 LONG length
= SysStringLen(entry
->value
);
1003 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
1006 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
1012 entry
= heap_alloc(sizeof(*entry
));
1013 if (!entry
) return E_OUTOFMEMORY
;
1016 entry
->header
= SysAllocString(header
);
1017 entry
->value
= SysAllocString(value
);
1019 /* header length including null terminator */
1020 This
->reqheader_size
+= SysStringLen(entry
->header
) + ARRAY_SIZE(colspaceW
) +
1021 SysStringLen(entry
->value
) + ARRAY_SIZE(crlfW
) - 1;
1023 list_add_head(&This
->reqheaders
, &entry
->entry
);
1028 static HRESULT
httprequest_getResponseHeader(httprequest
*This
, BSTR header
, BSTR
*value
)
1030 struct httpheader
*entry
;
1032 if (!header
) return E_INVALIDARG
;
1033 if (!value
) return E_POINTER
;
1035 if (This
->raw_respheaders
&& list_empty(&This
->respheaders
))
1039 ptr
= line
= This
->raw_respheaders
;
1042 if (*ptr
== '\r' && *(ptr
+1) == '\n')
1044 add_response_header(This
, line
, ptr
-line
);
1045 ptr
++; line
= ++ptr
;
1052 LIST_FOR_EACH_ENTRY(entry
, &This
->respheaders
, struct httpheader
, entry
)
1054 if (!wcsicmp(entry
->header
, header
))
1056 *value
= SysAllocString(entry
->value
);
1057 TRACE("header value %s\n", debugstr_w(*value
));
1065 static HRESULT
httprequest_getAllResponseHeaders(httprequest
*This
, BSTR
*respheaders
)
1067 if (!respheaders
) return E_POINTER
;
1069 *respheaders
= SysAllocString(This
->raw_respheaders
);
1074 static HRESULT
httprequest_send(httprequest
*This
, VARIANT body
)
1076 BindStatusCallback
*bsc
= NULL
;
1079 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
1081 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
1083 /* success path to detach it is OnStopBinding call */
1084 BindStatusCallback_Detach(bsc
);
1089 static HRESULT
httprequest_abort(httprequest
*This
)
1091 BindStatusCallback_Detach(This
->bsc
);
1093 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
1098 static HRESULT
httprequest_get_status(httprequest
*This
, LONG
*status
)
1100 if (!status
) return E_POINTER
;
1102 *status
= This
->status
;
1104 return This
->state
== READYSTATE_COMPLETE
? S_OK
: E_FAIL
;
1107 static HRESULT
httprequest_get_statusText(httprequest
*This
, BSTR
*status
)
1109 if (!status
) return E_POINTER
;
1110 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1112 *status
= SysAllocString(This
->status_text
);
1117 enum response_encoding
1119 RESPONSE_ENCODING_NONE
,
1120 RESPONSE_ENCODING_UCS4BE
,
1121 RESPONSE_ENCODING_UCS4LE
,
1122 RESPONSE_ENCODING_UCS4_2143
,
1123 RESPONSE_ENCODING_UCS4_3412
,
1124 RESPONSE_ENCODING_EBCDIC
,
1125 RESPONSE_ENCODING_UTF8
,
1126 RESPONSE_ENCODING_UTF16LE
,
1127 RESPONSE_ENCODING_UTF16BE
,
1130 static unsigned int detect_response_encoding(const BYTE
*in
, unsigned int len
)
1134 if (in
[0] == 0 && in
[1] == 0 && in
[2] == 0 && in
[3] == 0x3c)
1135 return RESPONSE_ENCODING_UCS4BE
;
1136 if (in
[0] == 0x3c && in
[1] == 0 && in
[2] == 0 && in
[3] == 0)
1137 return RESPONSE_ENCODING_UCS4LE
;
1138 if (in
[0] == 0 && in
[1] == 0 && in
[2] == 0x3c && in
[3] == 0)
1139 return RESPONSE_ENCODING_UCS4_2143
;
1140 if (in
[0] == 0 && in
[1] == 0x3c && in
[2] == 0 && in
[3] == 0)
1141 return RESPONSE_ENCODING_UCS4_3412
;
1142 if (in
[0] == 0x4c && in
[1] == 0x6f && in
[2] == 0xa7 && in
[3] == 0x94)
1143 return RESPONSE_ENCODING_EBCDIC
;
1144 if (in
[0] == 0x3c && in
[1] == 0x3f && in
[2] == 0x78 && in
[3] == 0x6d)
1145 return RESPONSE_ENCODING_UTF8
;
1146 if (in
[0] == 0x3c && in
[1] == 0 && in
[2] == 0x3f && in
[3] == 0)
1147 return RESPONSE_ENCODING_UTF16LE
;
1148 if (in
[0] == 0 && in
[1] == 0x3c && in
[2] == 0 && in
[3] == 0x3f)
1149 return RESPONSE_ENCODING_UTF16BE
;
1154 if (in
[0] == 0xef && in
[1] == 0xbb && in
[2] == 0xbf)
1155 return RESPONSE_ENCODING_UTF8
;
1160 if (in
[0] == 0xfe && in
[1] == 0xff)
1161 return RESPONSE_ENCODING_UTF16BE
;
1162 if (in
[0] == 0xff && in
[1] == 0xfe)
1163 return RESPONSE_ENCODING_UTF16LE
;
1166 return RESPONSE_ENCODING_NONE
;
1169 static HRESULT
httprequest_get_responseText(httprequest
*This
, BSTR
*body
)
1174 if (!body
) return E_POINTER
;
1175 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1177 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1180 const char *ptr
= GlobalLock(hglobal
);
1181 DWORD size
= GlobalSize(hglobal
);
1182 unsigned int encoding
= RESPONSE_ENCODING_NONE
;
1184 /* try to determine data encoding */
1187 encoding
= detect_response_encoding((const BYTE
*)ptr
, 4);
1188 TRACE("detected encoding: %u.\n", encoding
);
1190 if (encoding
!= RESPONSE_ENCODING_UTF8
&&
1191 encoding
!= RESPONSE_ENCODING_UTF16LE
&&
1192 encoding
!= RESPONSE_ENCODING_NONE
)
1194 FIXME("unsupported response encoding: %u.\n", encoding
);
1195 GlobalUnlock(hglobal
);
1200 /* without BOM assume UTF-8 */
1201 if (encoding
== RESPONSE_ENCODING_UTF8
|| encoding
== RESPONSE_ENCODING_NONE
)
1203 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, ptr
, size
, NULL
, 0);
1205 *body
= SysAllocStringLen(NULL
, length
);
1207 MultiByteToWideChar( CP_UTF8
, 0, ptr
, size
, *body
, length
);
1210 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
1212 if (!*body
) hr
= E_OUTOFMEMORY
;
1213 GlobalUnlock(hglobal
);
1219 static HRESULT
httprequest_get_responseXML(httprequest
*This
, IDispatch
**body
)
1221 IXMLDOMDocument3
*doc
;
1225 if (!body
) return E_INVALIDARG
;
1226 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1228 hr
= dom_document_create(MSXML_DEFAULT
, (void**)&doc
);
1229 if (hr
!= S_OK
) return hr
;
1231 hr
= httprequest_get_responseText(This
, &str
);
1236 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
1240 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
1241 IXMLDOMDocument3_Release(doc
);
1246 static HRESULT
httprequest_get_responseBody(httprequest
*This
, VARIANT
*body
)
1251 if (!body
) return E_INVALIDARG
;
1252 V_VT(body
) = VT_EMPTY
;
1254 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1256 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1259 void *ptr
= GlobalLock(hglobal
);
1260 DWORD size
= GlobalSize(hglobal
);
1262 SAFEARRAYBOUND bound
;
1266 bound
.cElements
= size
;
1267 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
1273 V_VT(body
) = VT_ARRAY
| VT_UI1
;
1274 V_ARRAY(body
) = array
;
1276 hr
= SafeArrayAccessData(array
, &dest
);
1279 memcpy(dest
, ptr
, size
);
1280 SafeArrayUnaccessData(array
);
1290 GlobalUnlock(hglobal
);
1296 static HRESULT
httprequest_get_responseStream(httprequest
*This
, VARIANT
*body
)
1302 if (!body
) return E_INVALIDARG
;
1303 V_VT(body
) = VT_EMPTY
;
1305 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1307 hr
= IStream_Clone(This
->bsc
->stream
, &stream
);
1310 IStream_Seek(stream
, move
, STREAM_SEEK_SET
, NULL
);
1312 V_VT(body
) = VT_UNKNOWN
;
1313 V_UNKNOWN(body
) = (IUnknown
*)stream
;
1318 static HRESULT
httprequest_get_readyState(httprequest
*This
, LONG
*state
)
1320 if (!state
) return E_POINTER
;
1322 *state
= This
->state
;
1326 static HRESULT
httprequest_put_onreadystatechange(httprequest
*This
, IDispatch
*sink
)
1328 if (This
->sink
) IDispatch_Release(This
->sink
);
1329 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1334 static void httprequest_release(httprequest
*This
)
1337 IUnknown_Release( This
->site
);
1339 IUri_Release(This
->uri
);
1341 IUri_Release(This
->base_uri
);
1343 SysFreeString(This
->custom
);
1344 SysFreeString(This
->user
);
1345 SysFreeString(This
->password
);
1347 /* cleanup headers lists */
1348 free_request_headers(This
);
1349 free_response_headers(This
);
1350 SysFreeString(This
->status_text
);
1352 /* detach callback object */
1353 BindStatusCallback_Detach(This
->bsc
);
1355 if (This
->sink
) IDispatch_Release(This
->sink
);
1358 static HRESULT WINAPI
XMLHTTPRequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
1360 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1361 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1363 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1364 IsEqualGUID( riid
, &IID_IDispatch
) ||
1365 IsEqualGUID( riid
, &IID_IUnknown
) )
1369 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
1371 *ppvObject
= &This
->IObjectWithSite_iface
;
1373 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
1375 *ppvObject
= &This
->IObjectSafety_iface
;
1377 else if (IsEqualGUID(&IID_ISupportErrorInfo
, riid
))
1379 *ppvObject
= &This
->ISupportErrorInfo_iface
;
1383 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1385 return E_NOINTERFACE
;
1388 IUnknown_AddRef((IUnknown
*)*ppvObject
);
1393 static ULONG WINAPI
XMLHTTPRequest_AddRef(IXMLHTTPRequest
*iface
)
1395 httprequest
*request
= impl_from_IXMLHTTPRequest(iface
);
1396 ULONG ref
= InterlockedIncrement(&request
->ref
);
1397 TRACE("%p, refcount %lu.\n", iface
, ref
);
1401 static ULONG WINAPI
XMLHTTPRequest_Release(IXMLHTTPRequest
*iface
)
1403 httprequest
*request
= impl_from_IXMLHTTPRequest(iface
);
1404 ULONG ref
= InterlockedDecrement(&request
->ref
);
1406 TRACE("%p, refcount %lu.\n", iface
, ref
);
1410 httprequest_release(request
);
1417 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1419 TRACE("%p, %p.\n", iface
, pctinfo
);
1426 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
1427 LCID lcid
, ITypeInfo
**ppTInfo
)
1429 TRACE("%p, %u, %lx,%p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1431 return get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
1434 static HRESULT WINAPI
XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
1435 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1437 ITypeInfo
*typeinfo
;
1440 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
,
1443 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1444 return E_INVALIDARG
;
1446 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1449 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1450 ITypeInfo_Release(typeinfo
);
1456 static HRESULT WINAPI
XMLHTTPRequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1457 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1458 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1460 ITypeInfo
*typeinfo
;
1463 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1464 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1466 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1469 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1470 ITypeInfo_Release(typeinfo
);
1476 static HRESULT WINAPI
XMLHTTPRequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1477 VARIANT async
, VARIANT user
, VARIANT password
)
1479 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1480 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1481 debugstr_variant(&async
));
1482 return httprequest_open(This
, method
, url
, async
, user
, password
);
1485 static HRESULT WINAPI
XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1487 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1488 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1489 return httprequest_setRequestHeader(This
, header
, value
);
1492 static HRESULT WINAPI
XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1494 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1495 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1496 return httprequest_getResponseHeader(This
, header
, value
);
1499 static HRESULT WINAPI
XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1501 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1502 TRACE("(%p)->(%p)\n", This
, respheaders
);
1503 return httprequest_getAllResponseHeaders(This
, respheaders
);
1506 static HRESULT WINAPI
XMLHTTPRequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
1508 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1509 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1510 return httprequest_send(This
, body
);
1513 static HRESULT WINAPI
XMLHTTPRequest_abort(IXMLHTTPRequest
*iface
)
1515 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1516 TRACE("(%p)\n", This
);
1517 return httprequest_abort(This
);
1520 static HRESULT WINAPI
XMLHTTPRequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
1522 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1523 TRACE("(%p)->(%p)\n", This
, status
);
1524 return httprequest_get_status(This
, status
);
1527 static HRESULT WINAPI
XMLHTTPRequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*status
)
1529 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1530 TRACE("(%p)->(%p)\n", This
, status
);
1531 return httprequest_get_statusText(This
, status
);
1534 static HRESULT WINAPI
XMLHTTPRequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
1536 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1537 TRACE("(%p)->(%p)\n", This
, body
);
1538 return httprequest_get_responseXML(This
, body
);
1541 static HRESULT WINAPI
XMLHTTPRequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
1543 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1544 TRACE("(%p)->(%p)\n", This
, body
);
1545 return httprequest_get_responseText(This
, body
);
1548 static HRESULT WINAPI
XMLHTTPRequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1550 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1551 TRACE("(%p)->(%p)\n", This
, body
);
1552 return httprequest_get_responseBody(This
, body
);
1555 static HRESULT WINAPI
XMLHTTPRequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1557 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1558 TRACE("(%p)->(%p)\n", This
, body
);
1559 return httprequest_get_responseStream(This
, body
);
1562 static HRESULT WINAPI
XMLHTTPRequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
1564 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1565 TRACE("(%p)->(%p)\n", This
, state
);
1566 return httprequest_get_readyState(This
, state
);
1569 static HRESULT WINAPI
XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
1571 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1572 TRACE("(%p)->(%p)\n", This
, sink
);
1573 return httprequest_put_onreadystatechange(This
, sink
);
1576 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl
=
1578 XMLHTTPRequest_QueryInterface
,
1579 XMLHTTPRequest_AddRef
,
1580 XMLHTTPRequest_Release
,
1581 XMLHTTPRequest_GetTypeInfoCount
,
1582 XMLHTTPRequest_GetTypeInfo
,
1583 XMLHTTPRequest_GetIDsOfNames
,
1584 XMLHTTPRequest_Invoke
,
1585 XMLHTTPRequest_open
,
1586 XMLHTTPRequest_setRequestHeader
,
1587 XMLHTTPRequest_getResponseHeader
,
1588 XMLHTTPRequest_getAllResponseHeaders
,
1589 XMLHTTPRequest_send
,
1590 XMLHTTPRequest_abort
,
1591 XMLHTTPRequest_get_status
,
1592 XMLHTTPRequest_get_statusText
,
1593 XMLHTTPRequest_get_responseXML
,
1594 XMLHTTPRequest_get_responseText
,
1595 XMLHTTPRequest_get_responseBody
,
1596 XMLHTTPRequest_get_responseStream
,
1597 XMLHTTPRequest_get_readyState
,
1598 XMLHTTPRequest_put_onreadystatechange
1601 /* IObjectWithSite */
1602 static HRESULT WINAPI
1603 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1605 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1606 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppvObject
);
1609 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1611 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1612 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1615 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1617 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1618 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1621 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1623 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1625 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1630 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1633 IUri
*get_base_uri(IUnknown
*site
)
1635 IServiceProvider
*provider
;
1636 IHTMLDocument2
*doc
;
1641 hr
= IUnknown_QueryInterface(site
, &IID_IServiceProvider
, (void**)&provider
);
1645 hr
= IServiceProvider_QueryService(provider
, &SID_SContainerDispatch
, &IID_IHTMLDocument2
, (void**)&doc
);
1647 hr
= IServiceProvider_QueryService(provider
, &SID_SInternetHostSecurityManager
, &IID_IHTMLDocument2
, (void**)&doc
);
1648 IServiceProvider_Release(provider
);
1652 hr
= IHTMLDocument2_get_URL(doc
, &url
);
1653 IHTMLDocument2_Release(doc
);
1654 if(FAILED(hr
) || !url
|| !*url
)
1657 TRACE("host url %s\n", debugstr_w(url
));
1659 hr
= CreateUri(url
, 0, 0, &uri
);
1667 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1669 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1671 TRACE("(%p)->(%p)\n", This
, punk
);
1674 IUnknown_Release( This
->site
);
1676 IUri_Release(This
->base_uri
);
1682 IUnknown_AddRef( punk
);
1683 This
->base_uri
= get_base_uri(This
->site
);
1689 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1691 httprequest_ObjectWithSite_QueryInterface
,
1692 httprequest_ObjectWithSite_AddRef
,
1693 httprequest_ObjectWithSite_Release
,
1694 httprequest_ObjectWithSite_SetSite
,
1695 httprequest_ObjectWithSite_GetSite
1699 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1701 httprequest
*This
= impl_from_IObjectSafety(iface
);
1702 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppv
);
1705 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1707 httprequest
*This
= impl_from_IObjectSafety(iface
);
1708 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1711 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1713 httprequest
*This
= impl_from_IObjectSafety(iface
);
1714 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1717 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1718 DWORD
*supported
, DWORD
*enabled
)
1720 httprequest
*This
= impl_from_IObjectSafety(iface
);
1722 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1724 if(!supported
|| !enabled
) return E_POINTER
;
1726 *supported
= safety_supported_options
;
1727 *enabled
= This
->safeopt
;
1732 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1733 DWORD mask
, DWORD enabled
)
1735 httprequest
*request
= impl_from_IObjectSafety(iface
);
1737 TRACE("%p, %s, %lx, %lx.\n", iface
, debugstr_guid(riid
), mask
, enabled
);
1739 if ((mask
& ~safety_supported_options
))
1742 request
->safeopt
= (request
->safeopt
& ~mask
) | (mask
& enabled
);
1747 static const IObjectSafetyVtbl ObjectSafetyVtbl
= {
1748 httprequest_Safety_QueryInterface
,
1749 httprequest_Safety_AddRef
,
1750 httprequest_Safety_Release
,
1751 httprequest_Safety_GetInterfaceSafetyOptions
,
1752 httprequest_Safety_SetInterfaceSafetyOptions
1755 static HRESULT WINAPI
SupportErrorInfo_QueryInterface(ISupportErrorInfo
*iface
, REFIID riid
, void **obj
)
1757 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1758 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, obj
);
1761 static ULONG WINAPI
SupportErrorInfo_AddRef(ISupportErrorInfo
*iface
)
1763 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1764 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1767 static ULONG WINAPI
SupportErrorInfo_Release(ISupportErrorInfo
*iface
)
1769 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1770 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1773 static HRESULT WINAPI
SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo
*iface
, REFIID riid
)
1775 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1777 FIXME("(%p)->(%s)\n", This
, debugstr_guid(riid
));
1782 static const ISupportErrorInfoVtbl SupportErrorInfoVtbl
=
1784 SupportErrorInfo_QueryInterface
,
1785 SupportErrorInfo_AddRef
,
1786 SupportErrorInfo_Release
,
1787 SupportErrorInfo_InterfaceSupportsErrorInfo
,
1790 /* IServerXMLHTTPRequest */
1791 static HRESULT WINAPI
ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest
*iface
, REFIID riid
, void **obj
)
1793 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1795 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1797 if ( IsEqualGUID( riid
, &IID_IServerXMLHTTPRequest
) ||
1798 IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1799 IsEqualGUID( riid
, &IID_IDispatch
) ||
1800 IsEqualGUID( riid
, &IID_IUnknown
) )
1804 else if ( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
1806 *obj
= &This
->req
.ISupportErrorInfo_iface
;
1810 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1812 return E_NOINTERFACE
;
1815 IUnknown_AddRef( (IUnknown
*)*obj
);
1820 static ULONG WINAPI
ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest
*iface
)
1822 serverhttp
*request
= impl_from_IServerXMLHTTPRequest(iface
);
1823 ULONG ref
= InterlockedIncrement(&request
->req
.ref
);
1824 TRACE("%p, refcount %lu.\n", iface
, ref
);
1828 static ULONG WINAPI
ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest
*iface
)
1830 serverhttp
*request
= impl_from_IServerXMLHTTPRequest(iface
);
1831 ULONG ref
= InterlockedDecrement(&request
->req
.ref
);
1833 TRACE("%p, refcount %lu.\n", iface
, ref
);
1837 httprequest_release(&request
->req
);
1844 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1846 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1848 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1854 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest
*iface
, UINT iTInfo
,
1855 LCID lcid
, ITypeInfo
**ppTInfo
)
1857 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1859 return get_typeinfo(IServerXMLHTTPRequest_tid
, ppTInfo
);
1862 static HRESULT WINAPI
ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest
*iface
, REFIID riid
,
1863 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1865 ITypeInfo
*typeinfo
;
1868 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
,
1871 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1872 return E_INVALIDARG
;
1874 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1877 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1878 ITypeInfo_Release(typeinfo
);
1884 static HRESULT WINAPI
ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1885 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1886 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1888 ITypeInfo
*typeinfo
;
1891 TRACE("%p, %ld, %s %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1892 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1894 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1897 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1898 ITypeInfo_Release(typeinfo
);
1904 static HRESULT WINAPI
ServerXMLHTTPRequest_open(IServerXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1905 VARIANT async
, VARIANT user
, VARIANT password
)
1907 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1908 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1909 debugstr_variant(&async
));
1910 return httprequest_open(&This
->req
, method
, url
, async
, user
, password
);
1913 static HRESULT WINAPI
ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1915 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1916 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1917 return httprequest_setRequestHeader(&This
->req
, header
, value
);
1920 static HRESULT WINAPI
ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1922 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1923 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1924 return httprequest_getResponseHeader(&This
->req
, header
, value
);
1927 static HRESULT WINAPI
ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1929 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1930 TRACE("(%p)->(%p)\n", This
, respheaders
);
1931 return httprequest_getAllResponseHeaders(&This
->req
, respheaders
);
1934 static HRESULT WINAPI
ServerXMLHTTPRequest_send(IServerXMLHTTPRequest
*iface
, VARIANT body
)
1936 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1937 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1938 return httprequest_send(&This
->req
, body
);
1941 static HRESULT WINAPI
ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest
*iface
)
1943 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1944 TRACE("(%p)\n", This
);
1945 return httprequest_abort(&This
->req
);
1948 static HRESULT WINAPI
ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest
*iface
, LONG
*status
)
1950 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1951 TRACE("(%p)->(%p)\n", This
, status
);
1952 return httprequest_get_status(&This
->req
, status
);
1955 static HRESULT WINAPI
ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest
*iface
, BSTR
*status
)
1957 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1958 TRACE("(%p)->(%p)\n", This
, status
);
1959 return httprequest_get_statusText(&This
->req
, status
);
1962 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest
*iface
, IDispatch
**body
)
1964 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1965 TRACE("(%p)->(%p)\n", This
, body
);
1966 return httprequest_get_responseXML(&This
->req
, body
);
1969 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest
*iface
, BSTR
*body
)
1971 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1972 TRACE("(%p)->(%p)\n", This
, body
);
1973 return httprequest_get_responseText(&This
->req
, body
);
1976 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1978 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1979 TRACE("(%p)->(%p)\n", This
, body
);
1980 return httprequest_get_responseBody(&This
->req
, body
);
1983 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1985 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1986 TRACE("(%p)->(%p)\n", This
, body
);
1987 return httprequest_get_responseStream(&This
->req
, body
);
1990 static HRESULT WINAPI
ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest
*iface
, LONG
*state
)
1992 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1993 TRACE("(%p)->(%p)\n", This
, state
);
1994 return httprequest_get_readyState(&This
->req
, state
);
1997 static HRESULT WINAPI
ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest
*iface
, IDispatch
*sink
)
1999 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2000 TRACE("(%p)->(%p)\n", This
, sink
);
2001 return httprequest_put_onreadystatechange(&This
->req
, sink
);
2004 static HRESULT WINAPI
ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest
*iface
, LONG resolveTimeout
, LONG connectTimeout
,
2005 LONG sendTimeout
, LONG receiveTimeout
)
2007 FIXME("%p, %ld, %ld, %ld, %ld: stub\n", iface
, resolveTimeout
, connectTimeout
, sendTimeout
, receiveTimeout
);
2011 static HRESULT WINAPI
ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest
*iface
, VARIANT timeout
, VARIANT_BOOL
*isSuccessful
)
2013 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2014 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_variant(&timeout
), isSuccessful
);
2018 static HRESULT WINAPI
ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT
*value
)
2020 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2021 FIXME("(%p)->(%d %p): stub\n", This
, option
, value
);
2025 static HRESULT WINAPI
ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT value
)
2027 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2028 FIXME("(%p)->(%d %s): stub\n", This
, option
, debugstr_variant(&value
));
2032 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl
=
2034 ServerXMLHTTPRequest_QueryInterface
,
2035 ServerXMLHTTPRequest_AddRef
,
2036 ServerXMLHTTPRequest_Release
,
2037 ServerXMLHTTPRequest_GetTypeInfoCount
,
2038 ServerXMLHTTPRequest_GetTypeInfo
,
2039 ServerXMLHTTPRequest_GetIDsOfNames
,
2040 ServerXMLHTTPRequest_Invoke
,
2041 ServerXMLHTTPRequest_open
,
2042 ServerXMLHTTPRequest_setRequestHeader
,
2043 ServerXMLHTTPRequest_getResponseHeader
,
2044 ServerXMLHTTPRequest_getAllResponseHeaders
,
2045 ServerXMLHTTPRequest_send
,
2046 ServerXMLHTTPRequest_abort
,
2047 ServerXMLHTTPRequest_get_status
,
2048 ServerXMLHTTPRequest_get_statusText
,
2049 ServerXMLHTTPRequest_get_responseXML
,
2050 ServerXMLHTTPRequest_get_responseText
,
2051 ServerXMLHTTPRequest_get_responseBody
,
2052 ServerXMLHTTPRequest_get_responseStream
,
2053 ServerXMLHTTPRequest_get_readyState
,
2054 ServerXMLHTTPRequest_put_onreadystatechange
,
2055 ServerXMLHTTPRequest_setTimeouts
,
2056 ServerXMLHTTPRequest_waitForResponse
,
2057 ServerXMLHTTPRequest_getOption
,
2058 ServerXMLHTTPRequest_setOption
2061 static void init_httprequest(httprequest
*req
)
2063 req
->IXMLHTTPRequest_iface
.lpVtbl
= &XMLHTTPRequestVtbl
;
2064 req
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
2065 req
->IObjectSafety_iface
.lpVtbl
= &ObjectSafetyVtbl
;
2066 req
->ISupportErrorInfo_iface
.lpVtbl
= &SupportErrorInfoVtbl
;
2072 req
->uri
= req
->base_uri
= NULL
;
2073 req
->user
= req
->password
= NULL
;
2075 req
->state
= READYSTATE_UNINITIALIZED
;
2080 req
->status_text
= NULL
;
2081 req
->reqheader_size
= 0;
2082 req
->raw_respheaders
= NULL
;
2083 req
->use_utf8_content
= FALSE
;
2085 list_init(&req
->reqheaders
);
2086 list_init(&req
->respheaders
);
2092 HRESULT
XMLHTTPRequest_create(void **obj
)
2096 TRACE("(%p)\n", obj
);
2098 req
= heap_alloc( sizeof (*req
) );
2100 return E_OUTOFMEMORY
;
2102 init_httprequest(req
);
2103 *obj
= &req
->IXMLHTTPRequest_iface
;
2105 TRACE("returning iface %p\n", *obj
);
2110 HRESULT
ServerXMLHTTP_create(void **obj
)
2114 TRACE("(%p)\n", obj
);
2116 req
= heap_alloc( sizeof (*req
) );
2118 return E_OUTOFMEMORY
;
2120 init_httprequest(&req
->req
);
2121 req
->IServerXMLHTTPRequest_iface
.lpVtbl
= &ServerXMLHTTPRequestVtbl
;
2123 *obj
= &req
->IServerXMLHTTPRequest_iface
;
2125 TRACE("returning iface %p\n", *obj
);