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
;
95 static inline httprequest
*impl_from_IXMLHTTPRequest( IXMLHTTPRequest
*iface
)
97 return CONTAINING_RECORD(iface
, httprequest
, IXMLHTTPRequest_iface
);
100 static inline httprequest
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
102 return CONTAINING_RECORD(iface
, httprequest
, IObjectWithSite_iface
);
105 static inline httprequest
*impl_from_IObjectSafety(IObjectSafety
*iface
)
107 return CONTAINING_RECORD(iface
, httprequest
, IObjectSafety_iface
);
110 static inline serverhttp
*impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest
*iface
)
112 return CONTAINING_RECORD(iface
, serverhttp
, IServerXMLHTTPRequest_iface
);
115 static void httprequest_setreadystate(httprequest
*This
, READYSTATE state
)
117 READYSTATE last
= This
->state
;
118 static const char* readystates
[] = {
119 "READYSTATE_UNINITIALIZED",
120 "READYSTATE_LOADING",
122 "READYSTATE_INTERACTIVE",
123 "READYSTATE_COMPLETE"};
127 TRACE("state %s\n", readystates
[state
]);
129 if (This
->sink
&& last
!= state
)
133 memset(¶ms
, 0, sizeof(params
));
134 IDispatch_Invoke(This
->sink
, 0, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, ¶ms
, 0, 0, 0);
138 static void free_response_headers(httprequest
*This
)
140 struct httpheader
*header
, *header2
;
142 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->respheaders
, struct httpheader
, entry
)
144 list_remove(&header
->entry
);
145 SysFreeString(header
->header
);
146 SysFreeString(header
->value
);
150 SysFreeString(This
->raw_respheaders
);
151 This
->raw_respheaders
= NULL
;
154 static void free_request_headers(httprequest
*This
)
156 struct httpheader
*header
, *header2
;
158 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->reqheaders
, struct httpheader
, entry
)
160 list_remove(&header
->entry
);
161 SysFreeString(header
->header
);
162 SysFreeString(header
->value
);
167 struct BindStatusCallback
169 IBindStatusCallback IBindStatusCallback_iface
;
170 IHttpNegotiate IHttpNegotiate_iface
;
171 IAuthenticate IAuthenticate_iface
;
175 httprequest
*request
;
180 /* request body data */
184 static inline BindStatusCallback
*impl_from_IBindStatusCallback( IBindStatusCallback
*iface
)
186 return CONTAINING_RECORD(iface
, BindStatusCallback
, IBindStatusCallback_iface
);
189 static inline BindStatusCallback
*impl_from_IHttpNegotiate( IHttpNegotiate
*iface
)
191 return CONTAINING_RECORD(iface
, BindStatusCallback
, IHttpNegotiate_iface
);
194 static inline BindStatusCallback
*impl_from_IAuthenticate( IAuthenticate
*iface
)
196 return CONTAINING_RECORD(iface
, BindStatusCallback
, IAuthenticate_iface
);
199 static void BindStatusCallback_Detach(BindStatusCallback
*bsc
)
203 if (bsc
->binding
) IBinding_Abort(bsc
->binding
);
204 bsc
->request
->bsc
= NULL
;
206 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
210 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
211 REFIID riid
, void **ppv
)
213 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
217 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
219 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
220 IsEqualGUID(&IID_IBindStatusCallback
, riid
))
222 *ppv
= &This
->IBindStatusCallback_iface
;
224 else if (IsEqualGUID(&IID_IHttpNegotiate
, riid
))
226 *ppv
= &This
->IHttpNegotiate_iface
;
228 else if (IsEqualGUID(&IID_IAuthenticate
, riid
))
230 *ppv
= &This
->IAuthenticate_iface
;
232 else if (IsEqualGUID(&IID_IServiceProvider
, riid
) ||
233 IsEqualGUID(&IID_IBindStatusCallbackEx
, riid
) ||
234 IsEqualGUID(&IID_IInternetProtocol
, riid
) ||
235 IsEqualGUID(&IID_IHttpNegotiate2
, riid
))
237 return E_NOINTERFACE
;
242 IBindStatusCallback_AddRef(iface
);
246 FIXME("Unsupported riid = %s\n", debugstr_guid(riid
));
248 return E_NOINTERFACE
;
251 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
253 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
254 LONG ref
= InterlockedIncrement(&This
->ref
);
256 TRACE("(%p) ref = %d\n", This
, ref
);
261 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
263 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
264 LONG ref
= InterlockedDecrement(&This
->ref
);
266 TRACE("(%p) ref = %d\n", This
, ref
);
270 if (This
->binding
) IBinding_Release(This
->binding
);
271 if (This
->stream
) IStream_Release(This
->stream
);
272 if (This
->body
) GlobalFree(This
->body
);
279 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
280 DWORD reserved
, IBinding
*pbind
)
282 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
284 TRACE("(%p)->(%d %p)\n", This
, reserved
, pbind
);
286 if (!pbind
) return E_INVALIDARG
;
288 This
->binding
= pbind
;
289 IBinding_AddRef(pbind
);
291 httprequest_setreadystate(This
->request
, READYSTATE_LOADED
);
293 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
296 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pPriority
)
298 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
300 TRACE("(%p)->(%p)\n", This
, pPriority
);
305 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
307 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
309 TRACE("(%p)->(%d)\n", This
, reserved
);
314 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
315 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
317 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
319 TRACE("(%p)->(%u %u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
320 debugstr_w(szStatusText
));
325 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
326 HRESULT hr
, LPCWSTR error
)
328 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
330 TRACE("(%p)->(0x%08x %s)\n", This
, hr
, debugstr_w(error
));
334 IBinding_Release(This
->binding
);
335 This
->binding
= NULL
;
340 BindStatusCallback_Detach(This
->request
->bsc
);
341 This
->request
->bsc
= This
;
342 httprequest_setreadystate(This
->request
, READYSTATE_COMPLETE
);
348 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
349 DWORD
*bind_flags
, BINDINFO
*pbindinfo
)
351 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
353 TRACE("(%p)->(%p %p)\n", This
, bind_flags
, pbindinfo
);
356 if (This
->request
->async
) *bind_flags
|= BINDF_ASYNCHRONOUS
;
358 if (This
->request
->verb
!= BINDVERB_GET
&& This
->body
)
360 pbindinfo
->stgmedData
.tymed
= TYMED_HGLOBAL
;
361 pbindinfo
->stgmedData
.u
.hGlobal
= This
->body
;
362 pbindinfo
->cbstgmedData
= GlobalSize(This
->body
);
363 /* callback owns passed body pointer */
364 IBindStatusCallback_QueryInterface(iface
, &IID_IUnknown
, (void**)&pbindinfo
->stgmedData
.pUnkForRelease
);
367 pbindinfo
->dwBindVerb
= This
->request
->verb
;
368 if (This
->request
->verb
== BINDVERB_CUSTOM
)
370 pbindinfo
->szCustomVerb
= CoTaskMemAlloc(SysStringByteLen(This
->request
->custom
));
371 strcpyW(pbindinfo
->szCustomVerb
, This
->request
->custom
);
377 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
378 DWORD flags
, DWORD size
, FORMATETC
*format
, STGMEDIUM
*stgmed
)
380 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
385 TRACE("(%p)->(%08x %d %p %p)\n", This
, flags
, size
, format
, stgmed
);
389 hr
= IStream_Read(stgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
390 if (hr
!= S_OK
) break;
392 hr
= IStream_Write(This
->stream
, buf
, read
, &written
);
393 } while((hr
== S_OK
) && written
!= 0 && read
!= 0);
395 httprequest_setreadystate(This
->request
, READYSTATE_INTERACTIVE
);
400 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
401 REFIID riid
, IUnknown
*punk
)
403 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
405 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
410 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
411 BindStatusCallback_QueryInterface
,
412 BindStatusCallback_AddRef
,
413 BindStatusCallback_Release
,
414 BindStatusCallback_OnStartBinding
,
415 BindStatusCallback_GetPriority
,
416 BindStatusCallback_OnLowResource
,
417 BindStatusCallback_OnProgress
,
418 BindStatusCallback_OnStopBinding
,
419 BindStatusCallback_GetBindInfo
,
420 BindStatusCallback_OnDataAvailable
,
421 BindStatusCallback_OnObjectAvailable
424 static HRESULT WINAPI
BSCHttpNegotiate_QueryInterface(IHttpNegotiate
*iface
,
425 REFIID riid
, void **ppv
)
427 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
428 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
431 static ULONG WINAPI
BSCHttpNegotiate_AddRef(IHttpNegotiate
*iface
)
433 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
434 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
437 static ULONG WINAPI
BSCHttpNegotiate_Release(IHttpNegotiate
*iface
)
439 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
440 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
443 static HRESULT WINAPI
BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate
*iface
,
444 LPCWSTR url
, LPCWSTR headers
, DWORD reserved
, LPWSTR
*add_headers
)
446 static const WCHAR content_type_utf8W
[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
447 't','e','x','t','/','p','l','a','i','n',';','c','h','a','r','s','e','t','=','u','t','f','-','8','\r','\n',0};
448 static const WCHAR refererW
[] = {'R','e','f','e','r','e','r',':',' ',0};
450 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
451 const struct httpheader
*entry
;
452 BSTR base_uri
= NULL
;
456 TRACE("(%p)->(%s %s %d %p)\n", This
, debugstr_w(url
), debugstr_w(headers
), reserved
, add_headers
);
460 if (This
->request
->use_utf8_content
)
461 size
= sizeof(content_type_utf8W
);
463 if (!list_empty(&This
->request
->reqheaders
))
464 size
+= This
->request
->reqheader_size
*sizeof(WCHAR
);
466 if (This
->request
->base_uri
)
468 IUri_GetRawUri(This
->request
->base_uri
, &base_uri
);
469 size
+= SysStringLen(base_uri
)*sizeof(WCHAR
) + sizeof(refererW
) + sizeof(crlfW
);
474 SysFreeString(base_uri
);
478 buff
= CoTaskMemAlloc(size
);
481 SysFreeString(base_uri
);
482 return E_OUTOFMEMORY
;
486 if (This
->request
->use_utf8_content
)
488 lstrcpyW(ptr
, content_type_utf8W
);
489 ptr
+= sizeof(content_type_utf8W
)/sizeof(WCHAR
)-1;
494 strcpyW(ptr
, refererW
);
495 strcatW(ptr
, base_uri
);
497 ptr
+= strlenW(refererW
) + SysStringLen(base_uri
) + strlenW(crlfW
);
498 SysFreeString(base_uri
);
502 LIST_FOR_EACH_ENTRY(entry
, &This
->request
->reqheaders
, struct httpheader
, entry
)
504 lstrcpyW(ptr
, entry
->header
);
505 ptr
+= SysStringLen(entry
->header
);
507 lstrcpyW(ptr
, colspaceW
);
508 ptr
+= sizeof(colspaceW
)/sizeof(WCHAR
)-1;
510 lstrcpyW(ptr
, entry
->value
);
511 ptr
+= SysStringLen(entry
->value
);
513 lstrcpyW(ptr
, crlfW
);
514 ptr
+= sizeof(crlfW
)/sizeof(WCHAR
)-1;
522 static void add_response_header(httprequest
*This
, const WCHAR
*data
, int len
)
524 struct httpheader
*entry
;
525 const WCHAR
*ptr
= data
;
532 header
= SysAllocStringLen(data
, ptr
-data
);
533 /* skip leading spaces for a value */
534 while (*++ptr
== ' ')
536 value
= SysAllocStringLen(ptr
, len
-(ptr
-data
));
545 TRACE("got header %s:%s\n", debugstr_w(header
), debugstr_w(value
));
547 entry
= heap_alloc(sizeof(*entry
));
548 entry
->header
= header
;
549 entry
->value
= value
;
550 list_add_head(&This
->respheaders
, &entry
->entry
);
553 static HRESULT WINAPI
BSCHttpNegotiate_OnResponse(IHttpNegotiate
*iface
, DWORD code
,
554 LPCWSTR resp_headers
, LPCWSTR req_headers
, LPWSTR
*add_reqheaders
)
556 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
558 TRACE("(%p)->(%d %s %s %p)\n", This
, code
, debugstr_w(resp_headers
),
559 debugstr_w(req_headers
), add_reqheaders
);
561 This
->request
->status
= code
;
562 /* store headers and status text */
563 free_response_headers(This
->request
);
564 SysFreeString(This
->request
->status_text
);
565 This
->request
->status_text
= NULL
;
568 const WCHAR
*ptr
, *line
, *status_text
;
570 ptr
= line
= resp_headers
;
572 /* skip HTTP-Version */
573 ptr
= strchrW(ptr
, ' ');
576 /* skip Status-Code */
577 ptr
= strchrW(++ptr
, ' ');
581 /* now it supposed to end with CRLF */
584 if (*ptr
== '\r' && *(ptr
+1) == '\n')
587 This
->request
->status_text
= SysAllocStringLen(status_text
, ptr
-status_text
);
588 TRACE("status text %s\n", debugstr_w(This
->request
->status_text
));
596 /* store as unparsed string for now */
597 This
->request
->raw_respheaders
= SysAllocString(line
);
603 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl
= {
604 BSCHttpNegotiate_QueryInterface
,
605 BSCHttpNegotiate_AddRef
,
606 BSCHttpNegotiate_Release
,
607 BSCHttpNegotiate_BeginningTransaction
,
608 BSCHttpNegotiate_OnResponse
611 static HRESULT WINAPI
Authenticate_QueryInterface(IAuthenticate
*iface
,
612 REFIID riid
, void **ppv
)
614 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
615 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
618 static ULONG WINAPI
Authenticate_AddRef(IAuthenticate
*iface
)
620 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
621 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
624 static ULONG WINAPI
Authenticate_Release(IAuthenticate
*iface
)
626 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
627 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
630 static HRESULT WINAPI
Authenticate_Authenticate(IAuthenticate
*iface
,
631 HWND
*hwnd
, LPWSTR
*username
, LPWSTR
*password
)
633 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
634 httprequest
*request
= This
->request
;
636 TRACE("(%p)->(%p %p %p)\n", This
, hwnd
, username
, password
);
638 if (request
->user
&& *request
->user
)
640 if (hwnd
) *hwnd
= NULL
;
641 *username
= CoTaskMemAlloc(SysStringByteLen(request
->user
)+sizeof(WCHAR
));
642 *password
= CoTaskMemAlloc(SysStringByteLen(request
->password
)+sizeof(WCHAR
));
643 if (!*username
|| !*password
)
645 CoTaskMemFree(*username
);
646 CoTaskMemFree(*password
);
647 return E_OUTOFMEMORY
;
650 memcpy(*username
, request
->user
, SysStringByteLen(request
->user
)+sizeof(WCHAR
));
651 memcpy(*password
, request
->password
, SysStringByteLen(request
->password
)+sizeof(WCHAR
));
657 static const IAuthenticateVtbl AuthenticateVtbl
= {
658 Authenticate_QueryInterface
,
660 Authenticate_Release
,
661 Authenticate_Authenticate
664 static HRESULT
BindStatusCallback_create(httprequest
* This
, BindStatusCallback
**obj
, const VARIANT
*body
)
666 BindStatusCallback
*bsc
;
671 hr
= CreateBindCtx(0, &pbc
);
672 if (hr
!= S_OK
) return hr
;
674 bsc
= heap_alloc(sizeof(*bsc
));
677 IBindCtx_Release(pbc
);
678 return E_OUTOFMEMORY
;
681 bsc
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
682 bsc
->IHttpNegotiate_iface
.lpVtbl
= &BSCHttpNegotiateVtbl
;
683 bsc
->IAuthenticate_iface
.lpVtbl
= &AuthenticateVtbl
;
690 TRACE("(%p)->(%p)\n", This
, bsc
);
692 This
->use_utf8_content
= FALSE
;
694 if (This
->verb
!= BINDVERB_GET
)
696 void *send_data
, *ptr
;
697 SAFEARRAY
*sa
= NULL
;
699 if (V_VT(body
) == (VT_VARIANT
|VT_BYREF
))
700 body
= V_VARIANTREF(body
);
706 int len
= SysStringLen(V_BSTR(body
));
707 const WCHAR
*str
= V_BSTR(body
);
710 for (i
= 0; i
< len
; i
++)
719 size
= WideCharToMultiByte(cp
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
720 if (!(ptr
= heap_alloc(size
)))
723 return E_OUTOFMEMORY
;
725 WideCharToMultiByte(cp
, 0, str
, len
, ptr
, size
, NULL
, NULL
);
726 if (cp
== CP_UTF8
) This
->use_utf8_content
= TRUE
;
729 case VT_ARRAY
|VT_UI1
:
732 if ((hr
= SafeArrayAccessData(sa
, (void **)&ptr
)) != S_OK
)
737 if ((hr
= SafeArrayGetUBound(sa
, 1, &size
)) != S_OK
)
739 SafeArrayUnaccessData(sa
);
747 FIXME("unsupported body data type %d\n", V_VT(body
));
759 bsc
->body
= GlobalAlloc(GMEM_FIXED
, size
);
762 if (V_VT(body
) == VT_BSTR
)
764 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
765 SafeArrayUnaccessData(sa
);
768 return E_OUTOFMEMORY
;
771 send_data
= GlobalLock(bsc
->body
);
772 memcpy(send_data
, ptr
, size
);
773 GlobalUnlock(bsc
->body
);
776 if (V_VT(body
) == VT_BSTR
)
778 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
779 SafeArrayUnaccessData(sa
);
782 hr
= RegisterBindStatusCallback(pbc
, &bsc
->IBindStatusCallback_iface
, NULL
, 0);
787 hr
= CreateURLMonikerEx2(NULL
, This
->uri
, &moniker
, URL_MK_UNIFORM
);
792 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
793 IMoniker_Release(moniker
);
794 if (stream
) IStream_Release(stream
);
796 IBindCtx_Release(pbc
);
801 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
809 static HRESULT
verify_uri(httprequest
*This
, IUri
*uri
)
811 DWORD scheme
, base_scheme
;
812 BSTR host
, base_host
;
815 if(!(This
->safeopt
& INTERFACESAFE_FOR_UNTRUSTED_DATA
))
819 return E_ACCESSDENIED
;
821 hr
= IUri_GetScheme(uri
, &scheme
);
825 hr
= IUri_GetScheme(This
->base_uri
, &base_scheme
);
829 if(scheme
!= base_scheme
) {
830 WARN("Schemes don't match\n");
831 return E_ACCESSDENIED
;
834 if(scheme
== INTERNET_SCHEME_UNKNOWN
) {
835 FIXME("Unknown scheme\n");
836 return E_ACCESSDENIED
;
839 hr
= IUri_GetHost(uri
, &host
);
843 hr
= IUri_GetHost(This
->base_uri
, &base_host
);
845 if(strcmpiW(host
, base_host
)) {
846 WARN("Hosts don't match\n");
849 SysFreeString(base_host
);
856 static HRESULT
httprequest_open(httprequest
*This
, BSTR method
, BSTR url
,
857 VARIANT async
, VARIANT user
, VARIANT password
)
859 static const WCHAR MethodGetW
[] = {'G','E','T',0};
860 static const WCHAR MethodPutW
[] = {'P','U','T',0};
861 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
862 static const WCHAR MethodDeleteW
[] = {'D','E','L','E','T','E',0};
863 static const WCHAR MethodPropFindW
[] = {'P','R','O','P','F','I','N','D',0};
864 VARIANT str
, is_async
;
868 if (!method
|| !url
) return E_INVALIDARG
;
870 /* free previously set data */
872 IUri_Release(This
->uri
);
876 SysFreeString(This
->user
);
877 SysFreeString(This
->password
);
878 This
->user
= This
->password
= NULL
;
879 free_request_headers(This
);
881 if (!strcmpiW(method
, MethodGetW
))
883 This
->verb
= BINDVERB_GET
;
885 else if (!strcmpiW(method
, MethodPutW
))
887 This
->verb
= BINDVERB_PUT
;
889 else if (!strcmpiW(method
, MethodPostW
))
891 This
->verb
= BINDVERB_POST
;
893 else if (!strcmpiW(method
, MethodDeleteW
) ||
894 !strcmpiW(method
, MethodPropFindW
))
896 This
->verb
= BINDVERB_CUSTOM
;
897 SysReAllocString(&This
->custom
, method
);
901 FIXME("unsupported request type %s\n", debugstr_w(method
));
907 hr
= CoInternetCombineUrlEx(This
->base_uri
, url
, 0, &uri
, 0);
909 hr
= CreateUri(url
, 0, 0, &uri
);
911 WARN("Could not create IUri object: %08x\n", hr
);
915 hr
= verify_uri(This
, uri
);
922 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
924 This
->user
= V_BSTR(&str
);
927 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
929 This
->password
= V_BSTR(&str
);
931 /* add authentication info */
932 if (This
->user
&& *This
->user
)
934 IUriBuilder
*builder
;
936 hr
= CreateIUriBuilder(uri
, 0, 0, &builder
);
941 IUriBuilder_SetUserName(builder
, This
->user
);
942 IUriBuilder_SetPassword(builder
, This
->password
);
943 hr
= IUriBuilder_CreateUri(builder
, -1, 0, 0, &full_uri
);
950 WARN("failed to create modified uri, 0x%08x\n", hr
);
951 IUriBuilder_Release(builder
);
954 WARN("IUriBuilder creation failed, 0x%08x\n", hr
);
959 VariantInit(&is_async
);
960 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
961 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
);
963 httprequest_setreadystate(This
, READYSTATE_LOADING
);
968 static HRESULT
httprequest_setRequestHeader(httprequest
*This
, BSTR header
, BSTR value
)
970 struct httpheader
*entry
;
972 if (!header
|| !*header
) return E_INVALIDARG
;
973 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
974 if (!value
) return E_INVALIDARG
;
976 /* replace existing header value if already added */
977 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct httpheader
, entry
)
979 if (lstrcmpW(entry
->header
, header
) == 0)
981 LONG length
= SysStringLen(entry
->value
);
984 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
987 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
993 entry
= heap_alloc(sizeof(*entry
));
994 if (!entry
) return E_OUTOFMEMORY
;
997 entry
->header
= SysAllocString(header
);
998 entry
->value
= SysAllocString(value
);
1000 /* header length including null terminator */
1001 This
->reqheader_size
+= SysStringLen(entry
->header
) + sizeof(colspaceW
)/sizeof(WCHAR
) +
1002 SysStringLen(entry
->value
) + sizeof(crlfW
)/sizeof(WCHAR
) - 1;
1004 list_add_head(&This
->reqheaders
, &entry
->entry
);
1009 static HRESULT
httprequest_getResponseHeader(httprequest
*This
, BSTR header
, BSTR
*value
)
1011 struct httpheader
*entry
;
1013 if (!header
) return E_INVALIDARG
;
1014 if (!value
) return E_POINTER
;
1016 if (This
->raw_respheaders
&& list_empty(&This
->respheaders
))
1020 ptr
= line
= This
->raw_respheaders
;
1023 if (*ptr
== '\r' && *(ptr
+1) == '\n')
1025 add_response_header(This
, line
, ptr
-line
);
1026 ptr
++; line
= ++ptr
;
1033 LIST_FOR_EACH_ENTRY(entry
, &This
->respheaders
, struct httpheader
, entry
)
1035 if (!strcmpiW(entry
->header
, header
))
1037 *value
= SysAllocString(entry
->value
);
1038 TRACE("header value %s\n", debugstr_w(*value
));
1046 static HRESULT
httprequest_getAllResponseHeaders(httprequest
*This
, BSTR
*respheaders
)
1048 if (!respheaders
) return E_POINTER
;
1050 *respheaders
= SysAllocString(This
->raw_respheaders
);
1055 static HRESULT
httprequest_send(httprequest
*This
, VARIANT body
)
1057 BindStatusCallback
*bsc
= NULL
;
1060 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
1062 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
1064 /* success path to detach it is OnStopBinding call */
1065 BindStatusCallback_Detach(bsc
);
1070 static HRESULT
httprequest_abort(httprequest
*This
)
1072 BindStatusCallback_Detach(This
->bsc
);
1074 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
1079 static HRESULT
httprequest_get_status(httprequest
*This
, LONG
*status
)
1081 if (!status
) return E_POINTER
;
1083 *status
= This
->status
;
1085 return This
->state
== READYSTATE_COMPLETE
? S_OK
: E_FAIL
;
1088 static HRESULT
httprequest_get_statusText(httprequest
*This
, BSTR
*status
)
1090 if (!status
) return E_POINTER
;
1091 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1093 *status
= SysAllocString(This
->status_text
);
1098 static HRESULT
httprequest_get_responseText(httprequest
*This
, BSTR
*body
)
1103 if (!body
) return E_POINTER
;
1104 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1106 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1109 xmlChar
*ptr
= GlobalLock(hglobal
);
1110 DWORD size
= GlobalSize(hglobal
);
1111 xmlCharEncoding encoding
= XML_CHAR_ENCODING_UTF8
;
1113 /* try to determine data encoding */
1116 encoding
= xmlDetectCharEncoding(ptr
, 4);
1117 TRACE("detected encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1118 if ( encoding
!= XML_CHAR_ENCODING_UTF8
&&
1119 encoding
!= XML_CHAR_ENCODING_UTF16LE
&&
1120 encoding
!= XML_CHAR_ENCODING_NONE
)
1122 FIXME("unsupported encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1123 GlobalUnlock(hglobal
);
1128 /* without BOM assume UTF-8 */
1129 if (encoding
== XML_CHAR_ENCODING_UTF8
||
1130 encoding
== XML_CHAR_ENCODING_NONE
)
1132 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)ptr
, size
, NULL
, 0);
1134 *body
= SysAllocStringLen(NULL
, length
);
1136 MultiByteToWideChar( CP_UTF8
, 0, (LPCSTR
)ptr
, size
, *body
, length
);
1139 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
1141 if (!*body
) hr
= E_OUTOFMEMORY
;
1142 GlobalUnlock(hglobal
);
1148 static HRESULT
httprequest_get_responseXML(httprequest
*This
, IDispatch
**body
)
1150 IXMLDOMDocument3
*doc
;
1154 if (!body
) return E_INVALIDARG
;
1155 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1157 hr
= DOMDocument_create(MSXML_DEFAULT
, (void**)&doc
);
1158 if (hr
!= S_OK
) return hr
;
1160 hr
= httprequest_get_responseText(This
, &str
);
1165 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
1169 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
1170 IXMLDOMDocument3_Release(doc
);
1175 static HRESULT
httprequest_get_responseBody(httprequest
*This
, VARIANT
*body
)
1180 if (!body
) return E_INVALIDARG
;
1181 V_VT(body
) = VT_EMPTY
;
1183 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1185 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1188 void *ptr
= GlobalLock(hglobal
);
1189 DWORD size
= GlobalSize(hglobal
);
1191 SAFEARRAYBOUND bound
;
1195 bound
.cElements
= size
;
1196 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
1202 V_VT(body
) = VT_ARRAY
| VT_UI1
;
1203 V_ARRAY(body
) = array
;
1205 hr
= SafeArrayAccessData(array
, &dest
);
1208 memcpy(dest
, ptr
, size
);
1209 SafeArrayUnaccessData(array
);
1219 GlobalUnlock(hglobal
);
1225 static HRESULT
httprequest_get_responseStream(httprequest
*This
, VARIANT
*body
)
1231 if (!body
) return E_INVALIDARG
;
1232 V_VT(body
) = VT_EMPTY
;
1234 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1236 hr
= IStream_Clone(This
->bsc
->stream
, &stream
);
1239 IStream_Seek(stream
, move
, STREAM_SEEK_SET
, NULL
);
1241 V_VT(body
) = VT_UNKNOWN
;
1242 V_UNKNOWN(body
) = (IUnknown
*)stream
;
1247 static HRESULT
httprequest_get_readyState(httprequest
*This
, LONG
*state
)
1249 if (!state
) return E_POINTER
;
1251 *state
= This
->state
;
1255 static HRESULT
httprequest_put_onreadystatechange(httprequest
*This
, IDispatch
*sink
)
1257 if (This
->sink
) IDispatch_Release(This
->sink
);
1258 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1263 static void httprequest_release(httprequest
*This
)
1266 IUnknown_Release( This
->site
);
1268 IUri_Release(This
->uri
);
1270 IUri_Release(This
->base_uri
);
1272 SysFreeString(This
->custom
);
1273 SysFreeString(This
->user
);
1274 SysFreeString(This
->password
);
1276 /* cleanup headers lists */
1277 free_request_headers(This
);
1278 free_response_headers(This
);
1279 SysFreeString(This
->status_text
);
1281 /* detach callback object */
1282 BindStatusCallback_Detach(This
->bsc
);
1284 if (This
->sink
) IDispatch_Release(This
->sink
);
1287 static HRESULT WINAPI
XMLHTTPRequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
1289 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1290 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1292 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1293 IsEqualGUID( riid
, &IID_IDispatch
) ||
1294 IsEqualGUID( riid
, &IID_IUnknown
) )
1298 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
1300 *ppvObject
= &This
->IObjectWithSite_iface
;
1302 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
1304 *ppvObject
= &This
->IObjectSafety_iface
;
1308 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1310 return E_NOINTERFACE
;
1313 IXMLHTTPRequest_AddRef( iface
);
1318 static ULONG WINAPI
XMLHTTPRequest_AddRef(IXMLHTTPRequest
*iface
)
1320 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1321 ULONG ref
= InterlockedIncrement( &This
->ref
);
1322 TRACE("(%p)->(%u)\n", This
, ref
);
1326 static ULONG WINAPI
XMLHTTPRequest_Release(IXMLHTTPRequest
*iface
)
1328 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1329 ULONG ref
= InterlockedDecrement( &This
->ref
);
1331 TRACE("(%p)->(%u)\n", This
, ref
);
1335 httprequest_release( This
);
1342 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1344 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1346 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1353 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
1354 LCID lcid
, ITypeInfo
**ppTInfo
)
1356 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1358 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1360 return get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
1363 static HRESULT WINAPI
XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
1364 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1366 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1367 ITypeInfo
*typeinfo
;
1370 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1373 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1374 return E_INVALIDARG
;
1376 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1379 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1380 ITypeInfo_Release(typeinfo
);
1386 static HRESULT WINAPI
XMLHTTPRequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1387 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1388 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1390 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1391 ITypeInfo
*typeinfo
;
1394 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1395 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1397 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1400 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1401 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1402 ITypeInfo_Release(typeinfo
);
1408 static HRESULT WINAPI
XMLHTTPRequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1409 VARIANT async
, VARIANT user
, VARIANT password
)
1411 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1412 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1413 debugstr_variant(&async
));
1414 return httprequest_open(This
, method
, url
, async
, user
, password
);
1417 static HRESULT WINAPI
XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1419 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1420 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1421 return httprequest_setRequestHeader(This
, header
, value
);
1424 static HRESULT WINAPI
XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1426 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1427 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1428 return httprequest_getResponseHeader(This
, header
, value
);
1431 static HRESULT WINAPI
XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1433 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1434 TRACE("(%p)->(%p)\n", This
, respheaders
);
1435 return httprequest_getAllResponseHeaders(This
, respheaders
);
1438 static HRESULT WINAPI
XMLHTTPRequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
1440 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1441 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1442 return httprequest_send(This
, body
);
1445 static HRESULT WINAPI
XMLHTTPRequest_abort(IXMLHTTPRequest
*iface
)
1447 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1448 TRACE("(%p)\n", This
);
1449 return httprequest_abort(This
);
1452 static HRESULT WINAPI
XMLHTTPRequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
1454 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1455 TRACE("(%p)->(%p)\n", This
, status
);
1456 return httprequest_get_status(This
, status
);
1459 static HRESULT WINAPI
XMLHTTPRequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*status
)
1461 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1462 TRACE("(%p)->(%p)\n", This
, status
);
1463 return httprequest_get_statusText(This
, status
);
1466 static HRESULT WINAPI
XMLHTTPRequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
1468 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1469 TRACE("(%p)->(%p)\n", This
, body
);
1470 return httprequest_get_responseXML(This
, body
);
1473 static HRESULT WINAPI
XMLHTTPRequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
1475 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1476 TRACE("(%p)->(%p)\n", This
, body
);
1477 return httprequest_get_responseText(This
, body
);
1480 static HRESULT WINAPI
XMLHTTPRequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1482 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1483 TRACE("(%p)->(%p)\n", This
, body
);
1484 return httprequest_get_responseBody(This
, body
);
1487 static HRESULT WINAPI
XMLHTTPRequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1489 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1490 TRACE("(%p)->(%p)\n", This
, body
);
1491 return httprequest_get_responseStream(This
, body
);
1494 static HRESULT WINAPI
XMLHTTPRequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
1496 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1497 TRACE("(%p)->(%p)\n", This
, state
);
1498 return httprequest_get_readyState(This
, state
);
1501 static HRESULT WINAPI
XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
1503 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1504 TRACE("(%p)->(%p)\n", This
, sink
);
1505 return httprequest_put_onreadystatechange(This
, sink
);
1508 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl
=
1510 XMLHTTPRequest_QueryInterface
,
1511 XMLHTTPRequest_AddRef
,
1512 XMLHTTPRequest_Release
,
1513 XMLHTTPRequest_GetTypeInfoCount
,
1514 XMLHTTPRequest_GetTypeInfo
,
1515 XMLHTTPRequest_GetIDsOfNames
,
1516 XMLHTTPRequest_Invoke
,
1517 XMLHTTPRequest_open
,
1518 XMLHTTPRequest_setRequestHeader
,
1519 XMLHTTPRequest_getResponseHeader
,
1520 XMLHTTPRequest_getAllResponseHeaders
,
1521 XMLHTTPRequest_send
,
1522 XMLHTTPRequest_abort
,
1523 XMLHTTPRequest_get_status
,
1524 XMLHTTPRequest_get_statusText
,
1525 XMLHTTPRequest_get_responseXML
,
1526 XMLHTTPRequest_get_responseText
,
1527 XMLHTTPRequest_get_responseBody
,
1528 XMLHTTPRequest_get_responseStream
,
1529 XMLHTTPRequest_get_readyState
,
1530 XMLHTTPRequest_put_onreadystatechange
1533 /* IObjectWithSite */
1534 static HRESULT WINAPI
1535 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1537 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1538 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppvObject
);
1541 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1543 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1544 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1547 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1549 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1550 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1553 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1555 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1557 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1562 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1565 static void get_base_uri(httprequest
*This
)
1567 IServiceProvider
*provider
;
1568 IHTMLDocument2
*doc
;
1573 hr
= IUnknown_QueryInterface(This
->site
, &IID_IServiceProvider
, (void**)&provider
);
1577 hr
= IServiceProvider_QueryService(provider
, &SID_SContainerDispatch
, &IID_IHTMLDocument2
, (void**)&doc
);
1579 hr
= IServiceProvider_QueryService(provider
, &SID_SInternetHostSecurityManager
, &IID_IHTMLDocument2
, (void**)&doc
);
1580 IServiceProvider_Release(provider
);
1584 hr
= IHTMLDocument2_get_URL(doc
, &url
);
1585 IHTMLDocument2_Release(doc
);
1586 if(FAILED(hr
) || !url
|| !*url
)
1589 TRACE("host url %s\n", debugstr_w(url
));
1591 hr
= CreateUri(url
, 0, 0, &uri
);
1596 This
->base_uri
= uri
;
1599 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1601 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1603 TRACE("(%p)->(%p)\n", This
, punk
);
1606 IUnknown_Release( This
->site
);
1608 IUri_Release(This
->base_uri
);
1614 IUnknown_AddRef( punk
);
1621 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1623 httprequest_ObjectWithSite_QueryInterface
,
1624 httprequest_ObjectWithSite_AddRef
,
1625 httprequest_ObjectWithSite_Release
,
1626 httprequest_ObjectWithSite_SetSite
,
1627 httprequest_ObjectWithSite_GetSite
1631 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1633 httprequest
*This
= impl_from_IObjectSafety(iface
);
1634 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppv
);
1637 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1639 httprequest
*This
= impl_from_IObjectSafety(iface
);
1640 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1643 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1645 httprequest
*This
= impl_from_IObjectSafety(iface
);
1646 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1649 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1650 DWORD
*supported
, DWORD
*enabled
)
1652 httprequest
*This
= impl_from_IObjectSafety(iface
);
1654 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1656 if(!supported
|| !enabled
) return E_POINTER
;
1658 *supported
= safety_supported_options
;
1659 *enabled
= This
->safeopt
;
1664 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1665 DWORD mask
, DWORD enabled
)
1667 httprequest
*This
= impl_from_IObjectSafety(iface
);
1668 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
1670 if ((mask
& ~safety_supported_options
))
1673 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
1678 static const IObjectSafetyVtbl ObjectSafetyVtbl
= {
1679 httprequest_Safety_QueryInterface
,
1680 httprequest_Safety_AddRef
,
1681 httprequest_Safety_Release
,
1682 httprequest_Safety_GetInterfaceSafetyOptions
,
1683 httprequest_Safety_SetInterfaceSafetyOptions
1686 /* IServerXMLHTTPRequest */
1687 static HRESULT WINAPI
ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest
*iface
, REFIID riid
, void **obj
)
1689 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1691 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1693 if ( IsEqualGUID( riid
, &IID_IServerXMLHTTPRequest
) ||
1694 IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1695 IsEqualGUID( riid
, &IID_IDispatch
) ||
1696 IsEqualGUID( riid
, &IID_IUnknown
) )
1702 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1704 return E_NOINTERFACE
;
1707 IServerXMLHTTPRequest_AddRef( iface
);
1712 static ULONG WINAPI
ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest
*iface
)
1714 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1715 ULONG ref
= InterlockedIncrement( &This
->req
.ref
);
1716 TRACE("(%p)->(%u)\n", This
, ref
);
1720 static ULONG WINAPI
ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest
*iface
)
1722 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1723 ULONG ref
= InterlockedDecrement( &This
->req
.ref
);
1725 TRACE("(%p)->(%u)\n", This
, ref
);
1729 httprequest_release( &This
->req
);
1736 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1738 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1740 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1746 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest
*iface
, UINT iTInfo
,
1747 LCID lcid
, ITypeInfo
**ppTInfo
)
1749 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1751 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1753 return get_typeinfo(IServerXMLHTTPRequest_tid
, ppTInfo
);
1756 static HRESULT WINAPI
ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest
*iface
, REFIID riid
,
1757 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1759 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1760 ITypeInfo
*typeinfo
;
1763 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1766 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1767 return E_INVALIDARG
;
1769 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1772 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1773 ITypeInfo_Release(typeinfo
);
1779 static HRESULT WINAPI
ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1780 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1781 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1783 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1784 ITypeInfo
*typeinfo
;
1787 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1788 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1790 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1793 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IServerXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1794 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1795 ITypeInfo_Release(typeinfo
);
1801 static HRESULT WINAPI
ServerXMLHTTPRequest_open(IServerXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1802 VARIANT async
, VARIANT user
, VARIANT password
)
1804 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1805 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1806 debugstr_variant(&async
));
1807 return httprequest_open(&This
->req
, method
, url
, async
, user
, password
);
1810 static HRESULT WINAPI
ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1812 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1813 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1814 return httprequest_setRequestHeader(&This
->req
, header
, value
);
1817 static HRESULT WINAPI
ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1819 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1820 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1821 return httprequest_getResponseHeader(&This
->req
, header
, value
);
1824 static HRESULT WINAPI
ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1826 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1827 TRACE("(%p)->(%p)\n", This
, respheaders
);
1828 return httprequest_getAllResponseHeaders(&This
->req
, respheaders
);
1831 static HRESULT WINAPI
ServerXMLHTTPRequest_send(IServerXMLHTTPRequest
*iface
, VARIANT body
)
1833 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1834 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1835 return httprequest_send(&This
->req
, body
);
1838 static HRESULT WINAPI
ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest
*iface
)
1840 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1841 TRACE("(%p)\n", This
);
1842 return httprequest_abort(&This
->req
);
1845 static HRESULT WINAPI
ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest
*iface
, LONG
*status
)
1847 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1848 TRACE("(%p)->(%p)\n", This
, status
);
1849 return httprequest_get_status(&This
->req
, status
);
1852 static HRESULT WINAPI
ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest
*iface
, BSTR
*status
)
1854 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1855 TRACE("(%p)->(%p)\n", This
, status
);
1856 return httprequest_get_statusText(&This
->req
, status
);
1859 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest
*iface
, IDispatch
**body
)
1861 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1862 TRACE("(%p)->(%p)\n", This
, body
);
1863 return httprequest_get_responseXML(&This
->req
, body
);
1866 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest
*iface
, BSTR
*body
)
1868 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1869 TRACE("(%p)->(%p)\n", This
, body
);
1870 return httprequest_get_responseText(&This
->req
, body
);
1873 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1875 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1876 TRACE("(%p)->(%p)\n", This
, body
);
1877 return httprequest_get_responseBody(&This
->req
, body
);
1880 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1882 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1883 TRACE("(%p)->(%p)\n", This
, body
);
1884 return httprequest_get_responseStream(&This
->req
, body
);
1887 static HRESULT WINAPI
ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest
*iface
, LONG
*state
)
1889 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1890 TRACE("(%p)->(%p)\n", This
, state
);
1891 return httprequest_get_readyState(&This
->req
, state
);
1894 static HRESULT WINAPI
ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest
*iface
, IDispatch
*sink
)
1896 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1897 TRACE("(%p)->(%p)\n", This
, sink
);
1898 return httprequest_put_onreadystatechange(&This
->req
, sink
);
1901 static HRESULT WINAPI
ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest
*iface
, LONG resolveTimeout
, LONG connectTimeout
,
1902 LONG sendTimeout
, LONG receiveTimeout
)
1904 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1905 FIXME("(%p)->(%d %d %d %d): stub\n", This
, resolveTimeout
, connectTimeout
, sendTimeout
, receiveTimeout
);
1909 static HRESULT WINAPI
ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest
*iface
, VARIANT timeout
, VARIANT_BOOL
*isSuccessful
)
1911 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1912 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_variant(&timeout
), isSuccessful
);
1916 static HRESULT WINAPI
ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT
*value
)
1918 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1919 FIXME("(%p)->(%d %p): stub\n", This
, option
, value
);
1923 static HRESULT WINAPI
ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT value
)
1925 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1926 FIXME("(%p)->(%d %s): stub\n", This
, option
, debugstr_variant(&value
));
1930 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl
=
1932 ServerXMLHTTPRequest_QueryInterface
,
1933 ServerXMLHTTPRequest_AddRef
,
1934 ServerXMLHTTPRequest_Release
,
1935 ServerXMLHTTPRequest_GetTypeInfoCount
,
1936 ServerXMLHTTPRequest_GetTypeInfo
,
1937 ServerXMLHTTPRequest_GetIDsOfNames
,
1938 ServerXMLHTTPRequest_Invoke
,
1939 ServerXMLHTTPRequest_open
,
1940 ServerXMLHTTPRequest_setRequestHeader
,
1941 ServerXMLHTTPRequest_getResponseHeader
,
1942 ServerXMLHTTPRequest_getAllResponseHeaders
,
1943 ServerXMLHTTPRequest_send
,
1944 ServerXMLHTTPRequest_abort
,
1945 ServerXMLHTTPRequest_get_status
,
1946 ServerXMLHTTPRequest_get_statusText
,
1947 ServerXMLHTTPRequest_get_responseXML
,
1948 ServerXMLHTTPRequest_get_responseText
,
1949 ServerXMLHTTPRequest_get_responseBody
,
1950 ServerXMLHTTPRequest_get_responseStream
,
1951 ServerXMLHTTPRequest_get_readyState
,
1952 ServerXMLHTTPRequest_put_onreadystatechange
,
1953 ServerXMLHTTPRequest_setTimeouts
,
1954 ServerXMLHTTPRequest_waitForResponse
,
1955 ServerXMLHTTPRequest_getOption
,
1956 ServerXMLHTTPRequest_setOption
1959 static void init_httprequest(httprequest
*req
)
1961 req
->IXMLHTTPRequest_iface
.lpVtbl
= &XMLHTTPRequestVtbl
;
1962 req
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
1963 req
->IObjectSafety_iface
.lpVtbl
= &ObjectSafetyVtbl
;
1969 req
->uri
= req
->base_uri
= NULL
;
1970 req
->user
= req
->password
= NULL
;
1972 req
->state
= READYSTATE_UNINITIALIZED
;
1977 req
->status_text
= NULL
;
1978 req
->reqheader_size
= 0;
1979 req
->raw_respheaders
= NULL
;
1980 req
->use_utf8_content
= FALSE
;
1982 list_init(&req
->reqheaders
);
1983 list_init(&req
->respheaders
);
1989 HRESULT
XMLHTTPRequest_create(void **obj
)
1993 TRACE("(%p)\n", obj
);
1995 req
= heap_alloc( sizeof (*req
) );
1997 return E_OUTOFMEMORY
;
1999 init_httprequest(req
);
2000 *obj
= &req
->IXMLHTTPRequest_iface
;
2002 TRACE("returning iface %p\n", *obj
);
2007 HRESULT
ServerXMLHTTP_create(void **obj
)
2011 TRACE("(%p)\n", obj
);
2013 req
= heap_alloc( sizeof (*req
) );
2015 return E_OUTOFMEMORY
;
2017 init_httprequest(&req
->req
);
2018 req
->IServerXMLHTTPRequest_iface
.lpVtbl
= &ServerXMLHTTPRequestVtbl
;
2020 *obj
= &req
->IServerXMLHTTPRequest_iface
;
2022 TRACE("returning iface %p\n", *obj
);
2029 HRESULT
XMLHTTPRequest_create(void **ppObj
)
2031 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
2032 "libxml2 support was not present at compile time.\n");
2036 HRESULT
ServerXMLHTTP_create(void **obj
)
2038 MESSAGE("This program tried to use a ServerXMLHTTP object, but\n"
2039 "libxml2 support was not present at compile time.\n");