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
31 static const WCHAR colspaceW
[] = {':',' ',0};
32 static const WCHAR crlfW
[] = {'\r','\n',0};
33 static const DWORD safety_supported_options
=
34 INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
35 INTERFACESAFE_FOR_UNTRUSTED_DATA
|
36 INTERFACE_USES_SECURITY_MANAGER
;
38 typedef struct BindStatusCallback BindStatusCallback
;
49 IXMLHTTPRequest IXMLHTTPRequest_iface
;
50 IObjectWithSite IObjectWithSite_iface
;
51 IObjectSafety IObjectSafety_iface
;
63 struct list reqheaders
;
64 /* cached resulting custom request headers string length in WCHARs */
66 /* use UTF-8 content type */
67 BOOL use_utf8_content
;
69 /* response headers */
70 struct list respheaders
;
78 BindStatusCallback
*bsc
;
92 IServerXMLHTTPRequest IServerXMLHTTPRequest_iface
;
96 static inline httprequest
*impl_from_IXMLHTTPRequest( IXMLHTTPRequest
*iface
)
98 return CONTAINING_RECORD(iface
, httprequest
, IXMLHTTPRequest_iface
);
101 static inline httprequest
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
103 return CONTAINING_RECORD(iface
, httprequest
, IObjectWithSite_iface
);
106 static inline httprequest
*impl_from_IObjectSafety(IObjectSafety
*iface
)
108 return CONTAINING_RECORD(iface
, httprequest
, IObjectSafety_iface
);
111 static inline serverhttp
*impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest
*iface
)
113 return CONTAINING_RECORD(iface
, serverhttp
, IServerXMLHTTPRequest_iface
);
116 static void httprequest_setreadystate(httprequest
*This
, READYSTATE state
)
118 READYSTATE last
= This
->state
;
119 static const char* readystates
[] = {
120 "READYSTATE_UNINITIALIZED",
121 "READYSTATE_LOADING",
123 "READYSTATE_INTERACTIVE",
124 "READYSTATE_COMPLETE"};
128 TRACE("state %s\n", readystates
[state
]);
130 if (This
->sink
&& last
!= state
)
134 memset(¶ms
, 0, sizeof(params
));
135 IDispatch_Invoke(This
->sink
, 0, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, ¶ms
, 0, 0, 0);
139 static void free_response_headers(httprequest
*This
)
141 struct httpheader
*header
, *header2
;
143 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->respheaders
, struct httpheader
, entry
)
145 list_remove(&header
->entry
);
146 SysFreeString(header
->header
);
147 SysFreeString(header
->value
);
151 SysFreeString(This
->raw_respheaders
);
152 This
->raw_respheaders
= NULL
;
155 struct BindStatusCallback
157 IBindStatusCallback IBindStatusCallback_iface
;
158 IHttpNegotiate IHttpNegotiate_iface
;
159 IAuthenticate IAuthenticate_iface
;
163 httprequest
*request
;
168 /* request body data */
172 static inline BindStatusCallback
*impl_from_IBindStatusCallback( IBindStatusCallback
*iface
)
174 return CONTAINING_RECORD(iface
, BindStatusCallback
, IBindStatusCallback_iface
);
177 static inline BindStatusCallback
*impl_from_IHttpNegotiate( IHttpNegotiate
*iface
)
179 return CONTAINING_RECORD(iface
, BindStatusCallback
, IHttpNegotiate_iface
);
182 static inline BindStatusCallback
*impl_from_IAuthenticate( IAuthenticate
*iface
)
184 return CONTAINING_RECORD(iface
, BindStatusCallback
, IAuthenticate_iface
);
187 static void BindStatusCallback_Detach(BindStatusCallback
*bsc
)
191 if (bsc
->binding
) IBinding_Abort(bsc
->binding
);
192 bsc
->request
->bsc
= NULL
;
194 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
198 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
199 REFIID riid
, void **ppv
)
201 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
205 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
207 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
208 IsEqualGUID(&IID_IBindStatusCallback
, riid
))
210 *ppv
= &This
->IBindStatusCallback_iface
;
212 else if (IsEqualGUID(&IID_IHttpNegotiate
, riid
))
214 *ppv
= &This
->IHttpNegotiate_iface
;
216 else if (IsEqualGUID(&IID_IAuthenticate
, riid
))
218 *ppv
= &This
->IAuthenticate_iface
;
220 else if (IsEqualGUID(&IID_IServiceProvider
, riid
) ||
221 IsEqualGUID(&IID_IBindStatusCallbackEx
, riid
) ||
222 IsEqualGUID(&IID_IInternetProtocol
, riid
) ||
223 IsEqualGUID(&IID_IHttpNegotiate2
, riid
))
225 return E_NOINTERFACE
;
230 IBindStatusCallback_AddRef(iface
);
234 FIXME("Unsupported riid = %s\n", debugstr_guid(riid
));
236 return E_NOINTERFACE
;
239 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
241 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
242 LONG ref
= InterlockedIncrement(&This
->ref
);
244 TRACE("(%p) ref = %d\n", This
, ref
);
249 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
251 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
252 LONG ref
= InterlockedDecrement(&This
->ref
);
254 TRACE("(%p) ref = %d\n", This
, ref
);
258 if (This
->binding
) IBinding_Release(This
->binding
);
259 if (This
->stream
) IStream_Release(This
->stream
);
260 if (This
->body
) GlobalFree(This
->body
);
267 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
268 DWORD reserved
, IBinding
*pbind
)
270 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
272 TRACE("(%p)->(%d %p)\n", This
, reserved
, pbind
);
274 if (!pbind
) return E_INVALIDARG
;
276 This
->binding
= pbind
;
277 IBinding_AddRef(pbind
);
279 httprequest_setreadystate(This
->request
, READYSTATE_LOADED
);
281 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
284 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pPriority
)
286 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
288 TRACE("(%p)->(%p)\n", This
, pPriority
);
293 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
295 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
297 TRACE("(%p)->(%d)\n", This
, reserved
);
302 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
303 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
305 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
307 TRACE("(%p)->(%u %u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
308 debugstr_w(szStatusText
));
313 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
314 HRESULT hr
, LPCWSTR error
)
316 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
318 TRACE("(%p)->(0x%08x %s)\n", This
, hr
, debugstr_w(error
));
322 IBinding_Release(This
->binding
);
323 This
->binding
= NULL
;
328 BindStatusCallback_Detach(This
->request
->bsc
);
329 This
->request
->bsc
= This
;
330 httprequest_setreadystate(This
->request
, READYSTATE_COMPLETE
);
336 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
337 DWORD
*bind_flags
, BINDINFO
*pbindinfo
)
339 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
341 TRACE("(%p)->(%p %p)\n", This
, bind_flags
, pbindinfo
);
344 if (This
->request
->async
) *bind_flags
|= BINDF_ASYNCHRONOUS
;
346 if (This
->request
->verb
!= BINDVERB_GET
&& This
->body
)
348 pbindinfo
->stgmedData
.tymed
= TYMED_HGLOBAL
;
349 pbindinfo
->stgmedData
.u
.hGlobal
= This
->body
;
350 pbindinfo
->cbstgmedData
= GlobalSize(This
->body
);
351 /* callback owns passed body pointer */
352 IBindStatusCallback_QueryInterface(iface
, &IID_IUnknown
, (void**)&pbindinfo
->stgmedData
.pUnkForRelease
);
355 pbindinfo
->dwBindVerb
= This
->request
->verb
;
356 if (This
->request
->verb
== BINDVERB_CUSTOM
)
358 pbindinfo
->szCustomVerb
= CoTaskMemAlloc(SysStringByteLen(This
->request
->custom
));
359 strcpyW(pbindinfo
->szCustomVerb
, This
->request
->custom
);
365 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
366 DWORD flags
, DWORD size
, FORMATETC
*format
, STGMEDIUM
*stgmed
)
368 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
373 TRACE("(%p)->(%08x %d %p %p)\n", This
, flags
, size
, format
, stgmed
);
377 hr
= IStream_Read(stgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
378 if (hr
!= S_OK
) break;
380 hr
= IStream_Write(This
->stream
, buf
, read
, &written
);
381 } while((hr
== S_OK
) && written
!= 0 && read
!= 0);
383 httprequest_setreadystate(This
->request
, READYSTATE_INTERACTIVE
);
388 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
389 REFIID riid
, IUnknown
*punk
)
391 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
393 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
398 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
399 BindStatusCallback_QueryInterface
,
400 BindStatusCallback_AddRef
,
401 BindStatusCallback_Release
,
402 BindStatusCallback_OnStartBinding
,
403 BindStatusCallback_GetPriority
,
404 BindStatusCallback_OnLowResource
,
405 BindStatusCallback_OnProgress
,
406 BindStatusCallback_OnStopBinding
,
407 BindStatusCallback_GetBindInfo
,
408 BindStatusCallback_OnDataAvailable
,
409 BindStatusCallback_OnObjectAvailable
412 static HRESULT WINAPI
BSCHttpNegotiate_QueryInterface(IHttpNegotiate
*iface
,
413 REFIID riid
, void **ppv
)
415 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
416 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
419 static ULONG WINAPI
BSCHttpNegotiate_AddRef(IHttpNegotiate
*iface
)
421 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
422 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
425 static ULONG WINAPI
BSCHttpNegotiate_Release(IHttpNegotiate
*iface
)
427 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
428 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
431 static HRESULT WINAPI
BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate
*iface
,
432 LPCWSTR url
, LPCWSTR headers
, DWORD reserved
, LPWSTR
*add_headers
)
434 static const WCHAR content_type_utf8W
[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
435 't','e','x','t','/','p','l','a','i','n',';','c','h','a','r','s','e','t','=','u','t','f','-','8','\r','\n',0};
437 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
438 const struct httpheader
*entry
;
442 TRACE("(%p)->(%s %s %d %p)\n", This
, debugstr_w(url
), debugstr_w(headers
), reserved
, add_headers
);
446 if (This
->request
->use_utf8_content
)
447 size
= sizeof(content_type_utf8W
);
449 if (!list_empty(&This
->request
->reqheaders
))
450 size
+= This
->request
->reqheader_size
*sizeof(WCHAR
);
452 if (!size
) return S_OK
;
454 buff
= CoTaskMemAlloc(size
);
455 if (!buff
) return E_OUTOFMEMORY
;
458 if (This
->request
->use_utf8_content
)
460 lstrcpyW(ptr
, content_type_utf8W
);
461 ptr
+= sizeof(content_type_utf8W
)/sizeof(WCHAR
)-1;
465 LIST_FOR_EACH_ENTRY(entry
, &This
->request
->reqheaders
, struct httpheader
, entry
)
467 lstrcpyW(ptr
, entry
->header
);
468 ptr
+= SysStringLen(entry
->header
);
470 lstrcpyW(ptr
, colspaceW
);
471 ptr
+= sizeof(colspaceW
)/sizeof(WCHAR
)-1;
473 lstrcpyW(ptr
, entry
->value
);
474 ptr
+= SysStringLen(entry
->value
);
476 lstrcpyW(ptr
, crlfW
);
477 ptr
+= sizeof(crlfW
)/sizeof(WCHAR
)-1;
485 static void add_response_header(httprequest
*This
, const WCHAR
*data
, int len
)
487 struct httpheader
*entry
;
488 const WCHAR
*ptr
= data
;
495 header
= SysAllocStringLen(data
, ptr
-data
);
496 /* skip leading spaces for a value */
497 while (*++ptr
== ' ')
499 value
= SysAllocStringLen(ptr
, len
-(ptr
-data
));
508 TRACE("got header %s:%s\n", debugstr_w(header
), debugstr_w(value
));
510 entry
= heap_alloc(sizeof(*entry
));
511 entry
->header
= header
;
512 entry
->value
= value
;
513 list_add_head(&This
->respheaders
, &entry
->entry
);
516 static HRESULT WINAPI
BSCHttpNegotiate_OnResponse(IHttpNegotiate
*iface
, DWORD code
,
517 LPCWSTR resp_headers
, LPCWSTR req_headers
, LPWSTR
*add_reqheaders
)
519 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
521 TRACE("(%p)->(%d %s %s %p)\n", This
, code
, debugstr_w(resp_headers
),
522 debugstr_w(req_headers
), add_reqheaders
);
524 This
->request
->status
= code
;
525 /* store headers and status text */
526 free_response_headers(This
->request
);
527 SysFreeString(This
->request
->status_text
);
528 This
->request
->status_text
= NULL
;
531 const WCHAR
*ptr
, *line
, *status_text
;
533 ptr
= line
= resp_headers
;
535 /* skip HTTP-Version */
536 ptr
= strchrW(ptr
, ' ');
539 /* skip Status-Code */
540 ptr
= strchrW(++ptr
, ' ');
544 /* now it supposed to end with CRLF */
547 if (*ptr
== '\r' && *(ptr
+1) == '\n')
550 This
->request
->status_text
= SysAllocStringLen(status_text
, ptr
-status_text
);
551 TRACE("status text %s\n", debugstr_w(This
->request
->status_text
));
559 /* store as unparsed string for now */
560 This
->request
->raw_respheaders
= SysAllocString(line
);
566 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl
= {
567 BSCHttpNegotiate_QueryInterface
,
568 BSCHttpNegotiate_AddRef
,
569 BSCHttpNegotiate_Release
,
570 BSCHttpNegotiate_BeginningTransaction
,
571 BSCHttpNegotiate_OnResponse
574 static HRESULT WINAPI
Authenticate_QueryInterface(IAuthenticate
*iface
,
575 REFIID riid
, void **ppv
)
577 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
578 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
581 static ULONG WINAPI
Authenticate_AddRef(IAuthenticate
*iface
)
583 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
584 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
587 static ULONG WINAPI
Authenticate_Release(IAuthenticate
*iface
)
589 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
590 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
593 static HRESULT WINAPI
Authenticate_Authenticate(IAuthenticate
*iface
,
594 HWND
*hwnd
, LPWSTR
*username
, LPWSTR
*password
)
596 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
597 httprequest
*request
= This
->request
;
599 TRACE("(%p)->(%p %p %p)\n", This
, hwnd
, username
, password
);
601 if (request
->user
&& *request
->user
)
603 if (hwnd
) *hwnd
= NULL
;
604 *username
= CoTaskMemAlloc(SysStringByteLen(request
->user
)+sizeof(WCHAR
));
605 *password
= CoTaskMemAlloc(SysStringByteLen(request
->password
)+sizeof(WCHAR
));
606 if (!*username
|| !*password
)
608 CoTaskMemFree(*username
);
609 CoTaskMemFree(*password
);
610 return E_OUTOFMEMORY
;
613 memcpy(*username
, request
->user
, SysStringByteLen(request
->user
)+sizeof(WCHAR
));
614 memcpy(*password
, request
->password
, SysStringByteLen(request
->password
)+sizeof(WCHAR
));
620 static const IAuthenticateVtbl AuthenticateVtbl
= {
621 Authenticate_QueryInterface
,
623 Authenticate_Release
,
624 Authenticate_Authenticate
627 static HRESULT
BindStatusCallback_create(httprequest
* This
, BindStatusCallback
**obj
, const VARIANT
*body
)
629 BindStatusCallback
*bsc
;
634 hr
= CreateBindCtx(0, &pbc
);
635 if (hr
!= S_OK
) return hr
;
637 bsc
= heap_alloc(sizeof(*bsc
));
640 IBindCtx_Release(pbc
);
641 return E_OUTOFMEMORY
;
644 bsc
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
645 bsc
->IHttpNegotiate_iface
.lpVtbl
= &BSCHttpNegotiateVtbl
;
646 bsc
->IAuthenticate_iface
.lpVtbl
= &AuthenticateVtbl
;
653 TRACE("(%p)->(%p)\n", This
, bsc
);
655 This
->use_utf8_content
= FALSE
;
657 if (This
->verb
!= BINDVERB_GET
)
659 void *send_data
, *ptr
;
660 SAFEARRAY
*sa
= NULL
;
662 if (V_VT(body
) == (VT_VARIANT
|VT_BYREF
))
663 body
= V_VARIANTREF(body
);
669 int len
= SysStringLen(V_BSTR(body
));
670 const WCHAR
*str
= V_BSTR(body
);
673 for (i
= 0; i
< len
; i
++)
682 size
= WideCharToMultiByte(cp
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
683 if (!(ptr
= heap_alloc(size
)))
686 return E_OUTOFMEMORY
;
688 WideCharToMultiByte(cp
, 0, str
, len
, ptr
, size
, NULL
, NULL
);
689 if (cp
== CP_UTF8
) This
->use_utf8_content
= TRUE
;
692 case VT_ARRAY
|VT_UI1
:
695 if ((hr
= SafeArrayAccessData(sa
, (void **)&ptr
)) != S_OK
)
700 if ((hr
= SafeArrayGetUBound(sa
, 1, &size
)) != S_OK
)
702 SafeArrayUnaccessData(sa
);
710 FIXME("unsupported body data type %d\n", V_VT(body
));
722 bsc
->body
= GlobalAlloc(GMEM_FIXED
, size
);
725 if (V_VT(body
) == VT_BSTR
)
727 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
728 SafeArrayUnaccessData(sa
);
731 return E_OUTOFMEMORY
;
734 send_data
= GlobalLock(bsc
->body
);
735 memcpy(send_data
, ptr
, size
);
736 GlobalUnlock(bsc
->body
);
739 if (V_VT(body
) == VT_BSTR
)
741 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
742 SafeArrayUnaccessData(sa
);
745 hr
= RegisterBindStatusCallback(pbc
, &bsc
->IBindStatusCallback_iface
, NULL
, 0);
750 hr
= CreateURLMonikerEx2(NULL
, This
->uri
, &moniker
, URL_MK_UNIFORM
);
755 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
756 IMoniker_Release(moniker
);
757 if (stream
) IStream_Release(stream
);
759 IBindCtx_Release(pbc
);
764 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
772 static HRESULT
verify_uri(httprequest
*This
, IUri
*uri
)
774 DWORD scheme
, base_scheme
;
775 BSTR host
, base_host
;
778 if(!(This
->safeopt
& INTERFACESAFE_FOR_UNTRUSTED_DATA
))
782 return E_ACCESSDENIED
;
784 hr
= IUri_GetScheme(uri
, &scheme
);
788 hr
= IUri_GetScheme(This
->base_uri
, &base_scheme
);
792 if(scheme
!= base_scheme
) {
793 WARN("Schemes don't match\n");
794 return E_ACCESSDENIED
;
797 if(scheme
== INTERNET_SCHEME_UNKNOWN
) {
798 FIXME("Unknown scheme\n");
799 return E_ACCESSDENIED
;
802 hr
= IUri_GetHost(uri
, &host
);
806 hr
= IUri_GetHost(This
->base_uri
, &base_host
);
808 if(strcmpiW(host
, base_host
)) {
809 WARN("Hosts don't match\n");
812 SysFreeString(base_host
);
819 static HRESULT
httprequest_open(httprequest
*This
, BSTR method
, BSTR url
,
820 VARIANT async
, VARIANT user
, VARIANT password
)
822 static const WCHAR MethodGetW
[] = {'G','E','T',0};
823 static const WCHAR MethodPutW
[] = {'P','U','T',0};
824 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
825 static const WCHAR MethodDeleteW
[] = {'D','E','L','E','T','E',0};
826 static const WCHAR MethodPropFindW
[] = {'P','R','O','P','F','I','N','D',0};
827 VARIANT str
, is_async
;
831 if (!method
|| !url
) return E_INVALIDARG
;
833 /* free previously set data */
835 IUri_Release(This
->uri
);
839 SysFreeString(This
->user
);
840 SysFreeString(This
->password
);
841 This
->user
= This
->password
= NULL
;
843 if (!strcmpiW(method
, MethodGetW
))
845 This
->verb
= BINDVERB_GET
;
847 else if (!strcmpiW(method
, MethodPutW
))
849 This
->verb
= BINDVERB_PUT
;
851 else if (!strcmpiW(method
, MethodPostW
))
853 This
->verb
= BINDVERB_POST
;
855 else if (!strcmpiW(method
, MethodDeleteW
) ||
856 !strcmpiW(method
, MethodPropFindW
))
858 This
->verb
= BINDVERB_CUSTOM
;
859 SysReAllocString(&This
->custom
, method
);
863 FIXME("unsupported request type %s\n", debugstr_w(method
));
869 hr
= CoInternetCombineUrlEx(This
->base_uri
, url
, 0, &uri
, 0);
871 hr
= CreateUri(url
, 0, 0, &uri
);
873 WARN("Could not create IUri object: %08x\n", hr
);
877 hr
= verify_uri(This
, uri
);
884 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
886 This
->user
= V_BSTR(&str
);
889 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
891 This
->password
= V_BSTR(&str
);
893 /* add authentication info */
894 if (This
->user
&& *This
->user
)
896 IUriBuilder
*builder
;
898 hr
= CreateIUriBuilder(uri
, 0, 0, &builder
);
903 IUriBuilder_SetUserName(builder
, This
->user
);
904 IUriBuilder_SetPassword(builder
, This
->password
);
905 hr
= IUriBuilder_CreateUri(builder
, -1, 0, 0, &full_uri
);
912 WARN("failed to create modified uri, 0x%08x\n", hr
);
913 IUriBuilder_Release(builder
);
916 WARN("IUriBuilder creation failed, 0x%08x\n", hr
);
921 VariantInit(&is_async
);
922 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
923 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
);
925 httprequest_setreadystate(This
, READYSTATE_LOADING
);
930 static HRESULT
httprequest_setRequestHeader(httprequest
*This
, BSTR header
, BSTR value
)
932 struct httpheader
*entry
;
934 if (!header
|| !*header
) return E_INVALIDARG
;
935 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
936 if (!value
) return E_INVALIDARG
;
938 /* replace existing header value if already added */
939 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct httpheader
, entry
)
941 if (lstrcmpW(entry
->header
, header
) == 0)
943 LONG length
= SysStringLen(entry
->value
);
946 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
949 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
955 entry
= heap_alloc(sizeof(*entry
));
956 if (!entry
) return E_OUTOFMEMORY
;
959 entry
->header
= SysAllocString(header
);
960 entry
->value
= SysAllocString(value
);
962 /* header length including null terminator */
963 This
->reqheader_size
+= SysStringLen(entry
->header
) + sizeof(colspaceW
)/sizeof(WCHAR
) +
964 SysStringLen(entry
->value
) + sizeof(crlfW
)/sizeof(WCHAR
) - 1;
966 list_add_head(&This
->reqheaders
, &entry
->entry
);
971 static HRESULT
httprequest_getResponseHeader(httprequest
*This
, BSTR header
, BSTR
*value
)
973 struct httpheader
*entry
;
975 if (!header
) return E_INVALIDARG
;
976 if (!value
) return E_POINTER
;
978 if (This
->raw_respheaders
&& list_empty(&This
->respheaders
))
982 ptr
= line
= This
->raw_respheaders
;
985 if (*ptr
== '\r' && *(ptr
+1) == '\n')
987 add_response_header(This
, line
, ptr
-line
);
995 LIST_FOR_EACH_ENTRY(entry
, &This
->respheaders
, struct httpheader
, entry
)
997 if (!strcmpiW(entry
->header
, header
))
999 *value
= SysAllocString(entry
->value
);
1000 TRACE("header value %s\n", debugstr_w(*value
));
1008 static HRESULT
httprequest_getAllResponseHeaders(httprequest
*This
, BSTR
*respheaders
)
1010 if (!respheaders
) return E_POINTER
;
1012 *respheaders
= SysAllocString(This
->raw_respheaders
);
1017 static HRESULT
httprequest_send(httprequest
*This
, VARIANT body
)
1019 BindStatusCallback
*bsc
= NULL
;
1022 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
1024 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
1026 /* success path to detach it is OnStopBinding call */
1027 BindStatusCallback_Detach(bsc
);
1032 static HRESULT
httprequest_abort(httprequest
*This
)
1034 BindStatusCallback_Detach(This
->bsc
);
1036 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
1041 static HRESULT
httprequest_get_status(httprequest
*This
, LONG
*status
)
1043 if (!status
) return E_POINTER
;
1045 *status
= This
->status
;
1047 return This
->state
== READYSTATE_COMPLETE
? S_OK
: E_FAIL
;
1050 static HRESULT
httprequest_get_statusText(httprequest
*This
, BSTR
*status
)
1052 if (!status
) return E_POINTER
;
1053 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1055 *status
= SysAllocString(This
->status_text
);
1060 static HRESULT
httprequest_get_responseText(httprequest
*This
, BSTR
*body
)
1065 if (!body
) return E_POINTER
;
1066 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1068 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1071 xmlChar
*ptr
= GlobalLock(hglobal
);
1072 DWORD size
= GlobalSize(hglobal
);
1073 xmlCharEncoding encoding
= XML_CHAR_ENCODING_UTF8
;
1075 /* try to determine data encoding */
1078 encoding
= xmlDetectCharEncoding(ptr
, 4);
1079 TRACE("detected encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1080 if ( encoding
!= XML_CHAR_ENCODING_UTF8
&&
1081 encoding
!= XML_CHAR_ENCODING_UTF16LE
&&
1082 encoding
!= XML_CHAR_ENCODING_NONE
)
1084 FIXME("unsupported encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1085 GlobalUnlock(hglobal
);
1090 /* without BOM assume UTF-8 */
1091 if (encoding
== XML_CHAR_ENCODING_UTF8
||
1092 encoding
== XML_CHAR_ENCODING_NONE
)
1094 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)ptr
, size
, NULL
, 0);
1096 *body
= SysAllocStringLen(NULL
, length
);
1098 MultiByteToWideChar( CP_UTF8
, 0, (LPCSTR
)ptr
, size
, *body
, length
);
1101 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
1103 if (!*body
) hr
= E_OUTOFMEMORY
;
1104 GlobalUnlock(hglobal
);
1110 static HRESULT
httprequest_get_responseXML(httprequest
*This
, IDispatch
**body
)
1112 IXMLDOMDocument3
*doc
;
1116 if (!body
) return E_INVALIDARG
;
1117 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1119 hr
= DOMDocument_create(MSXML_DEFAULT
, NULL
, (void**)&doc
);
1120 if (hr
!= S_OK
) return hr
;
1122 hr
= httprequest_get_responseText(This
, &str
);
1127 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
1131 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
1132 IXMLDOMDocument3_Release(doc
);
1137 static HRESULT
httprequest_get_responseBody(httprequest
*This
, VARIANT
*body
)
1142 if (!body
) return E_INVALIDARG
;
1143 V_VT(body
) = VT_EMPTY
;
1145 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1147 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1150 void *ptr
= GlobalLock(hglobal
);
1151 DWORD size
= GlobalSize(hglobal
);
1153 SAFEARRAYBOUND bound
;
1157 bound
.cElements
= size
;
1158 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
1164 V_VT(body
) = VT_ARRAY
| VT_UI1
;
1165 V_ARRAY(body
) = array
;
1167 hr
= SafeArrayAccessData(array
, &dest
);
1170 memcpy(dest
, ptr
, size
);
1171 SafeArrayUnaccessData(array
);
1181 GlobalUnlock(hglobal
);
1187 static HRESULT
httprequest_get_responseStream(httprequest
*This
, VARIANT
*body
)
1193 if (!body
) return E_INVALIDARG
;
1194 V_VT(body
) = VT_EMPTY
;
1196 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1198 hr
= IStream_Clone(This
->bsc
->stream
, &stream
);
1201 IStream_Seek(stream
, move
, STREAM_SEEK_SET
, NULL
);
1203 V_VT(body
) = VT_UNKNOWN
;
1204 V_UNKNOWN(body
) = (IUnknown
*)stream
;
1209 static HRESULT
httprequest_get_readyState(httprequest
*This
, LONG
*state
)
1211 if (!state
) return E_POINTER
;
1213 *state
= This
->state
;
1217 static HRESULT
httprequest_put_onreadystatechange(httprequest
*This
, IDispatch
*sink
)
1219 if (This
->sink
) IDispatch_Release(This
->sink
);
1220 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1225 static void httprequest_release(httprequest
*This
)
1227 struct httpheader
*header
, *header2
;
1230 IUnknown_Release( This
->site
);
1232 IUri_Release(This
->uri
);
1234 IUri_Release(This
->base_uri
);
1236 SysFreeString(This
->custom
);
1237 SysFreeString(This
->user
);
1238 SysFreeString(This
->password
);
1240 /* request headers */
1241 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->reqheaders
, struct httpheader
, entry
)
1243 list_remove(&header
->entry
);
1244 SysFreeString(header
->header
);
1245 SysFreeString(header
->value
);
1248 /* response headers */
1249 free_response_headers(This
);
1250 SysFreeString(This
->status_text
);
1252 /* detach callback object */
1253 BindStatusCallback_Detach(This
->bsc
);
1255 if (This
->sink
) IDispatch_Release(This
->sink
);
1258 static HRESULT WINAPI
XMLHTTPRequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
1260 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1261 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1263 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1264 IsEqualGUID( riid
, &IID_IDispatch
) ||
1265 IsEqualGUID( riid
, &IID_IUnknown
) )
1269 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
1271 *ppvObject
= &This
->IObjectWithSite_iface
;
1273 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
1275 *ppvObject
= &This
->IObjectSafety_iface
;
1279 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1281 return E_NOINTERFACE
;
1284 IXMLHTTPRequest_AddRef( iface
);
1289 static ULONG WINAPI
XMLHTTPRequest_AddRef(IXMLHTTPRequest
*iface
)
1291 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1292 ULONG ref
= InterlockedIncrement( &This
->ref
);
1293 TRACE("(%p)->(%u)\n", This
, ref
);
1297 static ULONG WINAPI
XMLHTTPRequest_Release(IXMLHTTPRequest
*iface
)
1299 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1300 ULONG ref
= InterlockedDecrement( &This
->ref
);
1302 TRACE("(%p)->(%u)\n", This
, ref
);
1306 httprequest_release( This
);
1313 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1315 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1317 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1324 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
1325 LCID lcid
, ITypeInfo
**ppTInfo
)
1327 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1329 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1331 return get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
1334 static HRESULT WINAPI
XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
1335 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1337 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1338 ITypeInfo
*typeinfo
;
1341 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1344 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1345 return E_INVALIDARG
;
1347 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1350 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1351 ITypeInfo_Release(typeinfo
);
1357 static HRESULT WINAPI
XMLHTTPRequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1358 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1359 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1361 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1362 ITypeInfo
*typeinfo
;
1365 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1366 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1368 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1371 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1372 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1373 ITypeInfo_Release(typeinfo
);
1379 static HRESULT WINAPI
XMLHTTPRequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1380 VARIANT async
, VARIANT user
, VARIANT password
)
1382 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1383 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1384 debugstr_variant(&async
));
1385 return httprequest_open(This
, method
, url
, async
, user
, password
);
1388 static HRESULT WINAPI
XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1390 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1391 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1392 return httprequest_setRequestHeader(This
, header
, value
);
1395 static HRESULT WINAPI
XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1397 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1398 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1399 return httprequest_getResponseHeader(This
, header
, value
);
1402 static HRESULT WINAPI
XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1404 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1405 TRACE("(%p)->(%p)\n", This
, respheaders
);
1406 return httprequest_getAllResponseHeaders(This
, respheaders
);
1409 static HRESULT WINAPI
XMLHTTPRequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
1411 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1412 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1413 return httprequest_send(This
, body
);
1416 static HRESULT WINAPI
XMLHTTPRequest_abort(IXMLHTTPRequest
*iface
)
1418 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1419 TRACE("(%p)\n", This
);
1420 return httprequest_abort(This
);
1423 static HRESULT WINAPI
XMLHTTPRequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
1425 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1426 TRACE("(%p)->(%p)\n", This
, status
);
1427 return httprequest_get_status(This
, status
);
1430 static HRESULT WINAPI
XMLHTTPRequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*status
)
1432 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1433 TRACE("(%p)->(%p)\n", This
, status
);
1434 return httprequest_get_statusText(This
, status
);
1437 static HRESULT WINAPI
XMLHTTPRequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
1439 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1440 TRACE("(%p)->(%p)\n", This
, body
);
1441 return httprequest_get_responseXML(This
, body
);
1444 static HRESULT WINAPI
XMLHTTPRequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
1446 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1447 TRACE("(%p)->(%p)\n", This
, body
);
1448 return httprequest_get_responseText(This
, body
);
1451 static HRESULT WINAPI
XMLHTTPRequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1453 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1454 TRACE("(%p)->(%p)\n", This
, body
);
1455 return httprequest_get_responseBody(This
, body
);
1458 static HRESULT WINAPI
XMLHTTPRequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1460 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1461 TRACE("(%p)->(%p)\n", This
, body
);
1462 return httprequest_get_responseStream(This
, body
);
1465 static HRESULT WINAPI
XMLHTTPRequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
1467 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1468 TRACE("(%p)->(%p)\n", This
, state
);
1469 return httprequest_get_readyState(This
, state
);
1472 static HRESULT WINAPI
XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
1474 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1475 TRACE("(%p)->(%p)\n", This
, sink
);
1476 return httprequest_put_onreadystatechange(This
, sink
);
1479 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl
=
1481 XMLHTTPRequest_QueryInterface
,
1482 XMLHTTPRequest_AddRef
,
1483 XMLHTTPRequest_Release
,
1484 XMLHTTPRequest_GetTypeInfoCount
,
1485 XMLHTTPRequest_GetTypeInfo
,
1486 XMLHTTPRequest_GetIDsOfNames
,
1487 XMLHTTPRequest_Invoke
,
1488 XMLHTTPRequest_open
,
1489 XMLHTTPRequest_setRequestHeader
,
1490 XMLHTTPRequest_getResponseHeader
,
1491 XMLHTTPRequest_getAllResponseHeaders
,
1492 XMLHTTPRequest_send
,
1493 XMLHTTPRequest_abort
,
1494 XMLHTTPRequest_get_status
,
1495 XMLHTTPRequest_get_statusText
,
1496 XMLHTTPRequest_get_responseXML
,
1497 XMLHTTPRequest_get_responseText
,
1498 XMLHTTPRequest_get_responseBody
,
1499 XMLHTTPRequest_get_responseStream
,
1500 XMLHTTPRequest_get_readyState
,
1501 XMLHTTPRequest_put_onreadystatechange
1504 /* IObjectWithSite */
1505 static HRESULT WINAPI
1506 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1508 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1509 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest
*)This
, riid
, ppvObject
);
1512 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1514 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1515 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest
*)This
);
1518 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1520 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1521 return IXMLHTTPRequest_Release((IXMLHTTPRequest
*)This
);
1524 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1526 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1528 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1533 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1536 static void get_base_uri(httprequest
*This
)
1538 IServiceProvider
*provider
;
1539 IHTMLDocument2
*doc
;
1544 hr
= IUnknown_QueryInterface(This
->site
, &IID_IServiceProvider
, (void**)&provider
);
1548 hr
= IServiceProvider_QueryService(provider
, &SID_SContainerDispatch
, &IID_IHTMLDocument2
, (void**)&doc
);
1549 IServiceProvider_Release(provider
);
1553 hr
= IHTMLDocument2_get_URL(doc
, &url
);
1554 IHTMLDocument2_Release(doc
);
1555 if(FAILED(hr
) || !url
|| !*url
)
1558 TRACE("host url %s\n", debugstr_w(url
));
1560 hr
= CreateUri(url
, 0, 0, &uri
);
1565 This
->base_uri
= uri
;
1568 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1570 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1572 TRACE("(%p)->(%p)\n", This
, punk
);
1575 IUnknown_Release( This
->site
);
1577 IUri_Release(This
->base_uri
);
1583 IUnknown_AddRef( punk
);
1590 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1592 httprequest_ObjectWithSite_QueryInterface
,
1593 httprequest_ObjectWithSite_AddRef
,
1594 httprequest_ObjectWithSite_Release
,
1595 httprequest_ObjectWithSite_SetSite
,
1596 httprequest_ObjectWithSite_GetSite
1600 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1602 httprequest
*This
= impl_from_IObjectSafety(iface
);
1603 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest
*)This
, riid
, ppv
);
1606 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1608 httprequest
*This
= impl_from_IObjectSafety(iface
);
1609 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest
*)This
);
1612 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1614 httprequest
*This
= impl_from_IObjectSafety(iface
);
1615 return IXMLHTTPRequest_Release((IXMLHTTPRequest
*)This
);
1618 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1619 DWORD
*supported
, DWORD
*enabled
)
1621 httprequest
*This
= impl_from_IObjectSafety(iface
);
1623 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1625 if(!supported
|| !enabled
) return E_POINTER
;
1627 *supported
= safety_supported_options
;
1628 *enabled
= This
->safeopt
;
1633 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1634 DWORD mask
, DWORD enabled
)
1636 httprequest
*This
= impl_from_IObjectSafety(iface
);
1637 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
1639 if ((mask
& ~safety_supported_options
))
1642 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
1647 static const IObjectSafetyVtbl ObjectSafetyVtbl
= {
1648 httprequest_Safety_QueryInterface
,
1649 httprequest_Safety_AddRef
,
1650 httprequest_Safety_Release
,
1651 httprequest_Safety_GetInterfaceSafetyOptions
,
1652 httprequest_Safety_SetInterfaceSafetyOptions
1655 /* IServerXMLHTTPRequest */
1656 static HRESULT WINAPI
ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest
*iface
, REFIID riid
, void **obj
)
1658 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1660 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1662 if ( IsEqualGUID( riid
, &IID_IServerXMLHTTPRequest
) ||
1663 IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1664 IsEqualGUID( riid
, &IID_IDispatch
) ||
1665 IsEqualGUID( riid
, &IID_IUnknown
) )
1671 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1673 return E_NOINTERFACE
;
1676 IServerXMLHTTPRequest_AddRef( iface
);
1681 static ULONG WINAPI
ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest
*iface
)
1683 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1684 ULONG ref
= InterlockedIncrement( &This
->ref
);
1685 TRACE("(%p)->(%u)\n", This
, ref
);
1689 static ULONG WINAPI
ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest
*iface
)
1691 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1692 ULONG ref
= InterlockedDecrement( &This
->ref
);
1694 TRACE("(%p)->(%u)\n", This
, ref
);
1698 httprequest_release( &This
->req
);
1705 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1707 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1709 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1715 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest
*iface
, UINT iTInfo
,
1716 LCID lcid
, ITypeInfo
**ppTInfo
)
1718 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1720 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1722 return get_typeinfo(IServerXMLHTTPRequest_tid
, ppTInfo
);
1725 static HRESULT WINAPI
ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest
*iface
, REFIID riid
,
1726 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1728 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1729 ITypeInfo
*typeinfo
;
1732 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1735 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1736 return E_INVALIDARG
;
1738 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1741 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1742 ITypeInfo_Release(typeinfo
);
1748 static HRESULT WINAPI
ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1749 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1750 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1752 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1753 ITypeInfo
*typeinfo
;
1756 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1757 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1759 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1762 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IServerXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1763 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1764 ITypeInfo_Release(typeinfo
);
1770 static HRESULT WINAPI
ServerXMLHTTPRequest_open(IServerXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1771 VARIANT async
, VARIANT user
, VARIANT password
)
1773 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1774 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1775 debugstr_variant(&async
));
1776 return httprequest_open(&This
->req
, method
, url
, async
, user
, password
);
1779 static HRESULT WINAPI
ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1781 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1782 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1783 return httprequest_setRequestHeader(&This
->req
, header
, value
);
1786 static HRESULT WINAPI
ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1788 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1789 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1790 return httprequest_getResponseHeader(&This
->req
, header
, value
);
1793 static HRESULT WINAPI
ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1795 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1796 TRACE("(%p)->(%p)\n", This
, respheaders
);
1797 return httprequest_getAllResponseHeaders(&This
->req
, respheaders
);
1800 static HRESULT WINAPI
ServerXMLHTTPRequest_send(IServerXMLHTTPRequest
*iface
, VARIANT body
)
1802 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1803 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1804 return httprequest_send(&This
->req
, body
);
1807 static HRESULT WINAPI
ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest
*iface
)
1809 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1810 TRACE("(%p)\n", This
);
1811 return httprequest_abort(&This
->req
);
1814 static HRESULT WINAPI
ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest
*iface
, LONG
*status
)
1816 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1817 TRACE("(%p)->(%p)\n", This
, status
);
1818 return httprequest_get_status(&This
->req
, status
);
1821 static HRESULT WINAPI
ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest
*iface
, BSTR
*status
)
1823 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1824 TRACE("(%p)->(%p)\n", This
, status
);
1825 return httprequest_get_statusText(&This
->req
, status
);
1828 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest
*iface
, IDispatch
**body
)
1830 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1831 TRACE("(%p)->(%p)\n", This
, body
);
1832 return httprequest_get_responseXML(&This
->req
, body
);
1835 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest
*iface
, BSTR
*body
)
1837 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1838 TRACE("(%p)->(%p)\n", This
, body
);
1839 return httprequest_get_responseText(&This
->req
, body
);
1842 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1844 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1845 TRACE("(%p)->(%p)\n", This
, body
);
1846 return httprequest_get_responseBody(&This
->req
, body
);
1849 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1851 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1852 TRACE("(%p)->(%p)\n", This
, body
);
1853 return httprequest_get_responseStream(&This
->req
, body
);
1856 static HRESULT WINAPI
ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest
*iface
, LONG
*state
)
1858 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1859 TRACE("(%p)->(%p)\n", This
, state
);
1860 return httprequest_get_readyState(&This
->req
, state
);
1863 static HRESULT WINAPI
ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest
*iface
, IDispatch
*sink
)
1865 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1866 TRACE("(%p)->(%p)\n", This
, sink
);
1867 return httprequest_put_onreadystatechange(&This
->req
, sink
);
1870 static HRESULT WINAPI
ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest
*iface
, LONG resolveTimeout
, LONG connectTimeout
,
1871 LONG sendTimeout
, LONG receiveTimeout
)
1873 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1874 FIXME("(%p)->(%d %d %d %d): stub\n", This
, resolveTimeout
, connectTimeout
, sendTimeout
, receiveTimeout
);
1878 static HRESULT WINAPI
ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest
*iface
, VARIANT timeout
, VARIANT_BOOL
*isSuccessful
)
1880 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1881 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_variant(&timeout
), isSuccessful
);
1885 static HRESULT WINAPI
ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT
*value
)
1887 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1888 FIXME("(%p)->(%d %p): stub\n", This
, option
, value
);
1892 static HRESULT WINAPI
ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT value
)
1894 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1895 FIXME("(%p)->(%d %s): stub\n", This
, option
, debugstr_variant(&value
));
1899 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl
=
1901 ServerXMLHTTPRequest_QueryInterface
,
1902 ServerXMLHTTPRequest_AddRef
,
1903 ServerXMLHTTPRequest_Release
,
1904 ServerXMLHTTPRequest_GetTypeInfoCount
,
1905 ServerXMLHTTPRequest_GetTypeInfo
,
1906 ServerXMLHTTPRequest_GetIDsOfNames
,
1907 ServerXMLHTTPRequest_Invoke
,
1908 ServerXMLHTTPRequest_open
,
1909 ServerXMLHTTPRequest_setRequestHeader
,
1910 ServerXMLHTTPRequest_getResponseHeader
,
1911 ServerXMLHTTPRequest_getAllResponseHeaders
,
1912 ServerXMLHTTPRequest_send
,
1913 ServerXMLHTTPRequest_abort
,
1914 ServerXMLHTTPRequest_get_status
,
1915 ServerXMLHTTPRequest_get_statusText
,
1916 ServerXMLHTTPRequest_get_responseXML
,
1917 ServerXMLHTTPRequest_get_responseText
,
1918 ServerXMLHTTPRequest_get_responseBody
,
1919 ServerXMLHTTPRequest_get_responseStream
,
1920 ServerXMLHTTPRequest_get_readyState
,
1921 ServerXMLHTTPRequest_put_onreadystatechange
,
1922 ServerXMLHTTPRequest_setTimeouts
,
1923 ServerXMLHTTPRequest_waitForResponse
,
1924 ServerXMLHTTPRequest_getOption
,
1925 ServerXMLHTTPRequest_setOption
1928 static void init_httprequest(httprequest
*req
)
1930 req
->IXMLHTTPRequest_iface
.lpVtbl
= &XMLHTTPRequestVtbl
;
1931 req
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
1932 req
->IObjectSafety_iface
.lpVtbl
= &ObjectSafetyVtbl
;
1938 req
->uri
= req
->base_uri
= NULL
;
1939 req
->user
= req
->password
= NULL
;
1941 req
->state
= READYSTATE_UNINITIALIZED
;
1946 req
->status_text
= NULL
;
1947 req
->reqheader_size
= 0;
1948 req
->raw_respheaders
= NULL
;
1949 req
->use_utf8_content
= FALSE
;
1951 list_init(&req
->reqheaders
);
1952 list_init(&req
->respheaders
);
1958 HRESULT
XMLHTTPRequest_create(IUnknown
*outer
, void **obj
)
1962 TRACE("(%p, %p)\n", outer
, obj
);
1964 req
= heap_alloc( sizeof (*req
) );
1966 return E_OUTOFMEMORY
;
1968 init_httprequest(req
);
1969 *obj
= &req
->IXMLHTTPRequest_iface
;
1971 TRACE("returning iface %p\n", *obj
);
1976 HRESULT
ServerXMLHTTP_create(IUnknown
*outer
, void **obj
)
1980 TRACE("(%p, %p)\n", outer
, obj
);
1982 req
= heap_alloc( sizeof (*req
) );
1984 return E_OUTOFMEMORY
;
1986 init_httprequest(&req
->req
);
1987 req
->IServerXMLHTTPRequest_iface
.lpVtbl
= &ServerXMLHTTPRequestVtbl
;
1990 *obj
= &req
->IServerXMLHTTPRequest_iface
;
1992 TRACE("returning iface %p\n", *obj
);
1999 HRESULT
XMLHTTPRequest_create(IUnknown
*pUnkOuter
, void **ppObj
)
2001 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
2002 "libxml2 support was not present at compile time.\n");
2006 HRESULT
ServerXMLHTTP_create(IUnknown
*outer
, void **obj
)
2008 MESSAGE("This program tried to use a ServerXMLHTTP object, but\n"
2009 "libxml2 support was not present at compile time.\n");