2 * IXMLHTTPRequest implementation
4 * Copyright 2008 Alistair Leslie-Hughes
5 * Copyright 2010-2012 Nikolay Sivov for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/encoding.h>
47 #include "msxml_private.h"
49 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
55 static const WCHAR colspaceW
[] = {':',' ',0};
56 static const WCHAR crlfW
[] = {'\r','\n',0};
57 static const DWORD safety_supported_options
=
58 INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
59 INTERFACESAFE_FOR_UNTRUSTED_DATA
|
60 INTERFACE_USES_SECURITY_MANAGER
;
62 typedef struct BindStatusCallback BindStatusCallback
;
73 IXMLHTTPRequest IXMLHTTPRequest_iface
;
74 IObjectWithSite IObjectWithSite_iface
;
75 IObjectSafety IObjectSafety_iface
;
87 struct list reqheaders
;
88 /* cached resulting custom request headers string length in WCHARs */
90 /* use UTF-8 content type */
91 BOOL use_utf8_content
;
93 /* response headers */
94 struct list respheaders
;
102 BindStatusCallback
*bsc
;
116 IServerXMLHTTPRequest IServerXMLHTTPRequest_iface
;
119 static inline httprequest
*impl_from_IXMLHTTPRequest( IXMLHTTPRequest
*iface
)
121 return CONTAINING_RECORD(iface
, httprequest
, IXMLHTTPRequest_iface
);
124 static inline httprequest
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
126 return CONTAINING_RECORD(iface
, httprequest
, IObjectWithSite_iface
);
129 static inline httprequest
*impl_from_IObjectSafety(IObjectSafety
*iface
)
131 return CONTAINING_RECORD(iface
, httprequest
, IObjectSafety_iface
);
134 static inline serverhttp
*impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest
*iface
)
136 return CONTAINING_RECORD(iface
, serverhttp
, IServerXMLHTTPRequest_iface
);
139 static void httprequest_setreadystate(httprequest
*This
, READYSTATE state
)
141 READYSTATE last
= This
->state
;
142 static const char* readystates
[] = {
143 "READYSTATE_UNINITIALIZED",
144 "READYSTATE_LOADING",
146 "READYSTATE_INTERACTIVE",
147 "READYSTATE_COMPLETE"};
151 TRACE("state %s\n", readystates
[state
]);
153 if (This
->sink
&& last
!= state
)
157 memset(¶ms
, 0, sizeof(params
));
158 IDispatch_Invoke(This
->sink
, 0, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, ¶ms
, 0, 0, 0);
162 static void free_response_headers(httprequest
*This
)
164 struct httpheader
*header
, *header2
;
166 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->respheaders
, struct httpheader
, entry
)
168 list_remove(&header
->entry
);
169 SysFreeString(header
->header
);
170 SysFreeString(header
->value
);
174 SysFreeString(This
->raw_respheaders
);
175 This
->raw_respheaders
= NULL
;
178 static void free_request_headers(httprequest
*This
)
180 struct httpheader
*header
, *header2
;
182 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->reqheaders
, struct httpheader
, entry
)
184 list_remove(&header
->entry
);
185 SysFreeString(header
->header
);
186 SysFreeString(header
->value
);
191 struct BindStatusCallback
193 IBindStatusCallback IBindStatusCallback_iface
;
194 IHttpNegotiate IHttpNegotiate_iface
;
195 IAuthenticate IAuthenticate_iface
;
199 httprequest
*request
;
204 /* request body data */
208 static inline BindStatusCallback
*impl_from_IBindStatusCallback( IBindStatusCallback
*iface
)
210 return CONTAINING_RECORD(iface
, BindStatusCallback
, IBindStatusCallback_iface
);
213 static inline BindStatusCallback
*impl_from_IHttpNegotiate( IHttpNegotiate
*iface
)
215 return CONTAINING_RECORD(iface
, BindStatusCallback
, IHttpNegotiate_iface
);
218 static inline BindStatusCallback
*impl_from_IAuthenticate( IAuthenticate
*iface
)
220 return CONTAINING_RECORD(iface
, BindStatusCallback
, IAuthenticate_iface
);
223 static void BindStatusCallback_Detach(BindStatusCallback
*bsc
)
227 if (bsc
->binding
) IBinding_Abort(bsc
->binding
);
228 bsc
->request
->bsc
= NULL
;
230 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
234 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
235 REFIID riid
, void **ppv
)
237 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
241 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
243 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
244 IsEqualGUID(&IID_IBindStatusCallback
, riid
))
246 *ppv
= &This
->IBindStatusCallback_iface
;
248 else if (IsEqualGUID(&IID_IHttpNegotiate
, riid
))
250 *ppv
= &This
->IHttpNegotiate_iface
;
252 else if (IsEqualGUID(&IID_IAuthenticate
, riid
))
254 *ppv
= &This
->IAuthenticate_iface
;
256 else if (IsEqualGUID(&IID_IServiceProvider
, riid
) ||
257 IsEqualGUID(&IID_IBindStatusCallbackEx
, riid
) ||
258 IsEqualGUID(&IID_IInternetProtocol
, riid
) ||
259 IsEqualGUID(&IID_IHttpNegotiate2
, riid
))
261 return E_NOINTERFACE
;
266 IBindStatusCallback_AddRef(iface
);
270 FIXME("Unsupported riid = %s\n", debugstr_guid(riid
));
272 return E_NOINTERFACE
;
275 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
277 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
278 LONG ref
= InterlockedIncrement(&This
->ref
);
280 TRACE("(%p) ref = %d\n", This
, ref
);
285 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
287 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
288 LONG ref
= InterlockedDecrement(&This
->ref
);
290 TRACE("(%p) ref = %d\n", This
, ref
);
294 if (This
->binding
) IBinding_Release(This
->binding
);
295 if (This
->stream
) IStream_Release(This
->stream
);
296 if (This
->body
) GlobalFree(This
->body
);
303 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
304 DWORD reserved
, IBinding
*pbind
)
306 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
308 TRACE("(%p)->(%d %p)\n", This
, reserved
, pbind
);
310 if (!pbind
) return E_INVALIDARG
;
312 This
->binding
= pbind
;
313 IBinding_AddRef(pbind
);
315 httprequest_setreadystate(This
->request
, READYSTATE_LOADED
);
317 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
320 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pPriority
)
322 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
324 TRACE("(%p)->(%p)\n", This
, pPriority
);
329 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
331 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
333 TRACE("(%p)->(%d)\n", This
, reserved
);
338 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
339 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
341 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
343 TRACE("(%p)->(%u %u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
344 debugstr_w(szStatusText
));
349 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
350 HRESULT hr
, LPCWSTR error
)
352 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
354 TRACE("(%p)->(0x%08x %s)\n", This
, hr
, debugstr_w(error
));
358 IBinding_Release(This
->binding
);
359 This
->binding
= NULL
;
364 BindStatusCallback_Detach(This
->request
->bsc
);
365 This
->request
->bsc
= This
;
366 httprequest_setreadystate(This
->request
, READYSTATE_COMPLETE
);
372 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
373 DWORD
*bind_flags
, BINDINFO
*pbindinfo
)
375 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
377 TRACE("(%p)->(%p %p)\n", This
, bind_flags
, pbindinfo
);
380 if (This
->request
->async
) *bind_flags
|= BINDF_ASYNCHRONOUS
;
382 if (This
->request
->verb
!= BINDVERB_GET
&& This
->body
)
384 pbindinfo
->stgmedData
.tymed
= TYMED_HGLOBAL
;
385 pbindinfo
->stgmedData
.u
.hGlobal
= This
->body
;
386 pbindinfo
->cbstgmedData
= GlobalSize(This
->body
);
387 /* callback owns passed body pointer */
388 IBindStatusCallback_QueryInterface(iface
, &IID_IUnknown
, (void**)&pbindinfo
->stgmedData
.pUnkForRelease
);
391 pbindinfo
->dwBindVerb
= This
->request
->verb
;
392 if (This
->request
->verb
== BINDVERB_CUSTOM
)
394 pbindinfo
->szCustomVerb
= CoTaskMemAlloc(SysStringByteLen(This
->request
->custom
));
395 strcpyW(pbindinfo
->szCustomVerb
, This
->request
->custom
);
401 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
402 DWORD flags
, DWORD size
, FORMATETC
*format
, STGMEDIUM
*stgmed
)
404 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
409 TRACE("(%p)->(%08x %d %p %p)\n", This
, flags
, size
, format
, stgmed
);
413 hr
= IStream_Read(stgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
414 if (hr
!= S_OK
) break;
416 hr
= IStream_Write(This
->stream
, buf
, read
, &written
);
417 } while((hr
== S_OK
) && written
!= 0 && read
!= 0);
419 httprequest_setreadystate(This
->request
, READYSTATE_INTERACTIVE
);
424 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
425 REFIID riid
, IUnknown
*punk
)
427 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
429 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
434 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
435 BindStatusCallback_QueryInterface
,
436 BindStatusCallback_AddRef
,
437 BindStatusCallback_Release
,
438 BindStatusCallback_OnStartBinding
,
439 BindStatusCallback_GetPriority
,
440 BindStatusCallback_OnLowResource
,
441 BindStatusCallback_OnProgress
,
442 BindStatusCallback_OnStopBinding
,
443 BindStatusCallback_GetBindInfo
,
444 BindStatusCallback_OnDataAvailable
,
445 BindStatusCallback_OnObjectAvailable
448 static HRESULT WINAPI
BSCHttpNegotiate_QueryInterface(IHttpNegotiate
*iface
,
449 REFIID riid
, void **ppv
)
451 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
452 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
455 static ULONG WINAPI
BSCHttpNegotiate_AddRef(IHttpNegotiate
*iface
)
457 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
458 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
461 static ULONG WINAPI
BSCHttpNegotiate_Release(IHttpNegotiate
*iface
)
463 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
464 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
467 static HRESULT WINAPI
BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate
*iface
,
468 LPCWSTR url
, LPCWSTR headers
, DWORD reserved
, LPWSTR
*add_headers
)
470 static const WCHAR content_type_utf8W
[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
471 't','e','x','t','/','p','l','a','i','n',';','c','h','a','r','s','e','t','=','u','t','f','-','8','\r','\n',0};
472 static const WCHAR refererW
[] = {'R','e','f','e','r','e','r',':',' ',0};
474 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
475 const struct httpheader
*entry
;
476 BSTR base_uri
= NULL
;
480 TRACE("(%p)->(%s %s %d %p)\n", This
, debugstr_w(url
), debugstr_w(headers
), reserved
, add_headers
);
484 if (This
->request
->use_utf8_content
)
485 size
= sizeof(content_type_utf8W
);
487 if (!list_empty(&This
->request
->reqheaders
))
488 size
+= This
->request
->reqheader_size
*sizeof(WCHAR
);
490 if (This
->request
->base_uri
)
492 IUri_GetRawUri(This
->request
->base_uri
, &base_uri
);
493 size
+= SysStringLen(base_uri
)*sizeof(WCHAR
) + sizeof(refererW
) + sizeof(crlfW
);
498 SysFreeString(base_uri
);
502 buff
= CoTaskMemAlloc(size
);
505 SysFreeString(base_uri
);
506 return E_OUTOFMEMORY
;
510 if (This
->request
->use_utf8_content
)
512 lstrcpyW(ptr
, content_type_utf8W
);
513 ptr
+= sizeof(content_type_utf8W
)/sizeof(WCHAR
)-1;
518 strcpyW(ptr
, refererW
);
519 strcatW(ptr
, base_uri
);
521 ptr
+= strlenW(refererW
) + SysStringLen(base_uri
) + strlenW(crlfW
);
522 SysFreeString(base_uri
);
526 LIST_FOR_EACH_ENTRY(entry
, &This
->request
->reqheaders
, struct httpheader
, entry
)
528 lstrcpyW(ptr
, entry
->header
);
529 ptr
+= SysStringLen(entry
->header
);
531 lstrcpyW(ptr
, colspaceW
);
532 ptr
+= sizeof(colspaceW
)/sizeof(WCHAR
)-1;
534 lstrcpyW(ptr
, entry
->value
);
535 ptr
+= SysStringLen(entry
->value
);
537 lstrcpyW(ptr
, crlfW
);
538 ptr
+= sizeof(crlfW
)/sizeof(WCHAR
)-1;
546 static void add_response_header(httprequest
*This
, const WCHAR
*data
, int len
)
548 struct httpheader
*entry
;
549 const WCHAR
*ptr
= data
;
556 header
= SysAllocStringLen(data
, ptr
-data
);
557 /* skip leading spaces for a value */
558 while (*++ptr
== ' ')
560 value
= SysAllocStringLen(ptr
, len
-(ptr
-data
));
569 TRACE("got header %s:%s\n", debugstr_w(header
), debugstr_w(value
));
571 entry
= heap_alloc(sizeof(*entry
));
572 entry
->header
= header
;
573 entry
->value
= value
;
574 list_add_head(&This
->respheaders
, &entry
->entry
);
577 static HRESULT WINAPI
BSCHttpNegotiate_OnResponse(IHttpNegotiate
*iface
, DWORD code
,
578 LPCWSTR resp_headers
, LPCWSTR req_headers
, LPWSTR
*add_reqheaders
)
580 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
582 TRACE("(%p)->(%d %s %s %p)\n", This
, code
, debugstr_w(resp_headers
),
583 debugstr_w(req_headers
), add_reqheaders
);
585 This
->request
->status
= code
;
586 /* store headers and status text */
587 free_response_headers(This
->request
);
588 SysFreeString(This
->request
->status_text
);
589 This
->request
->status_text
= NULL
;
592 const WCHAR
*ptr
, *line
, *status_text
;
594 ptr
= line
= resp_headers
;
596 /* skip HTTP-Version */
597 ptr
= strchrW(ptr
, ' ');
600 /* skip Status-Code */
601 ptr
= strchrW(++ptr
, ' ');
605 /* now it supposed to end with CRLF */
608 if (*ptr
== '\r' && *(ptr
+1) == '\n')
611 This
->request
->status_text
= SysAllocStringLen(status_text
, ptr
-status_text
);
612 TRACE("status text %s\n", debugstr_w(This
->request
->status_text
));
620 /* store as unparsed string for now */
621 This
->request
->raw_respheaders
= SysAllocString(line
);
627 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl
= {
628 BSCHttpNegotiate_QueryInterface
,
629 BSCHttpNegotiate_AddRef
,
630 BSCHttpNegotiate_Release
,
631 BSCHttpNegotiate_BeginningTransaction
,
632 BSCHttpNegotiate_OnResponse
635 static HRESULT WINAPI
Authenticate_QueryInterface(IAuthenticate
*iface
,
636 REFIID riid
, void **ppv
)
638 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
639 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
642 static ULONG WINAPI
Authenticate_AddRef(IAuthenticate
*iface
)
644 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
645 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
648 static ULONG WINAPI
Authenticate_Release(IAuthenticate
*iface
)
650 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
651 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
654 static HRESULT WINAPI
Authenticate_Authenticate(IAuthenticate
*iface
,
655 HWND
*hwnd
, LPWSTR
*username
, LPWSTR
*password
)
657 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
658 httprequest
*request
= This
->request
;
660 TRACE("(%p)->(%p %p %p)\n", This
, hwnd
, username
, password
);
662 if (request
->user
&& *request
->user
)
664 if (hwnd
) *hwnd
= NULL
;
665 *username
= CoTaskMemAlloc(SysStringByteLen(request
->user
)+sizeof(WCHAR
));
666 *password
= CoTaskMemAlloc(SysStringByteLen(request
->password
)+sizeof(WCHAR
));
667 if (!*username
|| !*password
)
669 CoTaskMemFree(*username
);
670 CoTaskMemFree(*password
);
671 return E_OUTOFMEMORY
;
674 memcpy(*username
, request
->user
, SysStringByteLen(request
->user
)+sizeof(WCHAR
));
675 memcpy(*password
, request
->password
, SysStringByteLen(request
->password
)+sizeof(WCHAR
));
681 static const IAuthenticateVtbl AuthenticateVtbl
= {
682 Authenticate_QueryInterface
,
684 Authenticate_Release
,
685 Authenticate_Authenticate
688 static HRESULT
BindStatusCallback_create(httprequest
* This
, BindStatusCallback
**obj
, const VARIANT
*body
)
690 BindStatusCallback
*bsc
;
695 hr
= CreateBindCtx(0, &pbc
);
696 if (hr
!= S_OK
) return hr
;
698 bsc
= heap_alloc(sizeof(*bsc
));
701 IBindCtx_Release(pbc
);
702 return E_OUTOFMEMORY
;
705 bsc
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
706 bsc
->IHttpNegotiate_iface
.lpVtbl
= &BSCHttpNegotiateVtbl
;
707 bsc
->IAuthenticate_iface
.lpVtbl
= &AuthenticateVtbl
;
714 TRACE("(%p)->(%p)\n", This
, bsc
);
716 This
->use_utf8_content
= FALSE
;
718 if (This
->verb
!= BINDVERB_GET
)
720 void *send_data
, *ptr
;
721 SAFEARRAY
*sa
= NULL
;
723 if (V_VT(body
) == (VT_VARIANT
|VT_BYREF
))
724 body
= V_VARIANTREF(body
);
730 int len
= SysStringLen(V_BSTR(body
));
731 const WCHAR
*str
= V_BSTR(body
);
734 for (i
= 0; i
< len
; i
++)
743 size
= WideCharToMultiByte(cp
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
744 if (!(ptr
= heap_alloc(size
)))
747 return E_OUTOFMEMORY
;
749 WideCharToMultiByte(cp
, 0, str
, len
, ptr
, size
, NULL
, NULL
);
750 if (cp
== CP_UTF8
) This
->use_utf8_content
= TRUE
;
753 case VT_ARRAY
|VT_UI1
:
756 if ((hr
= SafeArrayAccessData(sa
, (void **)&ptr
)) != S_OK
)
761 if ((hr
= SafeArrayGetUBound(sa
, 1, &size
)) != S_OK
)
763 SafeArrayUnaccessData(sa
);
771 FIXME("unsupported body data type %d\n", V_VT(body
));
783 bsc
->body
= GlobalAlloc(GMEM_FIXED
, size
);
786 if (V_VT(body
) == VT_BSTR
)
788 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
789 SafeArrayUnaccessData(sa
);
792 return E_OUTOFMEMORY
;
795 send_data
= GlobalLock(bsc
->body
);
796 memcpy(send_data
, ptr
, size
);
797 GlobalUnlock(bsc
->body
);
800 if (V_VT(body
) == VT_BSTR
)
802 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
803 SafeArrayUnaccessData(sa
);
806 hr
= RegisterBindStatusCallback(pbc
, &bsc
->IBindStatusCallback_iface
, NULL
, 0);
811 hr
= CreateURLMonikerEx2(NULL
, This
->uri
, &moniker
, URL_MK_UNIFORM
);
816 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
817 IMoniker_Release(moniker
);
818 if (stream
) IStream_Release(stream
);
820 IBindCtx_Release(pbc
);
825 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
833 static HRESULT
verify_uri(httprequest
*This
, IUri
*uri
)
835 DWORD scheme
, base_scheme
;
836 BSTR host
, base_host
;
839 if(!(This
->safeopt
& INTERFACESAFE_FOR_UNTRUSTED_DATA
))
843 return E_ACCESSDENIED
;
845 hr
= IUri_GetScheme(uri
, &scheme
);
849 hr
= IUri_GetScheme(This
->base_uri
, &base_scheme
);
853 if(scheme
!= base_scheme
) {
854 WARN("Schemes don't match\n");
855 return E_ACCESSDENIED
;
858 if(scheme
== INTERNET_SCHEME_UNKNOWN
) {
859 FIXME("Unknown scheme\n");
860 return E_ACCESSDENIED
;
863 hr
= IUri_GetHost(uri
, &host
);
867 hr
= IUri_GetHost(This
->base_uri
, &base_host
);
869 if(strcmpiW(host
, base_host
)) {
870 WARN("Hosts don't match\n");
873 SysFreeString(base_host
);
880 static HRESULT
httprequest_open(httprequest
*This
, BSTR method
, BSTR url
,
881 VARIANT async
, VARIANT user
, VARIANT password
)
883 static const WCHAR MethodGetW
[] = {'G','E','T',0};
884 static const WCHAR MethodPutW
[] = {'P','U','T',0};
885 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
886 static const WCHAR MethodDeleteW
[] = {'D','E','L','E','T','E',0};
887 static const WCHAR MethodPropFindW
[] = {'P','R','O','P','F','I','N','D',0};
888 VARIANT str
, is_async
;
892 if (!method
|| !url
) return E_INVALIDARG
;
894 /* free previously set data */
896 IUri_Release(This
->uri
);
900 SysFreeString(This
->user
);
901 SysFreeString(This
->password
);
902 This
->user
= This
->password
= NULL
;
903 free_request_headers(This
);
905 if (!strcmpiW(method
, MethodGetW
))
907 This
->verb
= BINDVERB_GET
;
909 else if (!strcmpiW(method
, MethodPutW
))
911 This
->verb
= BINDVERB_PUT
;
913 else if (!strcmpiW(method
, MethodPostW
))
915 This
->verb
= BINDVERB_POST
;
917 else if (!strcmpiW(method
, MethodDeleteW
) ||
918 !strcmpiW(method
, MethodPropFindW
))
920 This
->verb
= BINDVERB_CUSTOM
;
921 SysReAllocString(&This
->custom
, method
);
925 FIXME("unsupported request type %s\n", debugstr_w(method
));
931 hr
= CoInternetCombineUrlEx(This
->base_uri
, url
, 0, &uri
, 0);
933 hr
= CreateUri(url
, 0, 0, &uri
);
935 WARN("Could not create IUri object: %08x\n", hr
);
939 hr
= verify_uri(This
, uri
);
946 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
948 This
->user
= V_BSTR(&str
);
951 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
953 This
->password
= V_BSTR(&str
);
955 /* add authentication info */
956 if (This
->user
&& *This
->user
)
958 IUriBuilder
*builder
;
960 hr
= CreateIUriBuilder(uri
, 0, 0, &builder
);
965 IUriBuilder_SetUserName(builder
, This
->user
);
966 IUriBuilder_SetPassword(builder
, This
->password
);
967 hr
= IUriBuilder_CreateUri(builder
, -1, 0, 0, &full_uri
);
974 WARN("failed to create modified uri, 0x%08x\n", hr
);
975 IUriBuilder_Release(builder
);
978 WARN("IUriBuilder creation failed, 0x%08x\n", hr
);
983 VariantInit(&is_async
);
984 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
985 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
);
987 httprequest_setreadystate(This
, READYSTATE_LOADING
);
992 static HRESULT
httprequest_setRequestHeader(httprequest
*This
, BSTR header
, BSTR value
)
994 struct httpheader
*entry
;
996 if (!header
|| !*header
) return E_INVALIDARG
;
997 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
998 if (!value
) return E_INVALIDARG
;
1000 /* replace existing header value if already added */
1001 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct httpheader
, entry
)
1003 if (lstrcmpW(entry
->header
, header
) == 0)
1005 LONG length
= SysStringLen(entry
->value
);
1008 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
1011 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
1017 entry
= heap_alloc(sizeof(*entry
));
1018 if (!entry
) return E_OUTOFMEMORY
;
1021 entry
->header
= SysAllocString(header
);
1022 entry
->value
= SysAllocString(value
);
1024 /* header length including null terminator */
1025 This
->reqheader_size
+= SysStringLen(entry
->header
) + sizeof(colspaceW
)/sizeof(WCHAR
) +
1026 SysStringLen(entry
->value
) + sizeof(crlfW
)/sizeof(WCHAR
) - 1;
1028 list_add_head(&This
->reqheaders
, &entry
->entry
);
1033 static HRESULT
httprequest_getResponseHeader(httprequest
*This
, BSTR header
, BSTR
*value
)
1035 struct httpheader
*entry
;
1037 if (!header
) return E_INVALIDARG
;
1038 if (!value
) return E_POINTER
;
1040 if (This
->raw_respheaders
&& list_empty(&This
->respheaders
))
1044 ptr
= line
= This
->raw_respheaders
;
1047 if (*ptr
== '\r' && *(ptr
+1) == '\n')
1049 add_response_header(This
, line
, ptr
-line
);
1050 ptr
++; line
= ++ptr
;
1057 LIST_FOR_EACH_ENTRY(entry
, &This
->respheaders
, struct httpheader
, entry
)
1059 if (!strcmpiW(entry
->header
, header
))
1061 *value
= SysAllocString(entry
->value
);
1062 TRACE("header value %s\n", debugstr_w(*value
));
1070 static HRESULT
httprequest_getAllResponseHeaders(httprequest
*This
, BSTR
*respheaders
)
1072 if (!respheaders
) return E_POINTER
;
1074 *respheaders
= SysAllocString(This
->raw_respheaders
);
1079 static HRESULT
httprequest_send(httprequest
*This
, VARIANT body
)
1081 BindStatusCallback
*bsc
= NULL
;
1084 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
1086 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
1088 /* success path to detach it is OnStopBinding call */
1089 BindStatusCallback_Detach(bsc
);
1094 static HRESULT
httprequest_abort(httprequest
*This
)
1096 BindStatusCallback_Detach(This
->bsc
);
1098 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
1103 static HRESULT
httprequest_get_status(httprequest
*This
, LONG
*status
)
1105 if (!status
) return E_POINTER
;
1107 *status
= This
->status
;
1109 return This
->state
== READYSTATE_COMPLETE
? S_OK
: E_FAIL
;
1112 static HRESULT
httprequest_get_statusText(httprequest
*This
, BSTR
*status
)
1114 if (!status
) return E_POINTER
;
1115 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1117 *status
= SysAllocString(This
->status_text
);
1122 static HRESULT
httprequest_get_responseText(httprequest
*This
, BSTR
*body
)
1127 if (!body
) return E_POINTER
;
1128 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1130 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1133 xmlChar
*ptr
= GlobalLock(hglobal
);
1134 DWORD size
= GlobalSize(hglobal
);
1135 xmlCharEncoding encoding
= XML_CHAR_ENCODING_UTF8
;
1137 /* try to determine data encoding */
1140 encoding
= xmlDetectCharEncoding(ptr
, 4);
1141 TRACE("detected encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1142 if ( encoding
!= XML_CHAR_ENCODING_UTF8
&&
1143 encoding
!= XML_CHAR_ENCODING_UTF16LE
&&
1144 encoding
!= XML_CHAR_ENCODING_NONE
)
1146 FIXME("unsupported encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1147 GlobalUnlock(hglobal
);
1152 /* without BOM assume UTF-8 */
1153 if (encoding
== XML_CHAR_ENCODING_UTF8
||
1154 encoding
== XML_CHAR_ENCODING_NONE
)
1156 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)ptr
, size
, NULL
, 0);
1158 *body
= SysAllocStringLen(NULL
, length
);
1160 MultiByteToWideChar( CP_UTF8
, 0, (LPCSTR
)ptr
, size
, *body
, length
);
1163 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
1165 if (!*body
) hr
= E_OUTOFMEMORY
;
1166 GlobalUnlock(hglobal
);
1172 static HRESULT
httprequest_get_responseXML(httprequest
*This
, IDispatch
**body
)
1174 IXMLDOMDocument3
*doc
;
1178 if (!body
) return E_INVALIDARG
;
1179 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1181 hr
= DOMDocument_create(MSXML_DEFAULT
, (void**)&doc
);
1182 if (hr
!= S_OK
) return hr
;
1184 hr
= httprequest_get_responseText(This
, &str
);
1189 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
1193 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
1194 IXMLDOMDocument3_Release(doc
);
1199 static HRESULT
httprequest_get_responseBody(httprequest
*This
, VARIANT
*body
)
1204 if (!body
) return E_INVALIDARG
;
1205 V_VT(body
) = VT_EMPTY
;
1207 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1209 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1212 void *ptr
= GlobalLock(hglobal
);
1213 DWORD size
= GlobalSize(hglobal
);
1215 SAFEARRAYBOUND bound
;
1219 bound
.cElements
= size
;
1220 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
1226 V_VT(body
) = VT_ARRAY
| VT_UI1
;
1227 V_ARRAY(body
) = array
;
1229 hr
= SafeArrayAccessData(array
, &dest
);
1232 memcpy(dest
, ptr
, size
);
1233 SafeArrayUnaccessData(array
);
1243 GlobalUnlock(hglobal
);
1249 static HRESULT
httprequest_get_responseStream(httprequest
*This
, VARIANT
*body
)
1255 if (!body
) return E_INVALIDARG
;
1256 V_VT(body
) = VT_EMPTY
;
1258 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1260 hr
= IStream_Clone(This
->bsc
->stream
, &stream
);
1263 IStream_Seek(stream
, move
, STREAM_SEEK_SET
, NULL
);
1265 V_VT(body
) = VT_UNKNOWN
;
1266 V_UNKNOWN(body
) = (IUnknown
*)stream
;
1271 static HRESULT
httprequest_get_readyState(httprequest
*This
, LONG
*state
)
1273 if (!state
) return E_POINTER
;
1275 *state
= This
->state
;
1279 static HRESULT
httprequest_put_onreadystatechange(httprequest
*This
, IDispatch
*sink
)
1281 if (This
->sink
) IDispatch_Release(This
->sink
);
1282 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1287 static void httprequest_release(httprequest
*This
)
1290 IUnknown_Release( This
->site
);
1292 IUri_Release(This
->uri
);
1294 IUri_Release(This
->base_uri
);
1296 SysFreeString(This
->custom
);
1297 SysFreeString(This
->user
);
1298 SysFreeString(This
->password
);
1300 /* cleanup headers lists */
1301 free_request_headers(This
);
1302 free_response_headers(This
);
1303 SysFreeString(This
->status_text
);
1305 /* detach callback object */
1306 BindStatusCallback_Detach(This
->bsc
);
1308 if (This
->sink
) IDispatch_Release(This
->sink
);
1311 static HRESULT WINAPI
XMLHTTPRequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
1313 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1314 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1316 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1317 IsEqualGUID( riid
, &IID_IDispatch
) ||
1318 IsEqualGUID( riid
, &IID_IUnknown
) )
1322 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
1324 *ppvObject
= &This
->IObjectWithSite_iface
;
1326 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
1328 *ppvObject
= &This
->IObjectSafety_iface
;
1332 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1334 return E_NOINTERFACE
;
1337 IXMLHTTPRequest_AddRef( iface
);
1342 static ULONG WINAPI
XMLHTTPRequest_AddRef(IXMLHTTPRequest
*iface
)
1344 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1345 ULONG ref
= InterlockedIncrement( &This
->ref
);
1346 TRACE("(%p)->(%u)\n", This
, ref
);
1350 static ULONG WINAPI
XMLHTTPRequest_Release(IXMLHTTPRequest
*iface
)
1352 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1353 ULONG ref
= InterlockedDecrement( &This
->ref
);
1355 TRACE("(%p)->(%u)\n", This
, ref
);
1359 httprequest_release( This
);
1366 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1368 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1370 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1377 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
1378 LCID lcid
, ITypeInfo
**ppTInfo
)
1380 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1382 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1384 return get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
1387 static HRESULT WINAPI
XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
1388 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1390 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1391 ITypeInfo
*typeinfo
;
1394 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1397 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1398 return E_INVALIDARG
;
1400 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1403 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1404 ITypeInfo_Release(typeinfo
);
1410 static HRESULT WINAPI
XMLHTTPRequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1411 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1412 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1414 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1415 ITypeInfo
*typeinfo
;
1418 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1419 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1421 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1424 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1425 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1426 ITypeInfo_Release(typeinfo
);
1432 static HRESULT WINAPI
XMLHTTPRequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1433 VARIANT async
, VARIANT user
, VARIANT password
)
1435 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1436 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1437 debugstr_variant(&async
));
1438 return httprequest_open(This
, method
, url
, async
, user
, password
);
1441 static HRESULT WINAPI
XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1443 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1444 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1445 return httprequest_setRequestHeader(This
, header
, value
);
1448 static HRESULT WINAPI
XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1450 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1451 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1452 return httprequest_getResponseHeader(This
, header
, value
);
1455 static HRESULT WINAPI
XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1457 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1458 TRACE("(%p)->(%p)\n", This
, respheaders
);
1459 return httprequest_getAllResponseHeaders(This
, respheaders
);
1462 static HRESULT WINAPI
XMLHTTPRequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
1464 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1465 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1466 return httprequest_send(This
, body
);
1469 static HRESULT WINAPI
XMLHTTPRequest_abort(IXMLHTTPRequest
*iface
)
1471 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1472 TRACE("(%p)\n", This
);
1473 return httprequest_abort(This
);
1476 static HRESULT WINAPI
XMLHTTPRequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
1478 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1479 TRACE("(%p)->(%p)\n", This
, status
);
1480 return httprequest_get_status(This
, status
);
1483 static HRESULT WINAPI
XMLHTTPRequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*status
)
1485 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1486 TRACE("(%p)->(%p)\n", This
, status
);
1487 return httprequest_get_statusText(This
, status
);
1490 static HRESULT WINAPI
XMLHTTPRequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
1492 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1493 TRACE("(%p)->(%p)\n", This
, body
);
1494 return httprequest_get_responseXML(This
, body
);
1497 static HRESULT WINAPI
XMLHTTPRequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
1499 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1500 TRACE("(%p)->(%p)\n", This
, body
);
1501 return httprequest_get_responseText(This
, body
);
1504 static HRESULT WINAPI
XMLHTTPRequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1506 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1507 TRACE("(%p)->(%p)\n", This
, body
);
1508 return httprequest_get_responseBody(This
, body
);
1511 static HRESULT WINAPI
XMLHTTPRequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1513 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1514 TRACE("(%p)->(%p)\n", This
, body
);
1515 return httprequest_get_responseStream(This
, body
);
1518 static HRESULT WINAPI
XMLHTTPRequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
1520 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1521 TRACE("(%p)->(%p)\n", This
, state
);
1522 return httprequest_get_readyState(This
, state
);
1525 static HRESULT WINAPI
XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
1527 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1528 TRACE("(%p)->(%p)\n", This
, sink
);
1529 return httprequest_put_onreadystatechange(This
, sink
);
1532 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl
=
1534 XMLHTTPRequest_QueryInterface
,
1535 XMLHTTPRequest_AddRef
,
1536 XMLHTTPRequest_Release
,
1537 XMLHTTPRequest_GetTypeInfoCount
,
1538 XMLHTTPRequest_GetTypeInfo
,
1539 XMLHTTPRequest_GetIDsOfNames
,
1540 XMLHTTPRequest_Invoke
,
1541 XMLHTTPRequest_open
,
1542 XMLHTTPRequest_setRequestHeader
,
1543 XMLHTTPRequest_getResponseHeader
,
1544 XMLHTTPRequest_getAllResponseHeaders
,
1545 XMLHTTPRequest_send
,
1546 XMLHTTPRequest_abort
,
1547 XMLHTTPRequest_get_status
,
1548 XMLHTTPRequest_get_statusText
,
1549 XMLHTTPRequest_get_responseXML
,
1550 XMLHTTPRequest_get_responseText
,
1551 XMLHTTPRequest_get_responseBody
,
1552 XMLHTTPRequest_get_responseStream
,
1553 XMLHTTPRequest_get_readyState
,
1554 XMLHTTPRequest_put_onreadystatechange
1557 /* IObjectWithSite */
1558 static HRESULT WINAPI
1559 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1561 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1562 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppvObject
);
1565 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1567 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1568 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1571 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1573 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1574 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1577 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1579 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1581 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1586 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1589 static void get_base_uri(httprequest
*This
)
1591 IServiceProvider
*provider
;
1592 IHTMLDocument2
*doc
;
1597 hr
= IUnknown_QueryInterface(This
->site
, &IID_IServiceProvider
, (void**)&provider
);
1601 hr
= IServiceProvider_QueryService(provider
, &SID_SContainerDispatch
, &IID_IHTMLDocument2
, (void**)&doc
);
1603 hr
= IServiceProvider_QueryService(provider
, &SID_SInternetHostSecurityManager
, &IID_IHTMLDocument2
, (void**)&doc
);
1604 IServiceProvider_Release(provider
);
1608 hr
= IHTMLDocument2_get_URL(doc
, &url
);
1609 IHTMLDocument2_Release(doc
);
1610 if(FAILED(hr
) || !url
|| !*url
)
1613 TRACE("host url %s\n", debugstr_w(url
));
1615 hr
= CreateUri(url
, 0, 0, &uri
);
1620 This
->base_uri
= uri
;
1623 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1625 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1627 TRACE("(%p)->(%p)\n", This
, punk
);
1630 IUnknown_Release( This
->site
);
1632 IUri_Release(This
->base_uri
);
1638 IUnknown_AddRef( punk
);
1645 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1647 httprequest_ObjectWithSite_QueryInterface
,
1648 httprequest_ObjectWithSite_AddRef
,
1649 httprequest_ObjectWithSite_Release
,
1650 httprequest_ObjectWithSite_SetSite
,
1651 httprequest_ObjectWithSite_GetSite
1655 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1657 httprequest
*This
= impl_from_IObjectSafety(iface
);
1658 return IXMLHTTPRequest_QueryInterface(&This
->IXMLHTTPRequest_iface
, riid
, ppv
);
1661 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1663 httprequest
*This
= impl_from_IObjectSafety(iface
);
1664 return IXMLHTTPRequest_AddRef(&This
->IXMLHTTPRequest_iface
);
1667 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1669 httprequest
*This
= impl_from_IObjectSafety(iface
);
1670 return IXMLHTTPRequest_Release(&This
->IXMLHTTPRequest_iface
);
1673 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1674 DWORD
*supported
, DWORD
*enabled
)
1676 httprequest
*This
= impl_from_IObjectSafety(iface
);
1678 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1680 if(!supported
|| !enabled
) return E_POINTER
;
1682 *supported
= safety_supported_options
;
1683 *enabled
= This
->safeopt
;
1688 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1689 DWORD mask
, DWORD enabled
)
1691 httprequest
*This
= impl_from_IObjectSafety(iface
);
1692 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
1694 if ((mask
& ~safety_supported_options
))
1697 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
1702 static const IObjectSafetyVtbl ObjectSafetyVtbl
= {
1703 httprequest_Safety_QueryInterface
,
1704 httprequest_Safety_AddRef
,
1705 httprequest_Safety_Release
,
1706 httprequest_Safety_GetInterfaceSafetyOptions
,
1707 httprequest_Safety_SetInterfaceSafetyOptions
1710 /* IServerXMLHTTPRequest */
1711 static HRESULT WINAPI
ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest
*iface
, REFIID riid
, void **obj
)
1713 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1715 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1717 if ( IsEqualGUID( riid
, &IID_IServerXMLHTTPRequest
) ||
1718 IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1719 IsEqualGUID( riid
, &IID_IDispatch
) ||
1720 IsEqualGUID( riid
, &IID_IUnknown
) )
1726 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1728 return E_NOINTERFACE
;
1731 IServerXMLHTTPRequest_AddRef( iface
);
1736 static ULONG WINAPI
ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest
*iface
)
1738 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1739 ULONG ref
= InterlockedIncrement( &This
->req
.ref
);
1740 TRACE("(%p)->(%u)\n", This
, ref
);
1744 static ULONG WINAPI
ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest
*iface
)
1746 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1747 ULONG ref
= InterlockedDecrement( &This
->req
.ref
);
1749 TRACE("(%p)->(%u)\n", This
, ref
);
1753 httprequest_release( &This
->req
);
1760 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1762 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1764 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1770 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest
*iface
, UINT iTInfo
,
1771 LCID lcid
, ITypeInfo
**ppTInfo
)
1773 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1775 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1777 return get_typeinfo(IServerXMLHTTPRequest_tid
, ppTInfo
);
1780 static HRESULT WINAPI
ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest
*iface
, REFIID riid
,
1781 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1783 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1784 ITypeInfo
*typeinfo
;
1787 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1790 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1791 return E_INVALIDARG
;
1793 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1796 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1797 ITypeInfo_Release(typeinfo
);
1803 static HRESULT WINAPI
ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1804 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1805 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1807 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1808 ITypeInfo
*typeinfo
;
1811 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1812 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1814 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1817 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IServerXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1818 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1819 ITypeInfo_Release(typeinfo
);
1825 static HRESULT WINAPI
ServerXMLHTTPRequest_open(IServerXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1826 VARIANT async
, VARIANT user
, VARIANT password
)
1828 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1829 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1830 debugstr_variant(&async
));
1831 return httprequest_open(&This
->req
, method
, url
, async
, user
, password
);
1834 static HRESULT WINAPI
ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1836 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1837 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1838 return httprequest_setRequestHeader(&This
->req
, header
, value
);
1841 static HRESULT WINAPI
ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1843 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1844 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1845 return httprequest_getResponseHeader(&This
->req
, header
, value
);
1848 static HRESULT WINAPI
ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1850 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1851 TRACE("(%p)->(%p)\n", This
, respheaders
);
1852 return httprequest_getAllResponseHeaders(&This
->req
, respheaders
);
1855 static HRESULT WINAPI
ServerXMLHTTPRequest_send(IServerXMLHTTPRequest
*iface
, VARIANT body
)
1857 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1858 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1859 return httprequest_send(&This
->req
, body
);
1862 static HRESULT WINAPI
ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest
*iface
)
1864 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1865 TRACE("(%p)\n", This
);
1866 return httprequest_abort(&This
->req
);
1869 static HRESULT WINAPI
ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest
*iface
, LONG
*status
)
1871 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1872 TRACE("(%p)->(%p)\n", This
, status
);
1873 return httprequest_get_status(&This
->req
, status
);
1876 static HRESULT WINAPI
ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest
*iface
, BSTR
*status
)
1878 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1879 TRACE("(%p)->(%p)\n", This
, status
);
1880 return httprequest_get_statusText(&This
->req
, status
);
1883 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest
*iface
, IDispatch
**body
)
1885 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1886 TRACE("(%p)->(%p)\n", This
, body
);
1887 return httprequest_get_responseXML(&This
->req
, body
);
1890 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest
*iface
, BSTR
*body
)
1892 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1893 TRACE("(%p)->(%p)\n", This
, body
);
1894 return httprequest_get_responseText(&This
->req
, body
);
1897 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1899 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1900 TRACE("(%p)->(%p)\n", This
, body
);
1901 return httprequest_get_responseBody(&This
->req
, body
);
1904 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1906 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1907 TRACE("(%p)->(%p)\n", This
, body
);
1908 return httprequest_get_responseStream(&This
->req
, body
);
1911 static HRESULT WINAPI
ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest
*iface
, LONG
*state
)
1913 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1914 TRACE("(%p)->(%p)\n", This
, state
);
1915 return httprequest_get_readyState(&This
->req
, state
);
1918 static HRESULT WINAPI
ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest
*iface
, IDispatch
*sink
)
1920 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1921 TRACE("(%p)->(%p)\n", This
, sink
);
1922 return httprequest_put_onreadystatechange(&This
->req
, sink
);
1925 static HRESULT WINAPI
ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest
*iface
, LONG resolveTimeout
, LONG connectTimeout
,
1926 LONG sendTimeout
, LONG receiveTimeout
)
1928 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1929 FIXME("(%p)->(%d %d %d %d): stub\n", This
, resolveTimeout
, connectTimeout
, sendTimeout
, receiveTimeout
);
1933 static HRESULT WINAPI
ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest
*iface
, VARIANT timeout
, VARIANT_BOOL
*isSuccessful
)
1935 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1936 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_variant(&timeout
), isSuccessful
);
1940 static HRESULT WINAPI
ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT
*value
)
1942 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1943 FIXME("(%p)->(%d %p): stub\n", This
, option
, value
);
1947 static HRESULT WINAPI
ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT value
)
1949 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1950 FIXME("(%p)->(%d %s): stub\n", This
, option
, debugstr_variant(&value
));
1954 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl
=
1956 ServerXMLHTTPRequest_QueryInterface
,
1957 ServerXMLHTTPRequest_AddRef
,
1958 ServerXMLHTTPRequest_Release
,
1959 ServerXMLHTTPRequest_GetTypeInfoCount
,
1960 ServerXMLHTTPRequest_GetTypeInfo
,
1961 ServerXMLHTTPRequest_GetIDsOfNames
,
1962 ServerXMLHTTPRequest_Invoke
,
1963 ServerXMLHTTPRequest_open
,
1964 ServerXMLHTTPRequest_setRequestHeader
,
1965 ServerXMLHTTPRequest_getResponseHeader
,
1966 ServerXMLHTTPRequest_getAllResponseHeaders
,
1967 ServerXMLHTTPRequest_send
,
1968 ServerXMLHTTPRequest_abort
,
1969 ServerXMLHTTPRequest_get_status
,
1970 ServerXMLHTTPRequest_get_statusText
,
1971 ServerXMLHTTPRequest_get_responseXML
,
1972 ServerXMLHTTPRequest_get_responseText
,
1973 ServerXMLHTTPRequest_get_responseBody
,
1974 ServerXMLHTTPRequest_get_responseStream
,
1975 ServerXMLHTTPRequest_get_readyState
,
1976 ServerXMLHTTPRequest_put_onreadystatechange
,
1977 ServerXMLHTTPRequest_setTimeouts
,
1978 ServerXMLHTTPRequest_waitForResponse
,
1979 ServerXMLHTTPRequest_getOption
,
1980 ServerXMLHTTPRequest_setOption
1983 static void init_httprequest(httprequest
*req
)
1985 req
->IXMLHTTPRequest_iface
.lpVtbl
= &XMLHTTPRequestVtbl
;
1986 req
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
1987 req
->IObjectSafety_iface
.lpVtbl
= &ObjectSafetyVtbl
;
1993 req
->uri
= req
->base_uri
= NULL
;
1994 req
->user
= req
->password
= NULL
;
1996 req
->state
= READYSTATE_UNINITIALIZED
;
2001 req
->status_text
= NULL
;
2002 req
->reqheader_size
= 0;
2003 req
->raw_respheaders
= NULL
;
2004 req
->use_utf8_content
= FALSE
;
2006 list_init(&req
->reqheaders
);
2007 list_init(&req
->respheaders
);
2013 HRESULT
XMLHTTPRequest_create(void **obj
)
2017 TRACE("(%p)\n", obj
);
2019 req
= heap_alloc( sizeof (*req
) );
2021 return E_OUTOFMEMORY
;
2023 init_httprequest(req
);
2024 *obj
= &req
->IXMLHTTPRequest_iface
;
2026 TRACE("returning iface %p\n", *obj
);
2031 HRESULT
ServerXMLHTTP_create(void **obj
)
2035 TRACE("(%p)\n", obj
);
2037 req
= heap_alloc( sizeof (*req
) );
2039 return E_OUTOFMEMORY
;
2041 init_httprequest(&req
->req
);
2042 req
->IServerXMLHTTPRequest_iface
.lpVtbl
= &ServerXMLHTTPRequestVtbl
;
2044 *obj
= &req
->IServerXMLHTTPRequest_iface
;
2046 TRACE("returning iface %p\n", *obj
);
2053 HRESULT
XMLHTTPRequest_create(void **ppObj
)
2055 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
2056 "libxml2 support was not present at compile time.\n");
2060 HRESULT
ServerXMLHTTP_create(void **obj
)
2062 MESSAGE("This program tried to use a ServerXMLHTTP object, but\n"
2063 "libxml2 support was not present at compile time.\n");