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
39 #include "msxml_dispex.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
45 static const WCHAR colspaceW
[] = {':',' ',0};
46 static const WCHAR crlfW
[] = {'\r','\n',0};
47 static const DWORD safety_supported_options
=
48 INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
49 INTERFACESAFE_FOR_UNTRUSTED_DATA
|
50 INTERFACE_USES_SECURITY_MANAGER
;
52 typedef struct BindStatusCallback BindStatusCallback
;
63 IXMLHTTPRequest IXMLHTTPRequest_iface
;
64 IObjectWithSite IObjectWithSite_iface
;
65 IObjectSafety IObjectSafety_iface
;
66 ISupportErrorInfo ISupportErrorInfo_iface
;
78 struct list reqheaders
;
79 /* cached resulting custom request headers string length in WCHARs */
81 /* use UTF-8 content type */
82 BOOL use_utf8_content
;
84 /* response headers */
85 struct list respheaders
;
93 BindStatusCallback
*bsc
;
107 IServerXMLHTTPRequest IServerXMLHTTPRequest_iface
;
110 static inline httprequest
*impl_from_IXMLHTTPRequest( IXMLHTTPRequest
*iface
)
112 return CONTAINING_RECORD(iface
, httprequest
, IXMLHTTPRequest_iface
);
115 static inline httprequest
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
117 return CONTAINING_RECORD(iface
, httprequest
, IObjectWithSite_iface
);
120 static inline httprequest
*impl_from_IObjectSafety(IObjectSafety
*iface
)
122 return CONTAINING_RECORD(iface
, httprequest
, IObjectSafety_iface
);
125 static inline httprequest
*impl_from_ISupportErrorInfo(ISupportErrorInfo
*iface
)
127 return CONTAINING_RECORD(iface
, httprequest
, ISupportErrorInfo_iface
);
130 static inline serverhttp
*impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest
*iface
)
132 return CONTAINING_RECORD(iface
, serverhttp
, IServerXMLHTTPRequest_iface
);
135 static void httprequest_setreadystate(httprequest
*This
, READYSTATE state
)
137 READYSTATE last
= This
->state
;
138 static const char* readystates
[] = {
139 "READYSTATE_UNINITIALIZED",
140 "READYSTATE_LOADING",
142 "READYSTATE_INTERACTIVE",
143 "READYSTATE_COMPLETE"};
147 TRACE("state %s\n", readystates
[state
]);
149 if (This
->sink
&& last
!= state
)
153 memset(¶ms
, 0, sizeof(params
));
154 IDispatch_Invoke(This
->sink
, 0, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, ¶ms
, 0, 0, 0);
158 static void free_response_headers(httprequest
*This
)
160 struct httpheader
*header
, *header2
;
162 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->respheaders
, struct httpheader
, entry
)
164 list_remove(&header
->entry
);
165 SysFreeString(header
->header
);
166 SysFreeString(header
->value
);
170 SysFreeString(This
->raw_respheaders
);
171 This
->raw_respheaders
= NULL
;
174 static void free_request_headers(httprequest
*This
)
176 struct httpheader
*header
, *header2
;
178 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->reqheaders
, struct httpheader
, entry
)
180 list_remove(&header
->entry
);
181 SysFreeString(header
->header
);
182 SysFreeString(header
->value
);
187 struct BindStatusCallback
189 IBindStatusCallback IBindStatusCallback_iface
;
190 IHttpNegotiate IHttpNegotiate_iface
;
191 IAuthenticate IAuthenticate_iface
;
195 httprequest
*request
;
200 /* request body data */
204 static inline BindStatusCallback
*impl_from_IBindStatusCallback( IBindStatusCallback
*iface
)
206 return CONTAINING_RECORD(iface
, BindStatusCallback
, IBindStatusCallback_iface
);
209 static inline BindStatusCallback
*impl_from_IHttpNegotiate( IHttpNegotiate
*iface
)
211 return CONTAINING_RECORD(iface
, BindStatusCallback
, IHttpNegotiate_iface
);
214 static inline BindStatusCallback
*impl_from_IAuthenticate( IAuthenticate
*iface
)
216 return CONTAINING_RECORD(iface
, BindStatusCallback
, IAuthenticate_iface
);
219 static void BindStatusCallback_Detach(BindStatusCallback
*bsc
)
223 if (bsc
->binding
) IBinding_Abort(bsc
->binding
);
224 bsc
->request
->bsc
= NULL
;
226 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
230 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
231 REFIID riid
, void **ppv
)
233 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
237 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
239 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
240 IsEqualGUID(&IID_IBindStatusCallback
, riid
))
242 *ppv
= &This
->IBindStatusCallback_iface
;
244 else if (IsEqualGUID(&IID_IHttpNegotiate
, riid
))
246 *ppv
= &This
->IHttpNegotiate_iface
;
248 else if (IsEqualGUID(&IID_IAuthenticate
, riid
))
250 *ppv
= &This
->IAuthenticate_iface
;
252 else if (IsEqualGUID(&IID_IServiceProvider
, riid
) ||
253 IsEqualGUID(&IID_IBindStatusCallbackEx
, riid
) ||
254 IsEqualGUID(&IID_IInternetProtocol
, riid
) ||
255 IsEqualGUID(&IID_IHttpNegotiate2
, riid
))
257 return E_NOINTERFACE
;
262 IBindStatusCallback_AddRef(iface
);
266 FIXME("Unsupported riid = %s\n", debugstr_guid(riid
));
268 return E_NOINTERFACE
;
271 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
273 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
274 LONG ref
= InterlockedIncrement(&This
->ref
);
276 TRACE("%p, refcount %ld.\n", iface
, ref
);
281 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
283 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
284 LONG ref
= InterlockedDecrement(&This
->ref
);
286 TRACE("%p, refcount %ld.\n", iface
, ref
);
290 if (This
->binding
) IBinding_Release(This
->binding
);
291 if (This
->stream
) IStream_Release(This
->stream
);
292 if (This
->body
) GlobalFree(This
->body
);
299 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
300 DWORD reserved
, IBinding
*pbind
)
302 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
304 TRACE("%p, %ld, %p.\n", iface
, reserved
, pbind
);
306 if (!pbind
) return E_INVALIDARG
;
308 This
->binding
= pbind
;
309 IBinding_AddRef(pbind
);
311 httprequest_setreadystate(This
->request
, READYSTATE_LOADED
);
313 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
316 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pPriority
)
318 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
320 TRACE("(%p)->(%p)\n", This
, pPriority
);
325 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
327 TRACE("%p, %ld.\n", iface
, reserved
);
332 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
333 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
335 TRACE("%p, %lu, %lu, %lu, %s.\n", iface
, ulProgress
, ulProgressMax
, ulStatusCode
,
336 debugstr_w(szStatusText
));
341 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
342 HRESULT hr
, LPCWSTR error
)
344 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
346 TRACE("%p, %#lx, %s.\n", iface
, hr
, debugstr_w(error
));
350 IBinding_Release(This
->binding
);
351 This
->binding
= NULL
;
356 BindStatusCallback_Detach(This
->request
->bsc
);
357 This
->request
->bsc
= This
;
358 httprequest_setreadystate(This
->request
, READYSTATE_COMPLETE
);
364 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
365 DWORD
*bind_flags
, BINDINFO
*pbindinfo
)
367 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
369 TRACE("(%p)->(%p %p)\n", This
, bind_flags
, pbindinfo
);
372 if (This
->request
->async
) *bind_flags
|= BINDF_ASYNCHRONOUS
;
374 if (This
->request
->verb
!= BINDVERB_GET
&& This
->body
)
376 pbindinfo
->stgmedData
.tymed
= TYMED_HGLOBAL
;
377 pbindinfo
->stgmedData
.hGlobal
= This
->body
;
378 pbindinfo
->cbstgmedData
= GlobalSize(This
->body
);
379 /* callback owns passed body pointer */
380 IBindStatusCallback_QueryInterface(iface
, &IID_IUnknown
, (void**)&pbindinfo
->stgmedData
.pUnkForRelease
);
383 pbindinfo
->dwBindVerb
= This
->request
->verb
;
384 if (This
->request
->verb
== BINDVERB_CUSTOM
)
386 pbindinfo
->szCustomVerb
= CoTaskMemAlloc(SysStringByteLen(This
->request
->custom
)+sizeof(WCHAR
));
387 lstrcpyW(pbindinfo
->szCustomVerb
, This
->request
->custom
);
393 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
394 DWORD flags
, DWORD size
, FORMATETC
*format
, STGMEDIUM
*stgmed
)
396 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
401 TRACE("%p, %#lx, %lu, %p, %p.\n", iface
, flags
, size
, format
, stgmed
);
405 hr
= IStream_Read(stgmed
->pstm
, buf
, sizeof(buf
), &read
);
406 if (hr
!= S_OK
) break;
408 hr
= IStream_Write(This
->stream
, buf
, read
, &written
);
409 } while((hr
== S_OK
) && written
!= 0 && read
!= 0);
411 httprequest_setreadystate(This
->request
, READYSTATE_INTERACTIVE
);
416 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
417 REFIID riid
, IUnknown
*punk
)
419 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
421 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
426 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
427 BindStatusCallback_QueryInterface
,
428 BindStatusCallback_AddRef
,
429 BindStatusCallback_Release
,
430 BindStatusCallback_OnStartBinding
,
431 BindStatusCallback_GetPriority
,
432 BindStatusCallback_OnLowResource
,
433 BindStatusCallback_OnProgress
,
434 BindStatusCallback_OnStopBinding
,
435 BindStatusCallback_GetBindInfo
,
436 BindStatusCallback_OnDataAvailable
,
437 BindStatusCallback_OnObjectAvailable
440 static HRESULT WINAPI
BSCHttpNegotiate_QueryInterface(IHttpNegotiate
*iface
,
441 REFIID riid
, void **ppv
)
443 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
444 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
447 static ULONG WINAPI
BSCHttpNegotiate_AddRef(IHttpNegotiate
*iface
)
449 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
450 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
453 static ULONG WINAPI
BSCHttpNegotiate_Release(IHttpNegotiate
*iface
)
455 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
456 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
459 static HRESULT WINAPI
BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate
*iface
,
460 LPCWSTR url
, LPCWSTR headers
, DWORD reserved
, LPWSTR
*add_headers
)
462 static const WCHAR content_type_utf8W
[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
463 't','e','x','t','/','p','l','a','i','n',';','c','h','a','r','s','e','t','=','u','t','f','-','8','\r','\n',0};
464 static const WCHAR refererW
[] = {'R','e','f','e','r','e','r',':',' ',0};
466 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
467 const struct httpheader
*entry
;
468 BSTR base_uri
= NULL
;
472 TRACE("%p, %s, %s, %ld, %p.\n", iface
, debugstr_w(url
), debugstr_w(headers
), reserved
, add_headers
);
476 if (This
->request
->use_utf8_content
)
477 size
= sizeof(content_type_utf8W
);
479 if (!list_empty(&This
->request
->reqheaders
))
480 size
+= This
->request
->reqheader_size
*sizeof(WCHAR
);
482 if (This
->request
->base_uri
)
484 IUri_GetRawUri(This
->request
->base_uri
, &base_uri
);
485 size
+= SysStringLen(base_uri
)*sizeof(WCHAR
) + sizeof(refererW
) + sizeof(crlfW
);
490 SysFreeString(base_uri
);
494 buff
= CoTaskMemAlloc(size
);
497 SysFreeString(base_uri
);
498 return E_OUTOFMEMORY
;
502 if (This
->request
->use_utf8_content
)
504 lstrcpyW(ptr
, content_type_utf8W
);
505 ptr
+= ARRAY_SIZE(content_type_utf8W
) - 1;
510 lstrcpyW(ptr
, refererW
);
511 lstrcatW(ptr
, base_uri
);
512 lstrcatW(ptr
, crlfW
);
513 ptr
+= lstrlenW(refererW
) + SysStringLen(base_uri
) + lstrlenW(crlfW
);
514 SysFreeString(base_uri
);
518 LIST_FOR_EACH_ENTRY(entry
, &This
->request
->reqheaders
, struct httpheader
, entry
)
520 lstrcpyW(ptr
, entry
->header
);
521 ptr
+= SysStringLen(entry
->header
);
523 lstrcpyW(ptr
, colspaceW
);
524 ptr
+= ARRAY_SIZE(colspaceW
) - 1;
526 lstrcpyW(ptr
, entry
->value
);
527 ptr
+= SysStringLen(entry
->value
);
529 lstrcpyW(ptr
, crlfW
);
530 ptr
+= ARRAY_SIZE(crlfW
) - 1;
538 static void add_response_header(httprequest
*This
, const WCHAR
*data
, int len
)
540 struct httpheader
*entry
;
541 const WCHAR
*ptr
= data
;
548 header
= SysAllocStringLen(data
, ptr
-data
);
549 /* skip leading spaces for a value */
550 while (*++ptr
== ' ')
552 value
= SysAllocStringLen(ptr
, len
-(ptr
-data
));
561 TRACE("got header %s:%s\n", debugstr_w(header
), debugstr_w(value
));
563 entry
= heap_alloc(sizeof(*entry
));
564 entry
->header
= header
;
565 entry
->value
= value
;
566 list_add_head(&This
->respheaders
, &entry
->entry
);
569 static HRESULT WINAPI
BSCHttpNegotiate_OnResponse(IHttpNegotiate
*iface
, DWORD code
,
570 LPCWSTR resp_headers
, LPCWSTR req_headers
, LPWSTR
*add_reqheaders
)
572 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
574 TRACE("%p, %ld, %s, %s, %p.\n", iface
, code
, debugstr_w(resp_headers
),
575 debugstr_w(req_headers
), add_reqheaders
);
577 This
->request
->status
= code
;
578 /* store headers and status text */
579 free_response_headers(This
->request
);
580 SysFreeString(This
->request
->status_text
);
581 This
->request
->status_text
= NULL
;
584 const WCHAR
*ptr
, *line
, *status_text
;
586 ptr
= line
= resp_headers
;
588 /* skip HTTP-Version */
589 ptr
= wcschr(ptr
, ' ');
592 /* skip Status-Code */
593 ptr
= wcschr(++ptr
, ' ');
597 /* now it supposed to end with CRLF */
600 if (*ptr
== '\r' && *(ptr
+1) == '\n')
603 This
->request
->status_text
= SysAllocStringLen(status_text
, ptr
-status_text
);
604 TRACE("status text %s\n", debugstr_w(This
->request
->status_text
));
612 /* store as unparsed string for now */
613 This
->request
->raw_respheaders
= SysAllocString(line
);
619 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl
= {
620 BSCHttpNegotiate_QueryInterface
,
621 BSCHttpNegotiate_AddRef
,
622 BSCHttpNegotiate_Release
,
623 BSCHttpNegotiate_BeginningTransaction
,
624 BSCHttpNegotiate_OnResponse
627 static HRESULT WINAPI
Authenticate_QueryInterface(IAuthenticate
*iface
,
628 REFIID riid
, void **ppv
)
630 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
631 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
634 static ULONG WINAPI
Authenticate_AddRef(IAuthenticate
*iface
)
636 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
637 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
640 static ULONG WINAPI
Authenticate_Release(IAuthenticate
*iface
)
642 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
643 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
646 static HRESULT WINAPI
Authenticate_Authenticate(IAuthenticate
*iface
,
647 HWND
*hwnd
, LPWSTR
*username
, LPWSTR
*password
)
649 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
650 httprequest
*request
= This
->request
;
652 TRACE("(%p)->(%p %p %p)\n", This
, hwnd
, username
, password
);
654 if (request
->user
&& *request
->user
)
656 if (hwnd
) *hwnd
= NULL
;
657 *username
= CoTaskMemAlloc(SysStringByteLen(request
->user
)+sizeof(WCHAR
));
658 *password
= CoTaskMemAlloc(SysStringByteLen(request
->password
)+sizeof(WCHAR
));
659 if (!*username
|| !*password
)
661 CoTaskMemFree(*username
);
662 CoTaskMemFree(*password
);
663 return E_OUTOFMEMORY
;
666 memcpy(*username
, request
->user
, SysStringByteLen(request
->user
)+sizeof(WCHAR
));
667 memcpy(*password
, request
->password
, SysStringByteLen(request
->password
)+sizeof(WCHAR
));
673 static const IAuthenticateVtbl AuthenticateVtbl
= {
674 Authenticate_QueryInterface
,
676 Authenticate_Release
,
677 Authenticate_Authenticate
680 static HRESULT
BindStatusCallback_create(httprequest
* This
, BindStatusCallback
**obj
, const VARIANT
*body
)
682 BindStatusCallback
*bsc
;
687 hr
= CreateBindCtx(0, &pbc
);
688 if (hr
!= S_OK
) return hr
;
690 bsc
= heap_alloc(sizeof(*bsc
));
693 IBindCtx_Release(pbc
);
694 return E_OUTOFMEMORY
;
697 bsc
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
698 bsc
->IHttpNegotiate_iface
.lpVtbl
= &BSCHttpNegotiateVtbl
;
699 bsc
->IAuthenticate_iface
.lpVtbl
= &AuthenticateVtbl
;
706 TRACE("(%p)->(%p)\n", This
, bsc
);
708 This
->use_utf8_content
= FALSE
;
710 if (This
->verb
!= BINDVERB_GET
)
712 void *send_data
, *ptr
;
713 SAFEARRAY
*sa
= NULL
;
715 if (V_VT(body
) == (VT_VARIANT
|VT_BYREF
))
716 body
= V_VARIANTREF(body
);
722 int len
= SysStringLen(V_BSTR(body
));
723 const WCHAR
*str
= V_BSTR(body
);
726 for (i
= 0; i
< len
; i
++)
735 size
= WideCharToMultiByte(cp
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
736 if (!(ptr
= heap_alloc(size
)))
739 return E_OUTOFMEMORY
;
741 WideCharToMultiByte(cp
, 0, str
, len
, ptr
, size
, NULL
, NULL
);
742 if (cp
== CP_UTF8
) This
->use_utf8_content
= TRUE
;
745 case VT_ARRAY
|VT_UI1
:
748 if ((hr
= SafeArrayAccessData(sa
, &ptr
)) != S_OK
)
753 if ((hr
= SafeArrayGetUBound(sa
, 1, &size
)) != S_OK
)
755 SafeArrayUnaccessData(sa
);
763 FIXME("unsupported body data type %d\n", V_VT(body
));
775 bsc
->body
= GlobalAlloc(GMEM_FIXED
, size
);
778 if (V_VT(body
) == VT_BSTR
)
780 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
781 SafeArrayUnaccessData(sa
);
784 return E_OUTOFMEMORY
;
787 send_data
= GlobalLock(bsc
->body
);
788 memcpy(send_data
, ptr
, size
);
789 GlobalUnlock(bsc
->body
);
792 if (V_VT(body
) == VT_BSTR
)
794 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
795 SafeArrayUnaccessData(sa
);
798 hr
= RegisterBindStatusCallback(pbc
, &bsc
->IBindStatusCallback_iface
, NULL
, 0);
803 hr
= CreateURLMonikerEx2(NULL
, This
->uri
, &moniker
, URL_MK_UNIFORM
);
808 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
809 IMoniker_Release(moniker
);
810 if (stream
) IStream_Release(stream
);
812 IBindCtx_Release(pbc
);
817 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
825 static HRESULT
verify_uri(httprequest
*This
, IUri
*uri
)
827 DWORD scheme
, base_scheme
;
828 BSTR host
, base_host
;
831 if(!(This
->safeopt
& INTERFACESAFE_FOR_UNTRUSTED_DATA
))
835 return E_ACCESSDENIED
;
837 hr
= IUri_GetScheme(uri
, &scheme
);
841 hr
= IUri_GetScheme(This
->base_uri
, &base_scheme
);
845 if(scheme
!= base_scheme
) {
846 WARN("Schemes don't match\n");
847 return E_ACCESSDENIED
;
850 if(scheme
== INTERNET_SCHEME_UNKNOWN
) {
851 FIXME("Unknown scheme\n");
852 return E_ACCESSDENIED
;
855 hr
= IUri_GetHost(uri
, &host
);
859 hr
= IUri_GetHost(This
->base_uri
, &base_host
);
861 if(wcsicmp(host
, base_host
)) {
862 WARN("Hosts don't match\n");
865 SysFreeString(base_host
);
872 static HRESULT
httprequest_open(httprequest
*This
, BSTR method
, BSTR url
,
873 VARIANT async
, VARIANT user
, VARIANT password
)
875 static const WCHAR MethodHeadW
[] = {'H','E','A','D',0};
876 static const WCHAR MethodGetW
[] = {'G','E','T',0};
877 static const WCHAR MethodPutW
[] = {'P','U','T',0};
878 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
879 static const WCHAR MethodDeleteW
[] = {'D','E','L','E','T','E',0};
880 static const WCHAR MethodPropFindW
[] = {'P','R','O','P','F','I','N','D',0};
881 VARIANT str
, is_async
;
885 if (!method
|| !url
) return E_INVALIDARG
;
887 /* free previously set data */
889 IUri_Release(This
->uri
);
893 SysFreeString(This
->user
);
894 SysFreeString(This
->password
);
895 This
->user
= This
->password
= NULL
;
896 free_request_headers(This
);
898 if (!wcsicmp(method
, MethodGetW
))
900 This
->verb
= BINDVERB_GET
;
902 else if (!wcsicmp(method
, MethodPutW
))
904 This
->verb
= BINDVERB_PUT
;
906 else if (!wcsicmp(method
, MethodPostW
))
908 This
->verb
= BINDVERB_POST
;
910 else if (!wcsicmp(method
, MethodDeleteW
) ||
911 !wcsicmp(method
, MethodHeadW
) ||
912 !wcsicmp(method
, MethodPropFindW
))
914 This
->verb
= BINDVERB_CUSTOM
;
915 SysReAllocString(&This
->custom
, method
);
919 FIXME("unsupported request type %s\n", debugstr_w(method
));
925 hr
= CoInternetCombineUrlEx(This
->base_uri
, url
, 0, &uri
, 0);
927 hr
= CreateUri(url
, 0, 0, &uri
);
929 WARN("Could not create IUri object, hr %#lx.\n", hr
);
933 hr
= verify_uri(This
, uri
);
940 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
942 This
->user
= V_BSTR(&str
);
945 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
947 This
->password
= V_BSTR(&str
);
949 /* add authentication info */
950 if (This
->user
&& *This
->user
)
952 IUriBuilder
*builder
;
954 hr
= CreateIUriBuilder(uri
, 0, 0, &builder
);
959 IUriBuilder_SetUserName(builder
, This
->user
);
960 IUriBuilder_SetPassword(builder
, This
->password
);
961 hr
= IUriBuilder_CreateUri(builder
, -1, 0, 0, &full_uri
);
968 WARN("failed to create modified uri, hr %#lx.\n", hr
);
969 IUriBuilder_Release(builder
);
972 WARN("IUriBuilder creation failed, hr %#lx.\n", hr
);
977 VariantInit(&is_async
);
978 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
979 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
);
981 httprequest_setreadystate(This
, READYSTATE_LOADING
);
986 static HRESULT
httprequest_setRequestHeader(httprequest
*This
, BSTR header
, BSTR value
)
988 struct httpheader
*entry
;
990 if (!header
|| !*header
) return E_INVALIDARG
;
991 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
992 if (!value
) return E_INVALIDARG
;
994 /* replace existing header value if already added */
995 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct httpheader
, entry
)
997 if (wcscmp(entry
->header
, header
) == 0)
999 LONG length
= SysStringLen(entry
->value
);
1002 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
1005 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
1011 entry
= heap_alloc(sizeof(*entry
));
1012 if (!entry
) return E_OUTOFMEMORY
;
1015 entry
->header
= SysAllocString(header
);
1016 entry
->value
= SysAllocString(value
);
1018 /* header length including null terminator */
1019 This
->reqheader_size
+= SysStringLen(entry
->header
) + ARRAY_SIZE(colspaceW
) +
1020 SysStringLen(entry
->value
) + ARRAY_SIZE(crlfW
) - 1;
1022 list_add_head(&This
->reqheaders
, &entry
->entry
);
1027 static HRESULT
httprequest_getResponseHeader(httprequest
*This
, BSTR header
, BSTR
*value
)
1029 struct httpheader
*entry
;
1031 if (!header
) return E_INVALIDARG
;
1032 if (!value
) return E_POINTER
;
1034 if (This
->raw_respheaders
&& list_empty(&This
->respheaders
))
1038 ptr
= line
= This
->raw_respheaders
;
1041 if (*ptr
== '\r' && *(ptr
+1) == '\n')
1043 add_response_header(This
, line
, ptr
-line
);
1044 ptr
++; line
= ++ptr
;
1051 LIST_FOR_EACH_ENTRY(entry
, &This
->respheaders
, struct httpheader
, entry
)
1053 if (!wcsicmp(entry
->header
, header
))
1055 *value
= SysAllocString(entry
->value
);
1056 TRACE("header value %s\n", debugstr_w(*value
));
1064 static HRESULT
httprequest_getAllResponseHeaders(httprequest
*This
, BSTR
*respheaders
)
1066 if (!respheaders
) return E_POINTER
;
1068 *respheaders
= SysAllocString(This
->raw_respheaders
);
1073 static HRESULT
httprequest_send(httprequest
*This
, VARIANT body
)
1075 BindStatusCallback
*bsc
= NULL
;
1078 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
1080 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
1082 /* success path to detach it is OnStopBinding call */
1083 BindStatusCallback_Detach(bsc
);
1088 static HRESULT
httprequest_abort(httprequest
*This
)
1090 BindStatusCallback_Detach(This
->bsc
);
1092 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
1097 static HRESULT
httprequest_get_status(httprequest
*This
, LONG
*status
)
1099 if (!status
) return E_POINTER
;
1101 *status
= This
->status
;
1103 return This
->state
== READYSTATE_COMPLETE
? S_OK
: E_FAIL
;
1106 static HRESULT
httprequest_get_statusText(httprequest
*This
, BSTR
*status
)
1108 if (!status
) return E_POINTER
;
1109 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1111 *status
= SysAllocString(This
->status_text
);
1116 enum response_encoding
1118 RESPONSE_ENCODING_NONE
,
1119 RESPONSE_ENCODING_UCS4BE
,
1120 RESPONSE_ENCODING_UCS4LE
,
1121 RESPONSE_ENCODING_UCS4_2143
,
1122 RESPONSE_ENCODING_UCS4_3412
,
1123 RESPONSE_ENCODING_EBCDIC
,
1124 RESPONSE_ENCODING_UTF8
,
1125 RESPONSE_ENCODING_UTF16LE
,
1126 RESPONSE_ENCODING_UTF16BE
,
1129 static unsigned int detect_response_encoding(const BYTE
*in
, unsigned int len
)
1133 if (in
[0] == 0 && in
[1] == 0 && in
[2] == 0 && in
[3] == 0x3c)
1134 return RESPONSE_ENCODING_UCS4BE
;
1135 if (in
[0] == 0x3c && in
[1] == 0 && in
[2] == 0 && in
[3] == 0)
1136 return RESPONSE_ENCODING_UCS4LE
;
1137 if (in
[0] == 0 && in
[1] == 0 && in
[2] == 0x3c && in
[3] == 0)
1138 return RESPONSE_ENCODING_UCS4_2143
;
1139 if (in
[0] == 0 && in
[1] == 0x3c && in
[2] == 0 && in
[3] == 0)
1140 return RESPONSE_ENCODING_UCS4_3412
;
1141 if (in
[0] == 0x4c && in
[1] == 0x6f && in
[2] == 0xa7 && in
[3] == 0x94)
1142 return RESPONSE_ENCODING_EBCDIC
;
1143 if (in
[0] == 0x3c && in
[1] == 0x3f && in
[2] == 0x78 && in
[3] == 0x6d)
1144 return RESPONSE_ENCODING_UTF8
;
1145 if (in
[0] == 0x3c && in
[1] == 0 && in
[2] == 0x3f && in
[3] == 0)
1146 return RESPONSE_ENCODING_UTF16LE
;
1147 if (in
[0] == 0 && in
[1] == 0x3c && in
[2] == 0 && in
[3] == 0x3f)
1148 return RESPONSE_ENCODING_UTF16BE
;
1153 if (in
[0] == 0xef && in
[1] == 0xbb && in
[2] == 0xbf)
1154 return RESPONSE_ENCODING_UTF8
;
1159 if (in
[0] == 0xfe && in
[1] == 0xff)
1160 return RESPONSE_ENCODING_UTF16BE
;
1161 if (in
[0] == 0xff && in
[1] == 0xfe)
1162 return RESPONSE_ENCODING_UTF16LE
;
1165 return RESPONSE_ENCODING_NONE
;
1168 static HRESULT
httprequest_get_responseText(httprequest
*This
, BSTR
*body
)
1173 if (!body
) return E_POINTER
;
1174 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1176 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1179 const char *ptr
= GlobalLock(hglobal
);
1180 DWORD size
= GlobalSize(hglobal
);
1181 unsigned int encoding
= RESPONSE_ENCODING_NONE
;
1183 /* try to determine data encoding */
1186 encoding
= detect_response_encoding((const BYTE
*)ptr
, 4);
1187 TRACE("detected encoding: %u.\n", encoding
);
1189 if (encoding
!= RESPONSE_ENCODING_UTF8
&&
1190 encoding
!= RESPONSE_ENCODING_UTF16LE
&&
1191 encoding
!= RESPONSE_ENCODING_NONE
)
1193 FIXME("unsupported response encoding: %u.\n", encoding
);
1194 GlobalUnlock(hglobal
);
1199 /* without BOM assume UTF-8 */
1200 if (encoding
== RESPONSE_ENCODING_UTF8
|| encoding
== RESPONSE_ENCODING_NONE
)
1202 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, ptr
, size
, NULL
, 0);
1204 *body
= SysAllocStringLen(NULL
, length
);
1206 MultiByteToWideChar( CP_UTF8
, 0, ptr
, size
, *body
, length
);
1209 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
1211 if (!*body
) hr
= E_OUTOFMEMORY
;
1212 GlobalUnlock(hglobal
);
1218 static HRESULT
httprequest_get_responseXML(httprequest
*This
, IDispatch
**body
)
1220 IXMLDOMDocument3
*doc
;
1224 if (!body
) return E_INVALIDARG
;
1225 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1227 hr
= dom_document_create(MSXML_DEFAULT
, (void**)&doc
);
1228 if (hr
!= S_OK
) return hr
;
1230 hr
= httprequest_get_responseText(This
, &str
);
1235 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
1239 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
1240 IXMLDOMDocument3_Release(doc
);
1245 static HRESULT
httprequest_get_responseBody(httprequest
*This
, VARIANT
*body
)
1250 if (!body
) return E_INVALIDARG
;
1251 V_VT(body
) = VT_EMPTY
;
1253 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1255 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1258 void *ptr
= GlobalLock(hglobal
);
1259 DWORD size
= GlobalSize(hglobal
);
1261 SAFEARRAYBOUND bound
;
1265 bound
.cElements
= size
;
1266 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
1272 V_VT(body
) = VT_ARRAY
| VT_UI1
;
1273 V_ARRAY(body
) = array
;
1275 hr
= SafeArrayAccessData(array
, &dest
);
1278 memcpy(dest
, ptr
, size
);
1279 SafeArrayUnaccessData(array
);
1289 GlobalUnlock(hglobal
);
1295 static HRESULT
httprequest_get_responseStream(httprequest
*This
, VARIANT
*body
)
1301 if (!body
) return E_INVALIDARG
;
1302 V_VT(body
) = VT_EMPTY
;
1304 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1306 hr
= IStream_Clone(This
->bsc
->stream
, &stream
);
1309 IStream_Seek(stream
, move
, STREAM_SEEK_SET
, NULL
);
1311 V_VT(body
) = VT_UNKNOWN
;
1312 V_UNKNOWN(body
) = (IUnknown
*)stream
;
1317 static HRESULT
httprequest_get_readyState(httprequest
*This
, LONG
*state
)
1319 if (!state
) return E_POINTER
;
1321 *state
= This
->state
;
1325 static HRESULT
httprequest_put_onreadystatechange(httprequest
*This
, IDispatch
*sink
)
1327 if (This
->sink
) IDispatch_Release(This
->sink
);
1328 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1333 static void httprequest_release(httprequest
*This
)
1336 IUnknown_Release( This
->site
);
1338 IUri_Release(This
->uri
);
1340 IUri_Release(This
->base_uri
);
1342 SysFreeString(This
->custom
);
1343 SysFreeString(This
->user
);
1344 SysFreeString(This
->password
);
1346 /* cleanup headers lists */
1347 free_request_headers(This
);
1348 free_response_headers(This
);
1349 SysFreeString(This
->status_text
);
1351 /* detach callback object */
1352 BindStatusCallback_Detach(This
->bsc
);
1354 if (This
->sink
) IDispatch_Release(This
->sink
);
1357 static HRESULT WINAPI
XMLHTTPRequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
1359 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1360 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1362 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1363 IsEqualGUID( riid
, &IID_IDispatch
) ||
1364 IsEqualGUID( riid
, &IID_IUnknown
) )
1368 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
1370 *ppvObject
= &This
->IObjectWithSite_iface
;
1372 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
1374 *ppvObject
= &This
->IObjectSafety_iface
;
1376 else if (IsEqualGUID(&IID_ISupportErrorInfo
, riid
))
1378 *ppvObject
= &This
->ISupportErrorInfo_iface
;
1382 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1384 return E_NOINTERFACE
;
1387 IUnknown_AddRef((IUnknown
*)*ppvObject
);
1392 static ULONG WINAPI
XMLHTTPRequest_AddRef(IXMLHTTPRequest
*iface
)
1394 httprequest
*request
= impl_from_IXMLHTTPRequest(iface
);
1395 ULONG ref
= InterlockedIncrement(&request
->ref
);
1396 TRACE("%p, refcount %lu.\n", iface
, ref
);
1400 static ULONG WINAPI
XMLHTTPRequest_Release(IXMLHTTPRequest
*iface
)
1402 httprequest
*request
= impl_from_IXMLHTTPRequest(iface
);
1403 ULONG ref
= InterlockedDecrement(&request
->ref
);
1405 TRACE("%p, refcount %lu.\n", iface
, ref
);
1409 httprequest_release(request
);
1416 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1418 TRACE("%p, %p.\n", iface
, pctinfo
);
1425 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
1426 LCID lcid
, ITypeInfo
**ppTInfo
)
1428 TRACE("%p, %u, %lx,%p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1430 return get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
1433 static HRESULT WINAPI
XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
1434 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1436 ITypeInfo
*typeinfo
;
1439 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
,
1442 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1443 return E_INVALIDARG
;
1445 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1448 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1449 ITypeInfo_Release(typeinfo
);
1455 static HRESULT WINAPI
XMLHTTPRequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1456 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1457 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1459 ITypeInfo
*typeinfo
;
1462 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1463 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1465 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1468 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1469 ITypeInfo_Release(typeinfo
);
1475 static HRESULT WINAPI
XMLHTTPRequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1476 VARIANT async
, VARIANT user
, VARIANT password
)
1478 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1479 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1480 debugstr_variant(&async
));
1481 return httprequest_open(This
, method
, url
, async
, user
, password
);
1484 static HRESULT WINAPI
XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1486 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1487 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1488 return httprequest_setRequestHeader(This
, header
, value
);
1491 static HRESULT WINAPI
XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1493 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1494 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1495 return httprequest_getResponseHeader(This
, header
, value
);
1498 static HRESULT WINAPI
XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1500 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1501 TRACE("(%p)->(%p)\n", This
, respheaders
);
1502 return httprequest_getAllResponseHeaders(This
, respheaders
);
1505 static HRESULT WINAPI
XMLHTTPRequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
1507 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1508 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1509 return httprequest_send(This
, body
);
1512 static HRESULT WINAPI
XMLHTTPRequest_abort(IXMLHTTPRequest
*iface
)
1514 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1515 TRACE("(%p)\n", This
);
1516 return httprequest_abort(This
);
1519 static HRESULT WINAPI
XMLHTTPRequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
1521 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1522 TRACE("(%p)->(%p)\n", This
, status
);
1523 return httprequest_get_status(This
, status
);
1526 static HRESULT WINAPI
XMLHTTPRequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*status
)
1528 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1529 TRACE("(%p)->(%p)\n", This
, status
);
1530 return httprequest_get_statusText(This
, status
);
1533 static HRESULT WINAPI
XMLHTTPRequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
1535 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1536 TRACE("(%p)->(%p)\n", This
, body
);
1537 return httprequest_get_responseXML(This
, body
);
1540 static HRESULT WINAPI
XMLHTTPRequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
1542 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1543 TRACE("(%p)->(%p)\n", This
, body
);
1544 return httprequest_get_responseText(This
, body
);
1547 static HRESULT WINAPI
XMLHTTPRequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1549 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1550 TRACE("(%p)->(%p)\n", This
, body
);
1551 return httprequest_get_responseBody(This
, body
);
1554 static HRESULT WINAPI
XMLHTTPRequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1556 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1557 TRACE("(%p)->(%p)\n", This
, body
);
1558 return httprequest_get_responseStream(This
, body
);
1561 static HRESULT WINAPI
XMLHTTPRequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
1563 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1564 TRACE("(%p)->(%p)\n", This
, state
);
1565 return httprequest_get_readyState(This
, state
);
1568 static HRESULT WINAPI
XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
1570 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1571 TRACE("(%p)->(%p)\n", This
, sink
);
1572 return httprequest_put_onreadystatechange(This
, sink
);
1575 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl
=
1577 XMLHTTPRequest_QueryInterface
,
1578 XMLHTTPRequest_AddRef
,
1579 XMLHTTPRequest_Release
,
1580 XMLHTTPRequest_GetTypeInfoCount
,
1581 XMLHTTPRequest_GetTypeInfo
,
1582 XMLHTTPRequest_GetIDsOfNames
,
1583 XMLHTTPRequest_Invoke
,
1584 XMLHTTPRequest_open
,
1585 XMLHTTPRequest_setRequestHeader
,
1586 XMLHTTPRequest_getResponseHeader
,
1587 XMLHTTPRequest_getAllResponseHeaders
,
1588 XMLHTTPRequest_send
,
1589 XMLHTTPRequest_abort
,
1590 XMLHTTPRequest_get_status
,
1591 XMLHTTPRequest_get_statusText
,
1592 XMLHTTPRequest_get_responseXML
,
1593 XMLHTTPRequest_get_responseText
,
1594 XMLHTTPRequest_get_responseBody
,
1595 XMLHTTPRequest_get_responseStream
,
1596 XMLHTTPRequest_get_readyState
,
1597 XMLHTTPRequest_put_onreadystatechange
1600 /* IObjectWithSite */
1601 static HRESULT WINAPI
1602 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1604 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1605 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppvObject
);
1608 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1610 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1611 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1614 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1616 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1617 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1620 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1622 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1624 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1629 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1632 IUri
*get_base_uri(IUnknown
*site
)
1634 IServiceProvider
*provider
;
1635 IHTMLDocument2
*doc
;
1640 hr
= IUnknown_QueryInterface(site
, &IID_IServiceProvider
, (void**)&provider
);
1644 hr
= IServiceProvider_QueryService(provider
, &SID_SContainerDispatch
, &IID_IHTMLDocument2
, (void**)&doc
);
1646 hr
= IServiceProvider_QueryService(provider
, &SID_SInternetHostSecurityManager
, &IID_IHTMLDocument2
, (void**)&doc
);
1647 IServiceProvider_Release(provider
);
1651 hr
= IHTMLDocument2_get_URL(doc
, &url
);
1652 IHTMLDocument2_Release(doc
);
1653 if(FAILED(hr
) || !url
|| !*url
)
1656 TRACE("host url %s\n", debugstr_w(url
));
1658 hr
= CreateUri(url
, 0, 0, &uri
);
1666 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1668 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1670 TRACE("(%p)->(%p)\n", This
, punk
);
1673 IUnknown_Release( This
->site
);
1675 IUri_Release(This
->base_uri
);
1681 IUnknown_AddRef( punk
);
1682 This
->base_uri
= get_base_uri(This
->site
);
1688 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1690 httprequest_ObjectWithSite_QueryInterface
,
1691 httprequest_ObjectWithSite_AddRef
,
1692 httprequest_ObjectWithSite_Release
,
1693 httprequest_ObjectWithSite_SetSite
,
1694 httprequest_ObjectWithSite_GetSite
1698 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1700 httprequest
*This
= impl_from_IObjectSafety(iface
);
1701 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppv
);
1704 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1706 httprequest
*This
= impl_from_IObjectSafety(iface
);
1707 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1710 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1712 httprequest
*This
= impl_from_IObjectSafety(iface
);
1713 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1716 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1717 DWORD
*supported
, DWORD
*enabled
)
1719 httprequest
*This
= impl_from_IObjectSafety(iface
);
1721 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1723 if(!supported
|| !enabled
) return E_POINTER
;
1725 *supported
= safety_supported_options
;
1726 *enabled
= This
->safeopt
;
1731 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1732 DWORD mask
, DWORD enabled
)
1734 httprequest
*request
= impl_from_IObjectSafety(iface
);
1736 TRACE("%p, %s, %lx, %lx.\n", iface
, debugstr_guid(riid
), mask
, enabled
);
1738 if ((mask
& ~safety_supported_options
))
1741 request
->safeopt
= (request
->safeopt
& ~mask
) | (mask
& enabled
);
1746 static const IObjectSafetyVtbl ObjectSafetyVtbl
= {
1747 httprequest_Safety_QueryInterface
,
1748 httprequest_Safety_AddRef
,
1749 httprequest_Safety_Release
,
1750 httprequest_Safety_GetInterfaceSafetyOptions
,
1751 httprequest_Safety_SetInterfaceSafetyOptions
1754 static HRESULT WINAPI
SupportErrorInfo_QueryInterface(ISupportErrorInfo
*iface
, REFIID riid
, void **obj
)
1756 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1757 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, obj
);
1760 static ULONG WINAPI
SupportErrorInfo_AddRef(ISupportErrorInfo
*iface
)
1762 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1763 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1766 static ULONG WINAPI
SupportErrorInfo_Release(ISupportErrorInfo
*iface
)
1768 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1769 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1772 static HRESULT WINAPI
SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo
*iface
, REFIID riid
)
1774 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1776 FIXME("(%p)->(%s)\n", This
, debugstr_guid(riid
));
1781 static const ISupportErrorInfoVtbl SupportErrorInfoVtbl
=
1783 SupportErrorInfo_QueryInterface
,
1784 SupportErrorInfo_AddRef
,
1785 SupportErrorInfo_Release
,
1786 SupportErrorInfo_InterfaceSupportsErrorInfo
,
1789 /* IServerXMLHTTPRequest */
1790 static HRESULT WINAPI
ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest
*iface
, REFIID riid
, void **obj
)
1792 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1794 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1796 if ( IsEqualGUID( riid
, &IID_IServerXMLHTTPRequest
) ||
1797 IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1798 IsEqualGUID( riid
, &IID_IDispatch
) ||
1799 IsEqualGUID( riid
, &IID_IUnknown
) )
1803 else if ( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
1805 *obj
= &This
->req
.ISupportErrorInfo_iface
;
1809 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1811 return E_NOINTERFACE
;
1814 IUnknown_AddRef( (IUnknown
*)*obj
);
1819 static ULONG WINAPI
ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest
*iface
)
1821 serverhttp
*request
= impl_from_IServerXMLHTTPRequest(iface
);
1822 ULONG ref
= InterlockedIncrement(&request
->req
.ref
);
1823 TRACE("%p, refcount %lu.\n", iface
, ref
);
1827 static ULONG WINAPI
ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest
*iface
)
1829 serverhttp
*request
= impl_from_IServerXMLHTTPRequest(iface
);
1830 ULONG ref
= InterlockedDecrement(&request
->req
.ref
);
1832 TRACE("%p, refcount %lu.\n", iface
, ref
);
1836 httprequest_release(&request
->req
);
1843 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1845 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1847 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1853 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest
*iface
, UINT iTInfo
,
1854 LCID lcid
, ITypeInfo
**ppTInfo
)
1856 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1858 return get_typeinfo(IServerXMLHTTPRequest_tid
, ppTInfo
);
1861 static HRESULT WINAPI
ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest
*iface
, REFIID riid
,
1862 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1864 ITypeInfo
*typeinfo
;
1867 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
,
1870 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1871 return E_INVALIDARG
;
1873 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1876 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1877 ITypeInfo_Release(typeinfo
);
1883 static HRESULT WINAPI
ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1884 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1885 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1887 ITypeInfo
*typeinfo
;
1890 TRACE("%p, %ld, %s %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1891 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1893 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1896 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1897 ITypeInfo_Release(typeinfo
);
1903 static HRESULT WINAPI
ServerXMLHTTPRequest_open(IServerXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1904 VARIANT async
, VARIANT user
, VARIANT password
)
1906 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1907 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1908 debugstr_variant(&async
));
1909 return httprequest_open(&This
->req
, method
, url
, async
, user
, password
);
1912 static HRESULT WINAPI
ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1914 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1915 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1916 return httprequest_setRequestHeader(&This
->req
, header
, value
);
1919 static HRESULT WINAPI
ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1921 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1922 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1923 return httprequest_getResponseHeader(&This
->req
, header
, value
);
1926 static HRESULT WINAPI
ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1928 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1929 TRACE("(%p)->(%p)\n", This
, respheaders
);
1930 return httprequest_getAllResponseHeaders(&This
->req
, respheaders
);
1933 static HRESULT WINAPI
ServerXMLHTTPRequest_send(IServerXMLHTTPRequest
*iface
, VARIANT body
)
1935 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1936 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1937 return httprequest_send(&This
->req
, body
);
1940 static HRESULT WINAPI
ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest
*iface
)
1942 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1943 TRACE("(%p)\n", This
);
1944 return httprequest_abort(&This
->req
);
1947 static HRESULT WINAPI
ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest
*iface
, LONG
*status
)
1949 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1950 TRACE("(%p)->(%p)\n", This
, status
);
1951 return httprequest_get_status(&This
->req
, status
);
1954 static HRESULT WINAPI
ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest
*iface
, BSTR
*status
)
1956 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1957 TRACE("(%p)->(%p)\n", This
, status
);
1958 return httprequest_get_statusText(&This
->req
, status
);
1961 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest
*iface
, IDispatch
**body
)
1963 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1964 TRACE("(%p)->(%p)\n", This
, body
);
1965 return httprequest_get_responseXML(&This
->req
, body
);
1968 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest
*iface
, BSTR
*body
)
1970 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1971 TRACE("(%p)->(%p)\n", This
, body
);
1972 return httprequest_get_responseText(&This
->req
, body
);
1975 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1977 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1978 TRACE("(%p)->(%p)\n", This
, body
);
1979 return httprequest_get_responseBody(&This
->req
, body
);
1982 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1984 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1985 TRACE("(%p)->(%p)\n", This
, body
);
1986 return httprequest_get_responseStream(&This
->req
, body
);
1989 static HRESULT WINAPI
ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest
*iface
, LONG
*state
)
1991 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1992 TRACE("(%p)->(%p)\n", This
, state
);
1993 return httprequest_get_readyState(&This
->req
, state
);
1996 static HRESULT WINAPI
ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest
*iface
, IDispatch
*sink
)
1998 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1999 TRACE("(%p)->(%p)\n", This
, sink
);
2000 return httprequest_put_onreadystatechange(&This
->req
, sink
);
2003 static HRESULT WINAPI
ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest
*iface
, LONG resolveTimeout
, LONG connectTimeout
,
2004 LONG sendTimeout
, LONG receiveTimeout
)
2006 FIXME("%p, %ld, %ld, %ld, %ld: stub\n", iface
, resolveTimeout
, connectTimeout
, sendTimeout
, receiveTimeout
);
2010 static HRESULT WINAPI
ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest
*iface
, VARIANT timeout
, VARIANT_BOOL
*isSuccessful
)
2012 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2013 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_variant(&timeout
), isSuccessful
);
2017 static HRESULT WINAPI
ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT
*value
)
2019 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2020 FIXME("(%p)->(%d %p): stub\n", This
, option
, value
);
2024 static HRESULT WINAPI
ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT value
)
2026 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2027 FIXME("(%p)->(%d %s): stub\n", This
, option
, debugstr_variant(&value
));
2031 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl
=
2033 ServerXMLHTTPRequest_QueryInterface
,
2034 ServerXMLHTTPRequest_AddRef
,
2035 ServerXMLHTTPRequest_Release
,
2036 ServerXMLHTTPRequest_GetTypeInfoCount
,
2037 ServerXMLHTTPRequest_GetTypeInfo
,
2038 ServerXMLHTTPRequest_GetIDsOfNames
,
2039 ServerXMLHTTPRequest_Invoke
,
2040 ServerXMLHTTPRequest_open
,
2041 ServerXMLHTTPRequest_setRequestHeader
,
2042 ServerXMLHTTPRequest_getResponseHeader
,
2043 ServerXMLHTTPRequest_getAllResponseHeaders
,
2044 ServerXMLHTTPRequest_send
,
2045 ServerXMLHTTPRequest_abort
,
2046 ServerXMLHTTPRequest_get_status
,
2047 ServerXMLHTTPRequest_get_statusText
,
2048 ServerXMLHTTPRequest_get_responseXML
,
2049 ServerXMLHTTPRequest_get_responseText
,
2050 ServerXMLHTTPRequest_get_responseBody
,
2051 ServerXMLHTTPRequest_get_responseStream
,
2052 ServerXMLHTTPRequest_get_readyState
,
2053 ServerXMLHTTPRequest_put_onreadystatechange
,
2054 ServerXMLHTTPRequest_setTimeouts
,
2055 ServerXMLHTTPRequest_waitForResponse
,
2056 ServerXMLHTTPRequest_getOption
,
2057 ServerXMLHTTPRequest_setOption
2060 static void init_httprequest(httprequest
*req
)
2062 req
->IXMLHTTPRequest_iface
.lpVtbl
= &XMLHTTPRequestVtbl
;
2063 req
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
2064 req
->IObjectSafety_iface
.lpVtbl
= &ObjectSafetyVtbl
;
2065 req
->ISupportErrorInfo_iface
.lpVtbl
= &SupportErrorInfoVtbl
;
2071 req
->uri
= req
->base_uri
= NULL
;
2072 req
->user
= req
->password
= NULL
;
2074 req
->state
= READYSTATE_UNINITIALIZED
;
2079 req
->status_text
= NULL
;
2080 req
->reqheader_size
= 0;
2081 req
->raw_respheaders
= NULL
;
2082 req
->use_utf8_content
= FALSE
;
2084 list_init(&req
->reqheaders
);
2085 list_init(&req
->respheaders
);
2091 HRESULT
XMLHTTPRequest_create(void **obj
)
2095 TRACE("(%p)\n", obj
);
2097 req
= heap_alloc( sizeof (*req
) );
2099 return E_OUTOFMEMORY
;
2101 init_httprequest(req
);
2102 *obj
= &req
->IXMLHTTPRequest_iface
;
2104 TRACE("returning iface %p\n", *obj
);
2109 HRESULT
ServerXMLHTTP_create(void **obj
)
2113 TRACE("(%p)\n", obj
);
2115 req
= heap_alloc( sizeof (*req
) );
2117 return E_OUTOFMEMORY
;
2119 init_httprequest(&req
->req
);
2120 req
->IServerXMLHTTPRequest_iface
.lpVtbl
= &ServerXMLHTTPRequestVtbl
;
2122 *obj
= &req
->IServerXMLHTTPRequest_iface
;
2124 TRACE("returning iface %p\n", *obj
);