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
= malloc(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
;
683 IBindCtx
*pbc
= NULL
;
687 if (!(bsc
= malloc(sizeof(*bsc
))))
688 return E_OUTOFMEMORY
;
690 bsc
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
691 bsc
->IHttpNegotiate_iface
.lpVtbl
= &BSCHttpNegotiateVtbl
;
692 bsc
->IAuthenticate_iface
.lpVtbl
= &AuthenticateVtbl
;
699 TRACE("(%p)->(%p)\n", This
, bsc
);
701 This
->use_utf8_content
= FALSE
;
703 if (This
->verb
!= BINDVERB_GET
)
705 void *send_data
, *ptr
;
706 SAFEARRAY
*sa
= NULL
;
708 if (V_VT(body
) == (VT_VARIANT
|VT_BYREF
))
709 body
= V_VARIANTREF(body
);
715 int len
= SysStringLen(V_BSTR(body
));
716 const WCHAR
*str
= V_BSTR(body
);
719 for (i
= 0; i
< len
; i
++)
728 size
= WideCharToMultiByte(cp
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
729 if (!(ptr
= malloc(size
)))
732 return E_OUTOFMEMORY
;
734 WideCharToMultiByte(cp
, 0, str
, len
, ptr
, size
, NULL
, NULL
);
735 if (cp
== CP_UTF8
) This
->use_utf8_content
= TRUE
;
738 case VT_ARRAY
|VT_UI1
:
741 if ((hr
= SafeArrayAccessData(sa
, &ptr
)) != S_OK
)
746 if ((hr
= SafeArrayGetUBound(sa
, 1, &size
)) != S_OK
)
748 SafeArrayUnaccessData(sa
);
756 FIXME("unsupported body data type %d\n", V_VT(body
));
768 bsc
->body
= GlobalAlloc(GMEM_FIXED
, size
);
771 if (V_VT(body
) == VT_BSTR
)
773 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
774 SafeArrayUnaccessData(sa
);
777 return E_OUTOFMEMORY
;
780 send_data
= GlobalLock(bsc
->body
);
781 memcpy(send_data
, ptr
, size
);
782 GlobalUnlock(bsc
->body
);
785 if (V_VT(body
) == VT_BSTR
)
787 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
788 SafeArrayUnaccessData(sa
);
791 hr
= CreateBindCtx(0, &pbc
);
793 hr
= RegisterBindStatusCallback(pbc
, &bsc
->IBindStatusCallback_iface
, NULL
, 0);
798 hr
= CreateURLMonikerEx2(NULL
, This
->uri
, &moniker
, URL_MK_UNIFORM
);
803 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
804 IMoniker_Release(moniker
);
805 if (stream
) IStream_Release(stream
);
810 IBindCtx_Release(pbc
);
814 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
822 static HRESULT
verify_uri(httprequest
*This
, IUri
*uri
)
824 DWORD scheme
, base_scheme
;
825 BSTR host
, base_host
;
828 if(!(This
->safeopt
& INTERFACESAFE_FOR_UNTRUSTED_DATA
))
832 return E_ACCESSDENIED
;
834 hr
= IUri_GetScheme(uri
, &scheme
);
838 hr
= IUri_GetScheme(This
->base_uri
, &base_scheme
);
842 if(scheme
!= base_scheme
) {
843 WARN("Schemes don't match\n");
844 return E_ACCESSDENIED
;
847 if(scheme
== INTERNET_SCHEME_UNKNOWN
) {
848 FIXME("Unknown scheme\n");
849 return E_ACCESSDENIED
;
852 hr
= IUri_GetHost(uri
, &host
);
856 hr
= IUri_GetHost(This
->base_uri
, &base_host
);
858 if(wcsicmp(host
, base_host
)) {
859 WARN("Hosts don't match\n");
862 SysFreeString(base_host
);
869 static HRESULT
httprequest_open(httprequest
*This
, BSTR method
, BSTR url
,
870 VARIANT async
, VARIANT user
, VARIANT password
)
872 static const WCHAR MethodHeadW
[] = {'H','E','A','D',0};
873 static const WCHAR MethodGetW
[] = {'G','E','T',0};
874 static const WCHAR MethodPutW
[] = {'P','U','T',0};
875 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
876 static const WCHAR MethodDeleteW
[] = {'D','E','L','E','T','E',0};
877 static const WCHAR MethodPropFindW
[] = {'P','R','O','P','F','I','N','D',0};
878 VARIANT str
, is_async
;
882 if (!method
|| !url
) return E_INVALIDARG
;
884 /* free previously set data */
886 IUri_Release(This
->uri
);
890 SysFreeString(This
->user
);
891 SysFreeString(This
->password
);
892 This
->user
= This
->password
= NULL
;
893 free_request_headers(This
);
895 if (!wcsicmp(method
, MethodGetW
))
897 This
->verb
= BINDVERB_GET
;
899 else if (!wcsicmp(method
, MethodPutW
))
901 This
->verb
= BINDVERB_PUT
;
903 else if (!wcsicmp(method
, MethodPostW
))
905 This
->verb
= BINDVERB_POST
;
907 else if (!wcsicmp(method
, MethodDeleteW
) ||
908 !wcsicmp(method
, MethodHeadW
) ||
909 !wcsicmp(method
, MethodPropFindW
))
911 This
->verb
= BINDVERB_CUSTOM
;
912 SysReAllocString(&This
->custom
, method
);
916 FIXME("unsupported request type %s\n", debugstr_w(method
));
922 hr
= CoInternetCombineUrlEx(This
->base_uri
, url
, 0, &uri
, 0);
924 hr
= CreateUri(url
, 0, 0, &uri
);
926 WARN("Could not create IUri object, hr %#lx.\n", hr
);
930 hr
= verify_uri(This
, uri
);
937 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
939 This
->user
= V_BSTR(&str
);
942 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
944 This
->password
= V_BSTR(&str
);
946 /* add authentication info */
947 if (This
->user
&& *This
->user
)
949 IUriBuilder
*builder
;
951 hr
= CreateIUriBuilder(uri
, 0, 0, &builder
);
956 IUriBuilder_SetUserName(builder
, This
->user
);
957 IUriBuilder_SetPassword(builder
, This
->password
);
958 hr
= IUriBuilder_CreateUri(builder
, -1, 0, 0, &full_uri
);
965 WARN("failed to create modified uri, hr %#lx.\n", hr
);
966 IUriBuilder_Release(builder
);
969 WARN("IUriBuilder creation failed, hr %#lx.\n", hr
);
974 VariantInit(&is_async
);
975 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
976 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
);
978 httprequest_setreadystate(This
, READYSTATE_LOADING
);
983 static HRESULT
httprequest_setRequestHeader(httprequest
*This
, BSTR header
, BSTR value
)
985 struct httpheader
*entry
;
987 if (!header
|| !*header
) return E_INVALIDARG
;
988 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
989 if (!value
) return E_INVALIDARG
;
991 /* replace existing header value if already added */
992 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct httpheader
, entry
)
994 if (wcscmp(entry
->header
, header
) == 0)
996 LONG length
= SysStringLen(entry
->value
);
999 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
1002 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
1008 entry
= malloc(sizeof(*entry
));
1009 if (!entry
) return E_OUTOFMEMORY
;
1012 entry
->header
= SysAllocString(header
);
1013 entry
->value
= SysAllocString(value
);
1015 /* header length including null terminator */
1016 This
->reqheader_size
+= SysStringLen(entry
->header
) + ARRAY_SIZE(colspaceW
) +
1017 SysStringLen(entry
->value
) + ARRAY_SIZE(crlfW
) - 1;
1019 list_add_head(&This
->reqheaders
, &entry
->entry
);
1024 static HRESULT
httprequest_getResponseHeader(httprequest
*This
, BSTR header
, BSTR
*value
)
1026 struct httpheader
*entry
;
1028 if (!header
) return E_INVALIDARG
;
1029 if (!value
) return E_POINTER
;
1031 if (This
->raw_respheaders
&& list_empty(&This
->respheaders
))
1035 ptr
= line
= This
->raw_respheaders
;
1038 if (*ptr
== '\r' && *(ptr
+1) == '\n')
1040 add_response_header(This
, line
, ptr
-line
);
1041 ptr
++; line
= ++ptr
;
1048 LIST_FOR_EACH_ENTRY(entry
, &This
->respheaders
, struct httpheader
, entry
)
1050 if (!wcsicmp(entry
->header
, header
))
1052 *value
= SysAllocString(entry
->value
);
1053 TRACE("header value %s\n", debugstr_w(*value
));
1061 static HRESULT
httprequest_getAllResponseHeaders(httprequest
*This
, BSTR
*respheaders
)
1063 if (!respheaders
) return E_POINTER
;
1065 *respheaders
= SysAllocString(This
->raw_respheaders
);
1070 static HRESULT
httprequest_send(httprequest
*This
, VARIANT body
)
1072 BindStatusCallback
*bsc
= NULL
;
1075 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
1077 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
1079 /* success path to detach it is OnStopBinding call */
1080 BindStatusCallback_Detach(bsc
);
1085 static HRESULT
httprequest_abort(httprequest
*This
)
1087 BindStatusCallback_Detach(This
->bsc
);
1089 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
1094 static HRESULT
httprequest_get_status(httprequest
*This
, LONG
*status
)
1096 if (!status
) return E_POINTER
;
1098 *status
= This
->status
;
1100 return This
->state
== READYSTATE_COMPLETE
? S_OK
: E_FAIL
;
1103 static HRESULT
httprequest_get_statusText(httprequest
*This
, BSTR
*status
)
1105 if (!status
) return E_POINTER
;
1106 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1108 *status
= SysAllocString(This
->status_text
);
1113 enum response_encoding
1115 RESPONSE_ENCODING_NONE
,
1116 RESPONSE_ENCODING_UCS4BE
,
1117 RESPONSE_ENCODING_UCS4LE
,
1118 RESPONSE_ENCODING_UCS4_2143
,
1119 RESPONSE_ENCODING_UCS4_3412
,
1120 RESPONSE_ENCODING_EBCDIC
,
1121 RESPONSE_ENCODING_UTF8
,
1122 RESPONSE_ENCODING_UTF16LE
,
1123 RESPONSE_ENCODING_UTF16BE
,
1126 static unsigned int detect_response_encoding(const BYTE
*in
, unsigned int len
)
1130 if (in
[0] == 0 && in
[1] == 0 && in
[2] == 0 && in
[3] == 0x3c)
1131 return RESPONSE_ENCODING_UCS4BE
;
1132 if (in
[0] == 0x3c && in
[1] == 0 && in
[2] == 0 && in
[3] == 0)
1133 return RESPONSE_ENCODING_UCS4LE
;
1134 if (in
[0] == 0 && in
[1] == 0 && in
[2] == 0x3c && in
[3] == 0)
1135 return RESPONSE_ENCODING_UCS4_2143
;
1136 if (in
[0] == 0 && in
[1] == 0x3c && in
[2] == 0 && in
[3] == 0)
1137 return RESPONSE_ENCODING_UCS4_3412
;
1138 if (in
[0] == 0x4c && in
[1] == 0x6f && in
[2] == 0xa7 && in
[3] == 0x94)
1139 return RESPONSE_ENCODING_EBCDIC
;
1140 if (in
[0] == 0x3c && in
[1] == 0x3f && in
[2] == 0x78 && in
[3] == 0x6d)
1141 return RESPONSE_ENCODING_UTF8
;
1142 if (in
[0] == 0x3c && in
[1] == 0 && in
[2] == 0x3f && in
[3] == 0)
1143 return RESPONSE_ENCODING_UTF16LE
;
1144 if (in
[0] == 0 && in
[1] == 0x3c && in
[2] == 0 && in
[3] == 0x3f)
1145 return RESPONSE_ENCODING_UTF16BE
;
1150 if (in
[0] == 0xef && in
[1] == 0xbb && in
[2] == 0xbf)
1151 return RESPONSE_ENCODING_UTF8
;
1156 if (in
[0] == 0xfe && in
[1] == 0xff)
1157 return RESPONSE_ENCODING_UTF16BE
;
1158 if (in
[0] == 0xff && in
[1] == 0xfe)
1159 return RESPONSE_ENCODING_UTF16LE
;
1162 return RESPONSE_ENCODING_NONE
;
1165 static HRESULT
httprequest_get_responseText(httprequest
*This
, BSTR
*body
)
1170 if (!body
) return E_POINTER
;
1171 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1173 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1176 const char *ptr
= GlobalLock(hglobal
);
1177 DWORD size
= GlobalSize(hglobal
);
1178 unsigned int encoding
= RESPONSE_ENCODING_NONE
;
1180 /* try to determine data encoding */
1183 encoding
= detect_response_encoding((const BYTE
*)ptr
, 4);
1184 TRACE("detected encoding: %u.\n", encoding
);
1186 if (encoding
!= RESPONSE_ENCODING_UTF8
&&
1187 encoding
!= RESPONSE_ENCODING_UTF16LE
&&
1188 encoding
!= RESPONSE_ENCODING_NONE
)
1190 FIXME("unsupported response encoding: %u.\n", encoding
);
1191 GlobalUnlock(hglobal
);
1196 /* without BOM assume UTF-8 */
1197 if (encoding
== RESPONSE_ENCODING_UTF8
|| encoding
== RESPONSE_ENCODING_NONE
)
1199 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, ptr
, size
, NULL
, 0);
1201 *body
= SysAllocStringLen(NULL
, length
);
1203 MultiByteToWideChar( CP_UTF8
, 0, ptr
, size
, *body
, length
);
1206 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
1208 if (!*body
) hr
= E_OUTOFMEMORY
;
1209 GlobalUnlock(hglobal
);
1215 static HRESULT
httprequest_get_responseXML(httprequest
*This
, IDispatch
**body
)
1217 IXMLDOMDocument3
*doc
;
1221 if (!body
) return E_INVALIDARG
;
1222 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1224 hr
= dom_document_create(MSXML_DEFAULT
, (void**)&doc
);
1225 if (hr
!= S_OK
) return hr
;
1227 hr
= httprequest_get_responseText(This
, &str
);
1232 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
1236 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
1237 IXMLDOMDocument3_Release(doc
);
1242 static HRESULT
httprequest_get_responseBody(httprequest
*This
, VARIANT
*body
)
1247 if (!body
) return E_INVALIDARG
;
1248 V_VT(body
) = VT_EMPTY
;
1250 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1252 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1255 void *ptr
= GlobalLock(hglobal
);
1256 DWORD size
= GlobalSize(hglobal
);
1258 SAFEARRAYBOUND bound
;
1262 bound
.cElements
= size
;
1263 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
1269 V_VT(body
) = VT_ARRAY
| VT_UI1
;
1270 V_ARRAY(body
) = array
;
1272 hr
= SafeArrayAccessData(array
, &dest
);
1275 memcpy(dest
, ptr
, size
);
1276 SafeArrayUnaccessData(array
);
1286 GlobalUnlock(hglobal
);
1292 static HRESULT
httprequest_get_responseStream(httprequest
*This
, VARIANT
*body
)
1298 if (!body
) return E_INVALIDARG
;
1299 V_VT(body
) = VT_EMPTY
;
1301 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1303 hr
= IStream_Clone(This
->bsc
->stream
, &stream
);
1306 IStream_Seek(stream
, move
, STREAM_SEEK_SET
, NULL
);
1308 V_VT(body
) = VT_UNKNOWN
;
1309 V_UNKNOWN(body
) = (IUnknown
*)stream
;
1314 static HRESULT
httprequest_get_readyState(httprequest
*This
, LONG
*state
)
1316 if (!state
) return E_POINTER
;
1318 *state
= This
->state
;
1322 static HRESULT
httprequest_put_onreadystatechange(httprequest
*This
, IDispatch
*sink
)
1324 if (This
->sink
) IDispatch_Release(This
->sink
);
1325 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1330 static void httprequest_release(httprequest
*This
)
1333 IUnknown_Release( This
->site
);
1335 IUri_Release(This
->uri
);
1337 IUri_Release(This
->base_uri
);
1339 SysFreeString(This
->custom
);
1340 SysFreeString(This
->user
);
1341 SysFreeString(This
->password
);
1343 /* cleanup headers lists */
1344 free_request_headers(This
);
1345 free_response_headers(This
);
1346 SysFreeString(This
->status_text
);
1348 /* detach callback object */
1349 BindStatusCallback_Detach(This
->bsc
);
1351 if (This
->sink
) IDispatch_Release(This
->sink
);
1354 static HRESULT WINAPI
XMLHTTPRequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
1356 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1357 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1359 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1360 IsEqualGUID( riid
, &IID_IDispatch
) ||
1361 IsEqualGUID( riid
, &IID_IUnknown
) )
1365 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
1367 *ppvObject
= &This
->IObjectWithSite_iface
;
1369 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
1371 *ppvObject
= &This
->IObjectSafety_iface
;
1373 else if (IsEqualGUID(&IID_ISupportErrorInfo
, riid
))
1375 *ppvObject
= &This
->ISupportErrorInfo_iface
;
1379 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1381 return E_NOINTERFACE
;
1384 IUnknown_AddRef((IUnknown
*)*ppvObject
);
1389 static ULONG WINAPI
XMLHTTPRequest_AddRef(IXMLHTTPRequest
*iface
)
1391 httprequest
*request
= impl_from_IXMLHTTPRequest(iface
);
1392 ULONG ref
= InterlockedIncrement(&request
->ref
);
1393 TRACE("%p, refcount %lu.\n", iface
, ref
);
1397 static ULONG WINAPI
XMLHTTPRequest_Release(IXMLHTTPRequest
*iface
)
1399 httprequest
*request
= impl_from_IXMLHTTPRequest(iface
);
1400 ULONG ref
= InterlockedDecrement(&request
->ref
);
1402 TRACE("%p, refcount %lu.\n", iface
, ref
);
1406 httprequest_release(request
);
1413 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1415 TRACE("%p, %p.\n", iface
, pctinfo
);
1422 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
1423 LCID lcid
, ITypeInfo
**ppTInfo
)
1425 TRACE("%p, %u, %lx,%p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1427 return get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
1430 static HRESULT WINAPI
XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
1431 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1433 ITypeInfo
*typeinfo
;
1436 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
,
1439 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1440 return E_INVALIDARG
;
1442 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1445 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1446 ITypeInfo_Release(typeinfo
);
1452 static HRESULT WINAPI
XMLHTTPRequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1453 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1454 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1456 ITypeInfo
*typeinfo
;
1459 TRACE("%p, %ld, %s, %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1460 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1462 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1465 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1466 ITypeInfo_Release(typeinfo
);
1472 static HRESULT WINAPI
XMLHTTPRequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1473 VARIANT async
, VARIANT user
, VARIANT password
)
1475 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1476 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1477 debugstr_variant(&async
));
1478 return httprequest_open(This
, method
, url
, async
, user
, password
);
1481 static HRESULT WINAPI
XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1483 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1484 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1485 return httprequest_setRequestHeader(This
, header
, value
);
1488 static HRESULT WINAPI
XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1490 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1491 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1492 return httprequest_getResponseHeader(This
, header
, value
);
1495 static HRESULT WINAPI
XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1497 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1498 TRACE("(%p)->(%p)\n", This
, respheaders
);
1499 return httprequest_getAllResponseHeaders(This
, respheaders
);
1502 static HRESULT WINAPI
XMLHTTPRequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
1504 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1505 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1506 return httprequest_send(This
, body
);
1509 static HRESULT WINAPI
XMLHTTPRequest_abort(IXMLHTTPRequest
*iface
)
1511 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1512 TRACE("(%p)\n", This
);
1513 return httprequest_abort(This
);
1516 static HRESULT WINAPI
XMLHTTPRequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
1518 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1519 TRACE("(%p)->(%p)\n", This
, status
);
1520 return httprequest_get_status(This
, status
);
1523 static HRESULT WINAPI
XMLHTTPRequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*status
)
1525 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1526 TRACE("(%p)->(%p)\n", This
, status
);
1527 return httprequest_get_statusText(This
, status
);
1530 static HRESULT WINAPI
XMLHTTPRequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
1532 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1533 TRACE("(%p)->(%p)\n", This
, body
);
1534 return httprequest_get_responseXML(This
, body
);
1537 static HRESULT WINAPI
XMLHTTPRequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
1539 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1540 TRACE("(%p)->(%p)\n", This
, body
);
1541 return httprequest_get_responseText(This
, body
);
1544 static HRESULT WINAPI
XMLHTTPRequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1546 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1547 TRACE("(%p)->(%p)\n", This
, body
);
1548 return httprequest_get_responseBody(This
, body
);
1551 static HRESULT WINAPI
XMLHTTPRequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1553 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1554 TRACE("(%p)->(%p)\n", This
, body
);
1555 return httprequest_get_responseStream(This
, body
);
1558 static HRESULT WINAPI
XMLHTTPRequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
1560 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1561 TRACE("(%p)->(%p)\n", This
, state
);
1562 return httprequest_get_readyState(This
, state
);
1565 static HRESULT WINAPI
XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
1567 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1568 TRACE("(%p)->(%p)\n", This
, sink
);
1569 return httprequest_put_onreadystatechange(This
, sink
);
1572 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl
=
1574 XMLHTTPRequest_QueryInterface
,
1575 XMLHTTPRequest_AddRef
,
1576 XMLHTTPRequest_Release
,
1577 XMLHTTPRequest_GetTypeInfoCount
,
1578 XMLHTTPRequest_GetTypeInfo
,
1579 XMLHTTPRequest_GetIDsOfNames
,
1580 XMLHTTPRequest_Invoke
,
1581 XMLHTTPRequest_open
,
1582 XMLHTTPRequest_setRequestHeader
,
1583 XMLHTTPRequest_getResponseHeader
,
1584 XMLHTTPRequest_getAllResponseHeaders
,
1585 XMLHTTPRequest_send
,
1586 XMLHTTPRequest_abort
,
1587 XMLHTTPRequest_get_status
,
1588 XMLHTTPRequest_get_statusText
,
1589 XMLHTTPRequest_get_responseXML
,
1590 XMLHTTPRequest_get_responseText
,
1591 XMLHTTPRequest_get_responseBody
,
1592 XMLHTTPRequest_get_responseStream
,
1593 XMLHTTPRequest_get_readyState
,
1594 XMLHTTPRequest_put_onreadystatechange
1597 /* IObjectWithSite */
1598 static HRESULT WINAPI
1599 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1601 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1602 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppvObject
);
1605 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1607 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1608 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1611 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1613 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1614 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1617 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1619 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1621 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1626 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1629 IUri
*get_base_uri(IUnknown
*site
)
1631 IServiceProvider
*provider
;
1632 IHTMLDocument2
*doc
;
1637 hr
= IUnknown_QueryInterface(site
, &IID_IServiceProvider
, (void**)&provider
);
1641 hr
= IServiceProvider_QueryService(provider
, &SID_SContainerDispatch
, &IID_IHTMLDocument2
, (void**)&doc
);
1643 hr
= IServiceProvider_QueryService(provider
, &SID_SInternetHostSecurityManager
, &IID_IHTMLDocument2
, (void**)&doc
);
1644 IServiceProvider_Release(provider
);
1648 hr
= IHTMLDocument2_get_URL(doc
, &url
);
1649 IHTMLDocument2_Release(doc
);
1650 if(FAILED(hr
) || !url
|| !*url
)
1653 TRACE("host url %s\n", debugstr_w(url
));
1655 hr
= CreateUri(url
, 0, 0, &uri
);
1663 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1665 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1667 TRACE("(%p)->(%p)\n", This
, punk
);
1670 IUnknown_Release( This
->site
);
1672 IUri_Release(This
->base_uri
);
1678 IUnknown_AddRef( punk
);
1679 This
->base_uri
= get_base_uri(This
->site
);
1685 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1687 httprequest_ObjectWithSite_QueryInterface
,
1688 httprequest_ObjectWithSite_AddRef
,
1689 httprequest_ObjectWithSite_Release
,
1690 httprequest_ObjectWithSite_SetSite
,
1691 httprequest_ObjectWithSite_GetSite
1695 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1697 httprequest
*This
= impl_from_IObjectSafety(iface
);
1698 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppv
);
1701 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1703 httprequest
*This
= impl_from_IObjectSafety(iface
);
1704 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1707 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1709 httprequest
*This
= impl_from_IObjectSafety(iface
);
1710 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1713 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1714 DWORD
*supported
, DWORD
*enabled
)
1716 httprequest
*This
= impl_from_IObjectSafety(iface
);
1718 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1720 if(!supported
|| !enabled
) return E_POINTER
;
1722 *supported
= safety_supported_options
;
1723 *enabled
= This
->safeopt
;
1728 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1729 DWORD mask
, DWORD enabled
)
1731 httprequest
*request
= impl_from_IObjectSafety(iface
);
1733 TRACE("%p, %s, %lx, %lx.\n", iface
, debugstr_guid(riid
), mask
, enabled
);
1735 if ((mask
& ~safety_supported_options
))
1738 request
->safeopt
= (request
->safeopt
& ~mask
) | (mask
& enabled
);
1743 static const IObjectSafetyVtbl ObjectSafetyVtbl
= {
1744 httprequest_Safety_QueryInterface
,
1745 httprequest_Safety_AddRef
,
1746 httprequest_Safety_Release
,
1747 httprequest_Safety_GetInterfaceSafetyOptions
,
1748 httprequest_Safety_SetInterfaceSafetyOptions
1751 static HRESULT WINAPI
SupportErrorInfo_QueryInterface(ISupportErrorInfo
*iface
, REFIID riid
, void **obj
)
1753 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1754 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, obj
);
1757 static ULONG WINAPI
SupportErrorInfo_AddRef(ISupportErrorInfo
*iface
)
1759 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1760 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1763 static ULONG WINAPI
SupportErrorInfo_Release(ISupportErrorInfo
*iface
)
1765 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1766 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1769 static HRESULT WINAPI
SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo
*iface
, REFIID riid
)
1771 httprequest
*This
= impl_from_ISupportErrorInfo(iface
);
1773 FIXME("(%p)->(%s)\n", This
, debugstr_guid(riid
));
1778 static const ISupportErrorInfoVtbl SupportErrorInfoVtbl
=
1780 SupportErrorInfo_QueryInterface
,
1781 SupportErrorInfo_AddRef
,
1782 SupportErrorInfo_Release
,
1783 SupportErrorInfo_InterfaceSupportsErrorInfo
,
1786 /* IServerXMLHTTPRequest */
1787 static HRESULT WINAPI
ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest
*iface
, REFIID riid
, void **obj
)
1789 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1791 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1793 if ( IsEqualGUID( riid
, &IID_IServerXMLHTTPRequest
) ||
1794 IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1795 IsEqualGUID( riid
, &IID_IDispatch
) ||
1796 IsEqualGUID( riid
, &IID_IUnknown
) )
1800 else if ( IsEqualGUID( riid
, &IID_ISupportErrorInfo
))
1802 *obj
= &This
->req
.ISupportErrorInfo_iface
;
1806 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1808 return E_NOINTERFACE
;
1811 IUnknown_AddRef( (IUnknown
*)*obj
);
1816 static ULONG WINAPI
ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest
*iface
)
1818 serverhttp
*request
= impl_from_IServerXMLHTTPRequest(iface
);
1819 ULONG ref
= InterlockedIncrement(&request
->req
.ref
);
1820 TRACE("%p, refcount %lu.\n", iface
, ref
);
1824 static ULONG WINAPI
ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest
*iface
)
1826 serverhttp
*request
= impl_from_IServerXMLHTTPRequest(iface
);
1827 ULONG ref
= InterlockedDecrement(&request
->req
.ref
);
1829 TRACE("%p, refcount %lu.\n", iface
, ref
);
1833 httprequest_release(&request
->req
);
1840 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1842 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1844 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1850 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest
*iface
, UINT iTInfo
,
1851 LCID lcid
, ITypeInfo
**ppTInfo
)
1853 TRACE("%p, %u, %lx, %p.\n", iface
, iTInfo
, lcid
, ppTInfo
);
1855 return get_typeinfo(IServerXMLHTTPRequest_tid
, ppTInfo
);
1858 static HRESULT WINAPI
ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest
*iface
, REFIID riid
,
1859 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1861 ITypeInfo
*typeinfo
;
1864 TRACE("%p, %s, %p, %u, %lx, %p.\n", iface
, debugstr_guid(riid
), rgszNames
, cNames
,
1867 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1868 return E_INVALIDARG
;
1870 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1873 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1874 ITypeInfo_Release(typeinfo
);
1880 static HRESULT WINAPI
ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1881 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1882 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1884 ITypeInfo
*typeinfo
;
1887 TRACE("%p, %ld, %s %lx, %d, %p, %p, %p, %p.\n", iface
, dispIdMember
, debugstr_guid(riid
),
1888 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1890 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1893 hr
= ITypeInfo_Invoke(typeinfo
, iface
, dispIdMember
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1894 ITypeInfo_Release(typeinfo
);
1900 static HRESULT WINAPI
ServerXMLHTTPRequest_open(IServerXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1901 VARIANT async
, VARIANT user
, VARIANT password
)
1903 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1904 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1905 debugstr_variant(&async
));
1906 return httprequest_open(&This
->req
, method
, url
, async
, user
, password
);
1909 static HRESULT WINAPI
ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1911 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1912 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1913 return httprequest_setRequestHeader(&This
->req
, header
, value
);
1916 static HRESULT WINAPI
ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1918 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1919 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1920 return httprequest_getResponseHeader(&This
->req
, header
, value
);
1923 static HRESULT WINAPI
ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1925 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1926 TRACE("(%p)->(%p)\n", This
, respheaders
);
1927 return httprequest_getAllResponseHeaders(&This
->req
, respheaders
);
1930 static HRESULT WINAPI
ServerXMLHTTPRequest_send(IServerXMLHTTPRequest
*iface
, VARIANT body
)
1932 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1933 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1934 return httprequest_send(&This
->req
, body
);
1937 static HRESULT WINAPI
ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest
*iface
)
1939 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1940 TRACE("(%p)\n", This
);
1941 return httprequest_abort(&This
->req
);
1944 static HRESULT WINAPI
ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest
*iface
, LONG
*status
)
1946 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1947 TRACE("(%p)->(%p)\n", This
, status
);
1948 return httprequest_get_status(&This
->req
, status
);
1951 static HRESULT WINAPI
ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest
*iface
, BSTR
*status
)
1953 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1954 TRACE("(%p)->(%p)\n", This
, status
);
1955 return httprequest_get_statusText(&This
->req
, status
);
1958 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest
*iface
, IDispatch
**body
)
1960 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1961 TRACE("(%p)->(%p)\n", This
, body
);
1962 return httprequest_get_responseXML(&This
->req
, body
);
1965 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest
*iface
, BSTR
*body
)
1967 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1968 TRACE("(%p)->(%p)\n", This
, body
);
1969 return httprequest_get_responseText(&This
->req
, body
);
1972 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1974 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1975 TRACE("(%p)->(%p)\n", This
, body
);
1976 return httprequest_get_responseBody(&This
->req
, body
);
1979 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1981 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1982 TRACE("(%p)->(%p)\n", This
, body
);
1983 return httprequest_get_responseStream(&This
->req
, body
);
1986 static HRESULT WINAPI
ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest
*iface
, LONG
*state
)
1988 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1989 TRACE("(%p)->(%p)\n", This
, state
);
1990 return httprequest_get_readyState(&This
->req
, state
);
1993 static HRESULT WINAPI
ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest
*iface
, IDispatch
*sink
)
1995 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1996 TRACE("(%p)->(%p)\n", This
, sink
);
1997 return httprequest_put_onreadystatechange(&This
->req
, sink
);
2000 static HRESULT WINAPI
ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest
*iface
, LONG resolveTimeout
, LONG connectTimeout
,
2001 LONG sendTimeout
, LONG receiveTimeout
)
2003 FIXME("%p, %ld, %ld, %ld, %ld: stub\n", iface
, resolveTimeout
, connectTimeout
, sendTimeout
, receiveTimeout
);
2007 static HRESULT WINAPI
ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest
*iface
, VARIANT timeout
, VARIANT_BOOL
*isSuccessful
)
2009 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2010 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_variant(&timeout
), isSuccessful
);
2014 static HRESULT WINAPI
ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT
*value
)
2016 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2017 FIXME("(%p)->(%d %p): stub\n", This
, option
, value
);
2021 static HRESULT WINAPI
ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT value
)
2023 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
2024 FIXME("(%p)->(%d %s): stub\n", This
, option
, debugstr_variant(&value
));
2028 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl
=
2030 ServerXMLHTTPRequest_QueryInterface
,
2031 ServerXMLHTTPRequest_AddRef
,
2032 ServerXMLHTTPRequest_Release
,
2033 ServerXMLHTTPRequest_GetTypeInfoCount
,
2034 ServerXMLHTTPRequest_GetTypeInfo
,
2035 ServerXMLHTTPRequest_GetIDsOfNames
,
2036 ServerXMLHTTPRequest_Invoke
,
2037 ServerXMLHTTPRequest_open
,
2038 ServerXMLHTTPRequest_setRequestHeader
,
2039 ServerXMLHTTPRequest_getResponseHeader
,
2040 ServerXMLHTTPRequest_getAllResponseHeaders
,
2041 ServerXMLHTTPRequest_send
,
2042 ServerXMLHTTPRequest_abort
,
2043 ServerXMLHTTPRequest_get_status
,
2044 ServerXMLHTTPRequest_get_statusText
,
2045 ServerXMLHTTPRequest_get_responseXML
,
2046 ServerXMLHTTPRequest_get_responseText
,
2047 ServerXMLHTTPRequest_get_responseBody
,
2048 ServerXMLHTTPRequest_get_responseStream
,
2049 ServerXMLHTTPRequest_get_readyState
,
2050 ServerXMLHTTPRequest_put_onreadystatechange
,
2051 ServerXMLHTTPRequest_setTimeouts
,
2052 ServerXMLHTTPRequest_waitForResponse
,
2053 ServerXMLHTTPRequest_getOption
,
2054 ServerXMLHTTPRequest_setOption
2057 static void init_httprequest(httprequest
*req
)
2059 req
->IXMLHTTPRequest_iface
.lpVtbl
= &XMLHTTPRequestVtbl
;
2060 req
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
2061 req
->IObjectSafety_iface
.lpVtbl
= &ObjectSafetyVtbl
;
2062 req
->ISupportErrorInfo_iface
.lpVtbl
= &SupportErrorInfoVtbl
;
2068 req
->uri
= req
->base_uri
= NULL
;
2069 req
->user
= req
->password
= NULL
;
2071 req
->state
= READYSTATE_UNINITIALIZED
;
2076 req
->status_text
= NULL
;
2077 req
->reqheader_size
= 0;
2078 req
->raw_respheaders
= NULL
;
2079 req
->use_utf8_content
= FALSE
;
2081 list_init(&req
->reqheaders
);
2082 list_init(&req
->respheaders
);
2088 HRESULT
XMLHTTPRequest_create(void **obj
)
2092 TRACE("(%p)\n", obj
);
2094 req
= malloc(sizeof(*req
));
2096 return E_OUTOFMEMORY
;
2098 init_httprequest(req
);
2099 *obj
= &req
->IXMLHTTPRequest_iface
;
2101 TRACE("returning iface %p\n", *obj
);
2106 HRESULT
ServerXMLHTTP_create(void **obj
)
2110 TRACE("(%p)\n", obj
);
2112 req
= malloc(sizeof(*req
));
2114 return E_OUTOFMEMORY
;
2116 init_httprequest(&req
->req
);
2117 req
->IServerXMLHTTPRequest_iface
.lpVtbl
= &ServerXMLHTTPRequestVtbl
;
2119 *obj
= &req
->IServerXMLHTTPRequest_iface
;
2121 TRACE("returning iface %p\n", *obj
);