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
30 #include <wine/list.h>
34 static const WCHAR colspaceW
[] = {':',' ',0};
35 static const WCHAR crlfW
[] = {'\r','\n',0};
36 static const DWORD safety_supported_options
=
37 INTERFACESAFE_FOR_UNTRUSTED_CALLER
|
38 INTERFACESAFE_FOR_UNTRUSTED_DATA
|
39 INTERFACE_USES_SECURITY_MANAGER
;
41 typedef struct BindStatusCallback BindStatusCallback
;
52 IXMLHTTPRequest IXMLHTTPRequest_iface
;
53 IObjectWithSite IObjectWithSite_iface
;
54 IObjectSafety IObjectSafety_iface
;
66 struct list reqheaders
;
67 /* cached resulting custom request headers string length in WCHARs */
69 /* use UTF-8 content type */
70 BOOL use_utf8_content
;
72 /* response headers */
73 struct list respheaders
;
81 BindStatusCallback
*bsc
;
95 IServerXMLHTTPRequest IServerXMLHTTPRequest_iface
;
99 static inline httprequest
*impl_from_IXMLHTTPRequest( IXMLHTTPRequest
*iface
)
101 return CONTAINING_RECORD(iface
, httprequest
, IXMLHTTPRequest_iface
);
104 static inline httprequest
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
106 return CONTAINING_RECORD(iface
, httprequest
, IObjectWithSite_iface
);
109 static inline httprequest
*impl_from_IObjectSafety(IObjectSafety
*iface
)
111 return CONTAINING_RECORD(iface
, httprequest
, IObjectSafety_iface
);
114 static inline serverhttp
*impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest
*iface
)
116 return CONTAINING_RECORD(iface
, serverhttp
, IServerXMLHTTPRequest_iface
);
119 static void httprequest_setreadystate(httprequest
*This
, READYSTATE state
)
121 READYSTATE last
= This
->state
;
122 static const char* readystates
[] = {
123 "READYSTATE_UNINITIALIZED",
124 "READYSTATE_LOADING",
126 "READYSTATE_INTERACTIVE",
127 "READYSTATE_COMPLETE"};
131 TRACE("state %s\n", readystates
[state
]);
133 if (This
->sink
&& last
!= state
)
137 memset(¶ms
, 0, sizeof(params
));
138 IDispatch_Invoke(This
->sink
, 0, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, ¶ms
, 0, 0, 0);
142 static void free_response_headers(httprequest
*This
)
144 struct httpheader
*header
, *header2
;
146 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->respheaders
, struct httpheader
, entry
)
148 list_remove(&header
->entry
);
149 SysFreeString(header
->header
);
150 SysFreeString(header
->value
);
154 SysFreeString(This
->raw_respheaders
);
155 This
->raw_respheaders
= NULL
;
158 struct BindStatusCallback
160 IBindStatusCallback IBindStatusCallback_iface
;
161 IHttpNegotiate IHttpNegotiate_iface
;
162 IAuthenticate IAuthenticate_iface
;
166 httprequest
*request
;
171 /* request body data */
175 static inline BindStatusCallback
*impl_from_IBindStatusCallback( IBindStatusCallback
*iface
)
177 return CONTAINING_RECORD(iface
, BindStatusCallback
, IBindStatusCallback_iface
);
180 static inline BindStatusCallback
*impl_from_IHttpNegotiate( IHttpNegotiate
*iface
)
182 return CONTAINING_RECORD(iface
, BindStatusCallback
, IHttpNegotiate_iface
);
185 static inline BindStatusCallback
*impl_from_IAuthenticate( IAuthenticate
*iface
)
187 return CONTAINING_RECORD(iface
, BindStatusCallback
, IAuthenticate_iface
);
190 static void BindStatusCallback_Detach(BindStatusCallback
*bsc
)
194 if (bsc
->binding
) IBinding_Abort(bsc
->binding
);
195 bsc
->request
->bsc
= NULL
;
197 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
201 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
202 REFIID riid
, void **ppv
)
204 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
208 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
210 if (IsEqualGUID(&IID_IUnknown
, riid
) ||
211 IsEqualGUID(&IID_IBindStatusCallback
, riid
))
213 *ppv
= &This
->IBindStatusCallback_iface
;
215 else if (IsEqualGUID(&IID_IHttpNegotiate
, riid
))
217 *ppv
= &This
->IHttpNegotiate_iface
;
219 else if (IsEqualGUID(&IID_IAuthenticate
, riid
))
221 *ppv
= &This
->IAuthenticate_iface
;
223 else if (IsEqualGUID(&IID_IServiceProvider
, riid
) ||
224 IsEqualGUID(&IID_IBindStatusCallbackEx
, riid
) ||
225 IsEqualGUID(&IID_IInternetProtocol
, riid
) ||
226 IsEqualGUID(&IID_IHttpNegotiate2
, riid
))
228 return E_NOINTERFACE
;
233 IBindStatusCallback_AddRef(iface
);
237 FIXME("Unsupported riid = %s\n", debugstr_guid(riid
));
239 return E_NOINTERFACE
;
242 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
244 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
245 LONG ref
= InterlockedIncrement(&This
->ref
);
247 TRACE("(%p) ref = %d\n", This
, ref
);
252 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
254 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
255 LONG ref
= InterlockedDecrement(&This
->ref
);
257 TRACE("(%p) ref = %d\n", This
, ref
);
261 if (This
->binding
) IBinding_Release(This
->binding
);
262 if (This
->stream
) IStream_Release(This
->stream
);
263 if (This
->body
) GlobalFree(This
->body
);
270 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
271 DWORD reserved
, IBinding
*pbind
)
273 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
275 TRACE("(%p)->(%d %p)\n", This
, reserved
, pbind
);
277 if (!pbind
) return E_INVALIDARG
;
279 This
->binding
= pbind
;
280 IBinding_AddRef(pbind
);
282 httprequest_setreadystate(This
->request
, READYSTATE_LOADED
);
284 return CreateStreamOnHGlobal(NULL
, TRUE
, &This
->stream
);
287 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pPriority
)
289 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
291 TRACE("(%p)->(%p)\n", This
, pPriority
);
296 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
298 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
300 TRACE("(%p)->(%d)\n", This
, reserved
);
305 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
306 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
308 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
310 TRACE("(%p)->(%u %u %u %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
311 debugstr_w(szStatusText
));
316 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
317 HRESULT hr
, LPCWSTR error
)
319 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
321 TRACE("(%p)->(0x%08x %s)\n", This
, hr
, debugstr_w(error
));
325 IBinding_Release(This
->binding
);
326 This
->binding
= NULL
;
331 BindStatusCallback_Detach(This
->request
->bsc
);
332 This
->request
->bsc
= This
;
333 httprequest_setreadystate(This
->request
, READYSTATE_COMPLETE
);
339 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
340 DWORD
*bind_flags
, BINDINFO
*pbindinfo
)
342 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
344 TRACE("(%p)->(%p %p)\n", This
, bind_flags
, pbindinfo
);
347 if (This
->request
->async
) *bind_flags
|= BINDF_ASYNCHRONOUS
;
349 if (This
->request
->verb
!= BINDVERB_GET
&& This
->body
)
351 pbindinfo
->stgmedData
.tymed
= TYMED_HGLOBAL
;
352 pbindinfo
->stgmedData
.u
.hGlobal
= This
->body
;
353 pbindinfo
->cbstgmedData
= GlobalSize(This
->body
);
354 /* callback owns passed body pointer */
355 IBindStatusCallback_QueryInterface(iface
, &IID_IUnknown
, (void**)&pbindinfo
->stgmedData
.pUnkForRelease
);
358 pbindinfo
->dwBindVerb
= This
->request
->verb
;
359 if (This
->request
->verb
== BINDVERB_CUSTOM
)
361 pbindinfo
->szCustomVerb
= CoTaskMemAlloc(SysStringByteLen(This
->request
->custom
));
362 strcpyW(pbindinfo
->szCustomVerb
, This
->request
->custom
);
368 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
369 DWORD flags
, DWORD size
, FORMATETC
*format
, STGMEDIUM
*stgmed
)
371 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
376 TRACE("(%p)->(%08x %d %p %p)\n", This
, flags
, size
, format
, stgmed
);
380 hr
= IStream_Read(stgmed
->u
.pstm
, buf
, sizeof(buf
), &read
);
381 if (hr
!= S_OK
) break;
383 hr
= IStream_Write(This
->stream
, buf
, read
, &written
);
384 } while((hr
== S_OK
) && written
!= 0 && read
!= 0);
386 httprequest_setreadystate(This
->request
, READYSTATE_INTERACTIVE
);
391 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
392 REFIID riid
, IUnknown
*punk
)
394 BindStatusCallback
*This
= impl_from_IBindStatusCallback(iface
);
396 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), punk
);
401 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
402 BindStatusCallback_QueryInterface
,
403 BindStatusCallback_AddRef
,
404 BindStatusCallback_Release
,
405 BindStatusCallback_OnStartBinding
,
406 BindStatusCallback_GetPriority
,
407 BindStatusCallback_OnLowResource
,
408 BindStatusCallback_OnProgress
,
409 BindStatusCallback_OnStopBinding
,
410 BindStatusCallback_GetBindInfo
,
411 BindStatusCallback_OnDataAvailable
,
412 BindStatusCallback_OnObjectAvailable
415 static HRESULT WINAPI
BSCHttpNegotiate_QueryInterface(IHttpNegotiate
*iface
,
416 REFIID riid
, void **ppv
)
418 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
419 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
422 static ULONG WINAPI
BSCHttpNegotiate_AddRef(IHttpNegotiate
*iface
)
424 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
425 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
428 static ULONG WINAPI
BSCHttpNegotiate_Release(IHttpNegotiate
*iface
)
430 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
431 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
434 static HRESULT WINAPI
BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate
*iface
,
435 LPCWSTR url
, LPCWSTR headers
, DWORD reserved
, LPWSTR
*add_headers
)
437 static const WCHAR content_type_utf8W
[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ',
438 't','e','x','t','/','p','l','a','i','n',';','c','h','a','r','s','e','t','=','u','t','f','-','8','\r','\n',0};
440 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
441 const struct httpheader
*entry
;
445 TRACE("(%p)->(%s %s %d %p)\n", This
, debugstr_w(url
), debugstr_w(headers
), reserved
, add_headers
);
449 if (This
->request
->use_utf8_content
)
450 size
= sizeof(content_type_utf8W
);
452 if (!list_empty(&This
->request
->reqheaders
))
453 size
+= This
->request
->reqheader_size
*sizeof(WCHAR
);
455 if (!size
) return S_OK
;
457 buff
= CoTaskMemAlloc(size
);
458 if (!buff
) return E_OUTOFMEMORY
;
461 if (This
->request
->use_utf8_content
)
463 lstrcpyW(ptr
, content_type_utf8W
);
464 ptr
+= sizeof(content_type_utf8W
)/sizeof(WCHAR
)-1;
468 LIST_FOR_EACH_ENTRY(entry
, &This
->request
->reqheaders
, struct httpheader
, entry
)
470 lstrcpyW(ptr
, entry
->header
);
471 ptr
+= SysStringLen(entry
->header
);
473 lstrcpyW(ptr
, colspaceW
);
474 ptr
+= sizeof(colspaceW
)/sizeof(WCHAR
)-1;
476 lstrcpyW(ptr
, entry
->value
);
477 ptr
+= SysStringLen(entry
->value
);
479 lstrcpyW(ptr
, crlfW
);
480 ptr
+= sizeof(crlfW
)/sizeof(WCHAR
)-1;
488 static void add_response_header(httprequest
*This
, const WCHAR
*data
, int len
)
490 struct httpheader
*entry
;
491 const WCHAR
*ptr
= data
;
498 header
= SysAllocStringLen(data
, ptr
-data
);
499 /* skip leading spaces for a value */
500 while (*++ptr
== ' ')
502 value
= SysAllocStringLen(ptr
, len
-(ptr
-data
));
511 TRACE("got header %s:%s\n", debugstr_w(header
), debugstr_w(value
));
513 entry
= heap_alloc(sizeof(*entry
));
514 entry
->header
= header
;
515 entry
->value
= value
;
516 list_add_head(&This
->respheaders
, &entry
->entry
);
519 static HRESULT WINAPI
BSCHttpNegotiate_OnResponse(IHttpNegotiate
*iface
, DWORD code
,
520 LPCWSTR resp_headers
, LPCWSTR req_headers
, LPWSTR
*add_reqheaders
)
522 BindStatusCallback
*This
= impl_from_IHttpNegotiate(iface
);
524 TRACE("(%p)->(%d %s %s %p)\n", This
, code
, debugstr_w(resp_headers
),
525 debugstr_w(req_headers
), add_reqheaders
);
527 This
->request
->status
= code
;
528 /* store headers and status text */
529 free_response_headers(This
->request
);
530 SysFreeString(This
->request
->status_text
);
531 This
->request
->status_text
= NULL
;
534 const WCHAR
*ptr
, *line
, *status_text
;
536 ptr
= line
= resp_headers
;
538 /* skip HTTP-Version */
539 ptr
= strchrW(ptr
, ' ');
542 /* skip Status-Code */
543 ptr
= strchrW(++ptr
, ' ');
547 /* now it supposed to end with CRLF */
550 if (*ptr
== '\r' && *(ptr
+1) == '\n')
553 This
->request
->status_text
= SysAllocStringLen(status_text
, ptr
-status_text
);
554 TRACE("status text %s\n", debugstr_w(This
->request
->status_text
));
562 /* store as unparsed string for now */
563 This
->request
->raw_respheaders
= SysAllocString(line
);
569 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl
= {
570 BSCHttpNegotiate_QueryInterface
,
571 BSCHttpNegotiate_AddRef
,
572 BSCHttpNegotiate_Release
,
573 BSCHttpNegotiate_BeginningTransaction
,
574 BSCHttpNegotiate_OnResponse
577 static HRESULT WINAPI
Authenticate_QueryInterface(IAuthenticate
*iface
,
578 REFIID riid
, void **ppv
)
580 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
581 return IBindStatusCallback_QueryInterface(&This
->IBindStatusCallback_iface
, riid
, ppv
);
584 static ULONG WINAPI
Authenticate_AddRef(IAuthenticate
*iface
)
586 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
587 return IBindStatusCallback_AddRef(&This
->IBindStatusCallback_iface
);
590 static ULONG WINAPI
Authenticate_Release(IAuthenticate
*iface
)
592 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
593 return IBindStatusCallback_Release(&This
->IBindStatusCallback_iface
);
596 static HRESULT WINAPI
Authenticate_Authenticate(IAuthenticate
*iface
,
597 HWND
*hwnd
, LPWSTR
*username
, LPWSTR
*password
)
599 BindStatusCallback
*This
= impl_from_IAuthenticate(iface
);
600 httprequest
*request
= This
->request
;
602 TRACE("(%p)->(%p %p %p)\n", This
, hwnd
, username
, password
);
604 if (request
->user
&& *request
->user
)
606 if (hwnd
) *hwnd
= NULL
;
607 *username
= CoTaskMemAlloc(SysStringByteLen(request
->user
)+sizeof(WCHAR
));
608 *password
= CoTaskMemAlloc(SysStringByteLen(request
->password
)+sizeof(WCHAR
));
609 if (!*username
|| !*password
)
611 CoTaskMemFree(*username
);
612 CoTaskMemFree(*password
);
613 return E_OUTOFMEMORY
;
616 memcpy(*username
, request
->user
, SysStringByteLen(request
->user
)+sizeof(WCHAR
));
617 memcpy(*password
, request
->password
, SysStringByteLen(request
->password
)+sizeof(WCHAR
));
623 static const IAuthenticateVtbl AuthenticateVtbl
= {
624 Authenticate_QueryInterface
,
626 Authenticate_Release
,
627 Authenticate_Authenticate
630 static HRESULT
BindStatusCallback_create(httprequest
* This
, BindStatusCallback
**obj
, const VARIANT
*body
)
632 BindStatusCallback
*bsc
;
637 hr
= CreateBindCtx(0, &pbc
);
638 if (hr
!= S_OK
) return hr
;
640 bsc
= heap_alloc(sizeof(*bsc
));
643 IBindCtx_Release(pbc
);
644 return E_OUTOFMEMORY
;
647 bsc
->IBindStatusCallback_iface
.lpVtbl
= &BindStatusCallbackVtbl
;
648 bsc
->IHttpNegotiate_iface
.lpVtbl
= &BSCHttpNegotiateVtbl
;
649 bsc
->IAuthenticate_iface
.lpVtbl
= &AuthenticateVtbl
;
656 TRACE("(%p)->(%p)\n", This
, bsc
);
658 This
->use_utf8_content
= FALSE
;
660 if (This
->verb
!= BINDVERB_GET
)
662 void *send_data
, *ptr
;
663 SAFEARRAY
*sa
= NULL
;
665 if (V_VT(body
) == (VT_VARIANT
|VT_BYREF
))
666 body
= V_VARIANTREF(body
);
672 int len
= SysStringLen(V_BSTR(body
));
673 const WCHAR
*str
= V_BSTR(body
);
676 for (i
= 0; i
< len
; i
++)
685 size
= WideCharToMultiByte(cp
, 0, str
, len
, NULL
, 0, NULL
, NULL
);
686 if (!(ptr
= heap_alloc(size
)))
689 return E_OUTOFMEMORY
;
691 WideCharToMultiByte(cp
, 0, str
, len
, ptr
, size
, NULL
, NULL
);
692 if (cp
== CP_UTF8
) This
->use_utf8_content
= TRUE
;
695 case VT_ARRAY
|VT_UI1
:
698 if ((hr
= SafeArrayAccessData(sa
, (void **)&ptr
)) != S_OK
)
703 if ((hr
= SafeArrayGetUBound(sa
, 1, &size
)) != S_OK
)
705 SafeArrayUnaccessData(sa
);
713 FIXME("unsupported body data type %d\n", V_VT(body
));
725 bsc
->body
= GlobalAlloc(GMEM_FIXED
, size
);
728 if (V_VT(body
) == VT_BSTR
)
730 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
731 SafeArrayUnaccessData(sa
);
734 return E_OUTOFMEMORY
;
737 send_data
= GlobalLock(bsc
->body
);
738 memcpy(send_data
, ptr
, size
);
739 GlobalUnlock(bsc
->body
);
742 if (V_VT(body
) == VT_BSTR
)
744 else if (V_VT(body
) == (VT_ARRAY
|VT_UI1
))
745 SafeArrayUnaccessData(sa
);
748 hr
= RegisterBindStatusCallback(pbc
, &bsc
->IBindStatusCallback_iface
, NULL
, 0);
753 hr
= CreateURLMonikerEx2(NULL
, This
->uri
, &moniker
, URL_MK_UNIFORM
);
758 hr
= IMoniker_BindToStorage(moniker
, pbc
, NULL
, &IID_IStream
, (void**)&stream
);
759 IMoniker_Release(moniker
);
760 if (stream
) IStream_Release(stream
);
762 IBindCtx_Release(pbc
);
767 IBindStatusCallback_Release(&bsc
->IBindStatusCallback_iface
);
775 static HRESULT
verify_uri(httprequest
*This
, IUri
*uri
)
777 DWORD scheme
, base_scheme
;
778 BSTR host
, base_host
;
781 if(!(This
->safeopt
& INTERFACESAFE_FOR_UNTRUSTED_DATA
))
785 return E_ACCESSDENIED
;
787 hr
= IUri_GetScheme(uri
, &scheme
);
791 hr
= IUri_GetScheme(This
->base_uri
, &base_scheme
);
795 if(scheme
!= base_scheme
) {
796 WARN("Schemes don't match\n");
797 return E_ACCESSDENIED
;
800 if(scheme
== INTERNET_SCHEME_UNKNOWN
) {
801 FIXME("Unknown scheme\n");
802 return E_ACCESSDENIED
;
805 hr
= IUri_GetHost(uri
, &host
);
809 hr
= IUri_GetHost(This
->base_uri
, &base_host
);
811 if(strcmpiW(host
, base_host
)) {
812 WARN("Hosts don't match\n");
815 SysFreeString(base_host
);
822 static HRESULT
httprequest_open(httprequest
*This
, BSTR method
, BSTR url
,
823 VARIANT async
, VARIANT user
, VARIANT password
)
825 static const WCHAR MethodGetW
[] = {'G','E','T',0};
826 static const WCHAR MethodPutW
[] = {'P','U','T',0};
827 static const WCHAR MethodPostW
[] = {'P','O','S','T',0};
828 static const WCHAR MethodDeleteW
[] = {'D','E','L','E','T','E',0};
829 static const WCHAR MethodPropFindW
[] = {'P','R','O','P','F','I','N','D',0};
830 VARIANT str
, is_async
;
834 if (!method
|| !url
) return E_INVALIDARG
;
836 /* free previously set data */
838 IUri_Release(This
->uri
);
842 SysFreeString(This
->user
);
843 SysFreeString(This
->password
);
844 This
->user
= This
->password
= NULL
;
846 if (!strcmpiW(method
, MethodGetW
))
848 This
->verb
= BINDVERB_GET
;
850 else if (!strcmpiW(method
, MethodPutW
))
852 This
->verb
= BINDVERB_PUT
;
854 else if (!strcmpiW(method
, MethodPostW
))
856 This
->verb
= BINDVERB_POST
;
858 else if (!strcmpiW(method
, MethodDeleteW
) ||
859 !strcmpiW(method
, MethodPropFindW
))
861 This
->verb
= BINDVERB_CUSTOM
;
862 SysReAllocString(&This
->custom
, method
);
866 FIXME("unsupported request type %s\n", debugstr_w(method
));
872 hr
= CoInternetCombineUrlEx(This
->base_uri
, url
, 0, &uri
, 0);
874 hr
= CreateUri(url
, 0, 0, &uri
);
876 WARN("Could not create IUri object: %08x\n", hr
);
880 hr
= verify_uri(This
, uri
);
887 hr
= VariantChangeType(&str
, &user
, 0, VT_BSTR
);
889 This
->user
= V_BSTR(&str
);
892 hr
= VariantChangeType(&str
, &password
, 0, VT_BSTR
);
894 This
->password
= V_BSTR(&str
);
896 /* add authentication info */
897 if (This
->user
&& *This
->user
)
899 IUriBuilder
*builder
;
901 hr
= CreateIUriBuilder(uri
, 0, 0, &builder
);
906 IUriBuilder_SetUserName(builder
, This
->user
);
907 IUriBuilder_SetPassword(builder
, This
->password
);
908 hr
= IUriBuilder_CreateUri(builder
, -1, 0, 0, &full_uri
);
915 WARN("failed to create modified uri, 0x%08x\n", hr
);
916 IUriBuilder_Release(builder
);
919 WARN("IUriBuilder creation failed, 0x%08x\n", hr
);
924 VariantInit(&is_async
);
925 hr
= VariantChangeType(&is_async
, &async
, 0, VT_BOOL
);
926 This
->async
= hr
== S_OK
&& V_BOOL(&is_async
);
928 httprequest_setreadystate(This
, READYSTATE_LOADING
);
933 static HRESULT
httprequest_setRequestHeader(httprequest
*This
, BSTR header
, BSTR value
)
935 struct httpheader
*entry
;
937 if (!header
|| !*header
) return E_INVALIDARG
;
938 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
939 if (!value
) return E_INVALIDARG
;
941 /* replace existing header value if already added */
942 LIST_FOR_EACH_ENTRY(entry
, &This
->reqheaders
, struct httpheader
, entry
)
944 if (lstrcmpW(entry
->header
, header
) == 0)
946 LONG length
= SysStringLen(entry
->value
);
949 hr
= SysReAllocString(&entry
->value
, value
) ? S_OK
: E_OUTOFMEMORY
;
952 This
->reqheader_size
+= (SysStringLen(entry
->value
) - length
);
958 entry
= heap_alloc(sizeof(*entry
));
959 if (!entry
) return E_OUTOFMEMORY
;
962 entry
->header
= SysAllocString(header
);
963 entry
->value
= SysAllocString(value
);
965 /* header length including null terminator */
966 This
->reqheader_size
+= SysStringLen(entry
->header
) + sizeof(colspaceW
)/sizeof(WCHAR
) +
967 SysStringLen(entry
->value
) + sizeof(crlfW
)/sizeof(WCHAR
) - 1;
969 list_add_head(&This
->reqheaders
, &entry
->entry
);
974 static HRESULT
httprequest_getResponseHeader(httprequest
*This
, BSTR header
, BSTR
*value
)
976 struct httpheader
*entry
;
978 if (!header
) return E_INVALIDARG
;
979 if (!value
) return E_POINTER
;
981 if (This
->raw_respheaders
&& list_empty(&This
->respheaders
))
985 ptr
= line
= This
->raw_respheaders
;
988 if (*ptr
== '\r' && *(ptr
+1) == '\n')
990 add_response_header(This
, line
, ptr
-line
);
998 LIST_FOR_EACH_ENTRY(entry
, &This
->respheaders
, struct httpheader
, entry
)
1000 if (!strcmpiW(entry
->header
, header
))
1002 *value
= SysAllocString(entry
->value
);
1003 TRACE("header value %s\n", debugstr_w(*value
));
1011 static HRESULT
httprequest_getAllResponseHeaders(httprequest
*This
, BSTR
*respheaders
)
1013 if (!respheaders
) return E_POINTER
;
1015 *respheaders
= SysAllocString(This
->raw_respheaders
);
1020 static HRESULT
httprequest_send(httprequest
*This
, VARIANT body
)
1022 BindStatusCallback
*bsc
= NULL
;
1025 if (This
->state
!= READYSTATE_LOADING
) return E_FAIL
;
1027 hr
= BindStatusCallback_create(This
, &bsc
, &body
);
1029 /* success path to detach it is OnStopBinding call */
1030 BindStatusCallback_Detach(bsc
);
1035 static HRESULT
httprequest_abort(httprequest
*This
)
1037 BindStatusCallback_Detach(This
->bsc
);
1039 httprequest_setreadystate(This
, READYSTATE_UNINITIALIZED
);
1044 static HRESULT
httprequest_get_status(httprequest
*This
, LONG
*status
)
1046 if (!status
) return E_POINTER
;
1048 *status
= This
->status
;
1050 return This
->state
== READYSTATE_COMPLETE
? S_OK
: E_FAIL
;
1053 static HRESULT
httprequest_get_statusText(httprequest
*This
, BSTR
*status
)
1055 if (!status
) return E_POINTER
;
1056 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1058 *status
= SysAllocString(This
->status_text
);
1063 static HRESULT
httprequest_get_responseText(httprequest
*This
, BSTR
*body
)
1068 if (!body
) return E_POINTER
;
1069 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1071 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1074 xmlChar
*ptr
= GlobalLock(hglobal
);
1075 DWORD size
= GlobalSize(hglobal
);
1076 xmlCharEncoding encoding
= XML_CHAR_ENCODING_UTF8
;
1078 /* try to determine data encoding */
1081 encoding
= xmlDetectCharEncoding(ptr
, 4);
1082 TRACE("detected encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1083 if ( encoding
!= XML_CHAR_ENCODING_UTF8
&&
1084 encoding
!= XML_CHAR_ENCODING_UTF16LE
&&
1085 encoding
!= XML_CHAR_ENCODING_NONE
)
1087 FIXME("unsupported encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding
)));
1088 GlobalUnlock(hglobal
);
1093 /* without BOM assume UTF-8 */
1094 if (encoding
== XML_CHAR_ENCODING_UTF8
||
1095 encoding
== XML_CHAR_ENCODING_NONE
)
1097 DWORD length
= MultiByteToWideChar(CP_UTF8
, 0, (LPCSTR
)ptr
, size
, NULL
, 0);
1099 *body
= SysAllocStringLen(NULL
, length
);
1101 MultiByteToWideChar( CP_UTF8
, 0, (LPCSTR
)ptr
, size
, *body
, length
);
1104 *body
= SysAllocStringByteLen((LPCSTR
)ptr
, size
);
1106 if (!*body
) hr
= E_OUTOFMEMORY
;
1107 GlobalUnlock(hglobal
);
1113 static HRESULT
httprequest_get_responseXML(httprequest
*This
, IDispatch
**body
)
1115 IXMLDOMDocument3
*doc
;
1119 if (!body
) return E_INVALIDARG
;
1120 if (This
->state
!= READYSTATE_COMPLETE
) return E_FAIL
;
1122 hr
= DOMDocument_create(MSXML_DEFAULT
, NULL
, (void**)&doc
);
1123 if (hr
!= S_OK
) return hr
;
1125 hr
= httprequest_get_responseText(This
, &str
);
1130 hr
= IXMLDOMDocument3_loadXML(doc
, str
, &ok
);
1134 IXMLDOMDocument3_QueryInterface(doc
, &IID_IDispatch
, (void**)body
);
1135 IXMLDOMDocument3_Release(doc
);
1140 static HRESULT
httprequest_get_responseBody(httprequest
*This
, VARIANT
*body
)
1145 if (!body
) return E_INVALIDARG
;
1146 V_VT(body
) = VT_EMPTY
;
1148 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1150 hr
= GetHGlobalFromStream(This
->bsc
->stream
, &hglobal
);
1153 void *ptr
= GlobalLock(hglobal
);
1154 DWORD size
= GlobalSize(hglobal
);
1156 SAFEARRAYBOUND bound
;
1160 bound
.cElements
= size
;
1161 array
= SafeArrayCreate(VT_UI1
, 1, &bound
);
1167 V_VT(body
) = VT_ARRAY
| VT_UI1
;
1168 V_ARRAY(body
) = array
;
1170 hr
= SafeArrayAccessData(array
, &dest
);
1173 memcpy(dest
, ptr
, size
);
1174 SafeArrayUnaccessData(array
);
1184 GlobalUnlock(hglobal
);
1190 static HRESULT
httprequest_get_responseStream(httprequest
*This
, VARIANT
*body
)
1196 if (!body
) return E_INVALIDARG
;
1197 V_VT(body
) = VT_EMPTY
;
1199 if (This
->state
!= READYSTATE_COMPLETE
) return E_PENDING
;
1201 hr
= IStream_Clone(This
->bsc
->stream
, &stream
);
1204 IStream_Seek(stream
, move
, STREAM_SEEK_SET
, NULL
);
1206 V_VT(body
) = VT_UNKNOWN
;
1207 V_UNKNOWN(body
) = (IUnknown
*)stream
;
1212 static HRESULT
httprequest_get_readyState(httprequest
*This
, LONG
*state
)
1214 if (!state
) return E_POINTER
;
1216 *state
= This
->state
;
1220 static HRESULT
httprequest_put_onreadystatechange(httprequest
*This
, IDispatch
*sink
)
1222 if (This
->sink
) IDispatch_Release(This
->sink
);
1223 if ((This
->sink
= sink
)) IDispatch_AddRef(This
->sink
);
1228 static void httprequest_release(httprequest
*This
)
1230 struct httpheader
*header
, *header2
;
1233 IUnknown_Release( This
->site
);
1235 IUri_Release(This
->uri
);
1237 IUri_Release(This
->base_uri
);
1239 SysFreeString(This
->custom
);
1240 SysFreeString(This
->user
);
1241 SysFreeString(This
->password
);
1243 /* request headers */
1244 LIST_FOR_EACH_ENTRY_SAFE(header
, header2
, &This
->reqheaders
, struct httpheader
, entry
)
1246 list_remove(&header
->entry
);
1247 SysFreeString(header
->header
);
1248 SysFreeString(header
->value
);
1251 /* response headers */
1252 free_response_headers(This
);
1253 SysFreeString(This
->status_text
);
1255 /* detach callback object */
1256 BindStatusCallback_Detach(This
->bsc
);
1258 if (This
->sink
) IDispatch_Release(This
->sink
);
1261 static HRESULT WINAPI
XMLHTTPRequest_QueryInterface(IXMLHTTPRequest
*iface
, REFIID riid
, void **ppvObject
)
1263 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1264 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
1266 if ( IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1267 IsEqualGUID( riid
, &IID_IDispatch
) ||
1268 IsEqualGUID( riid
, &IID_IUnknown
) )
1272 else if (IsEqualGUID(&IID_IObjectWithSite
, riid
))
1274 *ppvObject
= &This
->IObjectWithSite_iface
;
1276 else if (IsEqualGUID(&IID_IObjectSafety
, riid
))
1278 *ppvObject
= &This
->IObjectSafety_iface
;
1282 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1284 return E_NOINTERFACE
;
1287 IXMLHTTPRequest_AddRef( iface
);
1292 static ULONG WINAPI
XMLHTTPRequest_AddRef(IXMLHTTPRequest
*iface
)
1294 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1295 ULONG ref
= InterlockedIncrement( &This
->ref
);
1296 TRACE("(%p)->(%u)\n", This
, ref
);
1300 static ULONG WINAPI
XMLHTTPRequest_Release(IXMLHTTPRequest
*iface
)
1302 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1303 ULONG ref
= InterlockedDecrement( &This
->ref
);
1305 TRACE("(%p)->(%u)\n", This
, ref
);
1309 httprequest_release( This
);
1316 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1318 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1320 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1327 static HRESULT WINAPI
XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest
*iface
, UINT iTInfo
,
1328 LCID lcid
, ITypeInfo
**ppTInfo
)
1330 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1332 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1334 return get_typeinfo(IXMLHTTPRequest_tid
, ppTInfo
);
1337 static HRESULT WINAPI
XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest
*iface
, REFIID riid
,
1338 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1340 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1341 ITypeInfo
*typeinfo
;
1344 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1347 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1348 return E_INVALIDARG
;
1350 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1353 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1354 ITypeInfo_Release(typeinfo
);
1360 static HRESULT WINAPI
XMLHTTPRequest_Invoke(IXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1361 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1362 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1364 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1365 ITypeInfo
*typeinfo
;
1368 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1369 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1371 hr
= get_typeinfo(IXMLHTTPRequest_tid
, &typeinfo
);
1374 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1375 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1376 ITypeInfo_Release(typeinfo
);
1382 static HRESULT WINAPI
XMLHTTPRequest_open(IXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1383 VARIANT async
, VARIANT user
, VARIANT password
)
1385 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1386 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1387 debugstr_variant(&async
));
1388 return httprequest_open(This
, method
, url
, async
, user
, password
);
1391 static HRESULT WINAPI
XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1393 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1394 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1395 return httprequest_setRequestHeader(This
, header
, value
);
1398 static HRESULT WINAPI
XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1400 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1401 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1402 return httprequest_getResponseHeader(This
, header
, value
);
1405 static HRESULT WINAPI
XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1407 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1408 TRACE("(%p)->(%p)\n", This
, respheaders
);
1409 return httprequest_getAllResponseHeaders(This
, respheaders
);
1412 static HRESULT WINAPI
XMLHTTPRequest_send(IXMLHTTPRequest
*iface
, VARIANT body
)
1414 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1415 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1416 return httprequest_send(This
, body
);
1419 static HRESULT WINAPI
XMLHTTPRequest_abort(IXMLHTTPRequest
*iface
)
1421 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1422 TRACE("(%p)\n", This
);
1423 return httprequest_abort(This
);
1426 static HRESULT WINAPI
XMLHTTPRequest_get_status(IXMLHTTPRequest
*iface
, LONG
*status
)
1428 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1429 TRACE("(%p)->(%p)\n", This
, status
);
1430 return httprequest_get_status(This
, status
);
1433 static HRESULT WINAPI
XMLHTTPRequest_get_statusText(IXMLHTTPRequest
*iface
, BSTR
*status
)
1435 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1436 TRACE("(%p)->(%p)\n", This
, status
);
1437 return httprequest_get_statusText(This
, status
);
1440 static HRESULT WINAPI
XMLHTTPRequest_get_responseXML(IXMLHTTPRequest
*iface
, IDispatch
**body
)
1442 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1443 TRACE("(%p)->(%p)\n", This
, body
);
1444 return httprequest_get_responseXML(This
, body
);
1447 static HRESULT WINAPI
XMLHTTPRequest_get_responseText(IXMLHTTPRequest
*iface
, BSTR
*body
)
1449 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1450 TRACE("(%p)->(%p)\n", This
, body
);
1451 return httprequest_get_responseText(This
, body
);
1454 static HRESULT WINAPI
XMLHTTPRequest_get_responseBody(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1456 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1457 TRACE("(%p)->(%p)\n", This
, body
);
1458 return httprequest_get_responseBody(This
, body
);
1461 static HRESULT WINAPI
XMLHTTPRequest_get_responseStream(IXMLHTTPRequest
*iface
, VARIANT
*body
)
1463 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1464 TRACE("(%p)->(%p)\n", This
, body
);
1465 return httprequest_get_responseStream(This
, body
);
1468 static HRESULT WINAPI
XMLHTTPRequest_get_readyState(IXMLHTTPRequest
*iface
, LONG
*state
)
1470 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1471 TRACE("(%p)->(%p)\n", This
, state
);
1472 return httprequest_get_readyState(This
, state
);
1475 static HRESULT WINAPI
XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest
*iface
, IDispatch
*sink
)
1477 httprequest
*This
= impl_from_IXMLHTTPRequest( iface
);
1478 TRACE("(%p)->(%p)\n", This
, sink
);
1479 return httprequest_put_onreadystatechange(This
, sink
);
1482 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl
=
1484 XMLHTTPRequest_QueryInterface
,
1485 XMLHTTPRequest_AddRef
,
1486 XMLHTTPRequest_Release
,
1487 XMLHTTPRequest_GetTypeInfoCount
,
1488 XMLHTTPRequest_GetTypeInfo
,
1489 XMLHTTPRequest_GetIDsOfNames
,
1490 XMLHTTPRequest_Invoke
,
1491 XMLHTTPRequest_open
,
1492 XMLHTTPRequest_setRequestHeader
,
1493 XMLHTTPRequest_getResponseHeader
,
1494 XMLHTTPRequest_getAllResponseHeaders
,
1495 XMLHTTPRequest_send
,
1496 XMLHTTPRequest_abort
,
1497 XMLHTTPRequest_get_status
,
1498 XMLHTTPRequest_get_statusText
,
1499 XMLHTTPRequest_get_responseXML
,
1500 XMLHTTPRequest_get_responseText
,
1501 XMLHTTPRequest_get_responseBody
,
1502 XMLHTTPRequest_get_responseStream
,
1503 XMLHTTPRequest_get_readyState
,
1504 XMLHTTPRequest_put_onreadystatechange
1507 /* IObjectWithSite */
1508 static HRESULT WINAPI
1509 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite
* iface
, REFIID riid
, void** ppvObject
)
1511 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1512 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest
*)This
, riid
, ppvObject
);
1515 static ULONG WINAPI
httprequest_ObjectWithSite_AddRef( IObjectWithSite
* iface
)
1517 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1518 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest
*)This
);
1521 static ULONG WINAPI
httprequest_ObjectWithSite_Release( IObjectWithSite
* iface
)
1523 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1524 return IXMLHTTPRequest_Release((IXMLHTTPRequest
*)This
);
1527 static HRESULT WINAPI
httprequest_ObjectWithSite_GetSite( IObjectWithSite
*iface
, REFIID iid
, void **ppvSite
)
1529 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1531 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( iid
), ppvSite
);
1536 return IUnknown_QueryInterface( This
->site
, iid
, ppvSite
);
1539 static void get_base_uri(httprequest
*This
)
1541 IServiceProvider
*provider
;
1542 IHTMLDocument2
*doc
;
1547 hr
= IUnknown_QueryInterface(This
->site
, &IID_IServiceProvider
, (void**)&provider
);
1551 hr
= IServiceProvider_QueryService(provider
, &SID_SContainerDispatch
, &IID_IHTMLDocument2
, (void**)&doc
);
1552 IServiceProvider_Release(provider
);
1556 hr
= IHTMLDocument2_get_URL(doc
, &url
);
1557 IHTMLDocument2_Release(doc
);
1558 if(FAILED(hr
) || !url
|| !*url
)
1561 TRACE("host url %s\n", debugstr_w(url
));
1563 hr
= CreateUri(url
, 0, 0, &uri
);
1568 This
->base_uri
= uri
;
1571 static HRESULT WINAPI
httprequest_ObjectWithSite_SetSite( IObjectWithSite
*iface
, IUnknown
*punk
)
1573 httprequest
*This
= impl_from_IObjectWithSite(iface
);
1575 TRACE("(%p)->(%p)\n", This
, punk
);
1578 IUnknown_Release( This
->site
);
1580 IUri_Release(This
->base_uri
);
1586 IUnknown_AddRef( punk
);
1593 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1595 httprequest_ObjectWithSite_QueryInterface
,
1596 httprequest_ObjectWithSite_AddRef
,
1597 httprequest_ObjectWithSite_Release
,
1598 httprequest_ObjectWithSite_SetSite
,
1599 httprequest_ObjectWithSite_GetSite
1603 static HRESULT WINAPI
httprequest_Safety_QueryInterface(IObjectSafety
*iface
, REFIID riid
, void **ppv
)
1605 httprequest
*This
= impl_from_IObjectSafety(iface
);
1606 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest
*)This
, riid
, ppv
);
1609 static ULONG WINAPI
httprequest_Safety_AddRef(IObjectSafety
*iface
)
1611 httprequest
*This
= impl_from_IObjectSafety(iface
);
1612 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest
*)This
);
1615 static ULONG WINAPI
httprequest_Safety_Release(IObjectSafety
*iface
)
1617 httprequest
*This
= impl_from_IObjectSafety(iface
);
1618 return IXMLHTTPRequest_Release((IXMLHTTPRequest
*)This
);
1621 static HRESULT WINAPI
httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1622 DWORD
*supported
, DWORD
*enabled
)
1624 httprequest
*This
= impl_from_IObjectSafety(iface
);
1626 TRACE("(%p)->(%s %p %p)\n", This
, debugstr_guid(riid
), supported
, enabled
);
1628 if(!supported
|| !enabled
) return E_POINTER
;
1630 *supported
= safety_supported_options
;
1631 *enabled
= This
->safeopt
;
1636 static HRESULT WINAPI
httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety
*iface
, REFIID riid
,
1637 DWORD mask
, DWORD enabled
)
1639 httprequest
*This
= impl_from_IObjectSafety(iface
);
1640 TRACE("(%p)->(%s %x %x)\n", This
, debugstr_guid(riid
), mask
, enabled
);
1642 if ((mask
& ~safety_supported_options
))
1645 This
->safeopt
= (This
->safeopt
& ~mask
) | (mask
& enabled
);
1650 static const IObjectSafetyVtbl ObjectSafetyVtbl
= {
1651 httprequest_Safety_QueryInterface
,
1652 httprequest_Safety_AddRef
,
1653 httprequest_Safety_Release
,
1654 httprequest_Safety_GetInterfaceSafetyOptions
,
1655 httprequest_Safety_SetInterfaceSafetyOptions
1658 /* IServerXMLHTTPRequest */
1659 static HRESULT WINAPI
ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest
*iface
, REFIID riid
, void **obj
)
1661 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1663 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
1665 if ( IsEqualGUID( riid
, &IID_IServerXMLHTTPRequest
) ||
1666 IsEqualGUID( riid
, &IID_IXMLHTTPRequest
) ||
1667 IsEqualGUID( riid
, &IID_IDispatch
) ||
1668 IsEqualGUID( riid
, &IID_IUnknown
) )
1674 TRACE("Unsupported interface %s\n", debugstr_guid(riid
));
1676 return E_NOINTERFACE
;
1679 IServerXMLHTTPRequest_AddRef( iface
);
1684 static ULONG WINAPI
ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest
*iface
)
1686 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1687 ULONG ref
= InterlockedIncrement( &This
->ref
);
1688 TRACE("(%p)->(%u)\n", This
, ref
);
1692 static ULONG WINAPI
ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest
*iface
)
1694 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1695 ULONG ref
= InterlockedDecrement( &This
->ref
);
1697 TRACE("(%p)->(%u)\n", This
, ref
);
1701 httprequest_release( &This
->req
);
1708 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest
*iface
, UINT
*pctinfo
)
1710 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1712 TRACE("(%p)->(%p)\n", This
, pctinfo
);
1718 static HRESULT WINAPI
ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest
*iface
, UINT iTInfo
,
1719 LCID lcid
, ITypeInfo
**ppTInfo
)
1721 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1723 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
1725 return get_typeinfo(IServerXMLHTTPRequest_tid
, ppTInfo
);
1728 static HRESULT WINAPI
ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest
*iface
, REFIID riid
,
1729 LPOLESTR
*rgszNames
, UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1731 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1732 ITypeInfo
*typeinfo
;
1735 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
1738 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
1739 return E_INVALIDARG
;
1741 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1744 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
1745 ITypeInfo_Release(typeinfo
);
1751 static HRESULT WINAPI
ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest
*iface
, DISPID dispIdMember
, REFIID riid
,
1752 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
,
1753 EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
1755 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1756 ITypeInfo
*typeinfo
;
1759 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
1760 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1762 hr
= get_typeinfo(IServerXMLHTTPRequest_tid
, &typeinfo
);
1765 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IServerXMLHTTPRequest_iface
, dispIdMember
, wFlags
,
1766 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1767 ITypeInfo_Release(typeinfo
);
1773 static HRESULT WINAPI
ServerXMLHTTPRequest_open(IServerXMLHTTPRequest
*iface
, BSTR method
, BSTR url
,
1774 VARIANT async
, VARIANT user
, VARIANT password
)
1776 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1777 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_w(method
), debugstr_w(url
),
1778 debugstr_variant(&async
));
1779 return httprequest_open(&This
->req
, method
, url
, async
, user
, password
);
1782 static HRESULT WINAPI
ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR value
)
1784 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1785 TRACE("(%p)->(%s %s)\n", This
, debugstr_w(header
), debugstr_w(value
));
1786 return httprequest_setRequestHeader(&This
->req
, header
, value
);
1789 static HRESULT WINAPI
ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest
*iface
, BSTR header
, BSTR
*value
)
1791 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1792 TRACE("(%p)->(%s %p)\n", This
, debugstr_w(header
), value
);
1793 return httprequest_getResponseHeader(&This
->req
, header
, value
);
1796 static HRESULT WINAPI
ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest
*iface
, BSTR
*respheaders
)
1798 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1799 TRACE("(%p)->(%p)\n", This
, respheaders
);
1800 return httprequest_getAllResponseHeaders(&This
->req
, respheaders
);
1803 static HRESULT WINAPI
ServerXMLHTTPRequest_send(IServerXMLHTTPRequest
*iface
, VARIANT body
)
1805 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1806 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&body
));
1807 return httprequest_send(&This
->req
, body
);
1810 static HRESULT WINAPI
ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest
*iface
)
1812 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1813 TRACE("(%p)\n", This
);
1814 return httprequest_abort(&This
->req
);
1817 static HRESULT WINAPI
ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest
*iface
, LONG
*status
)
1819 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1820 TRACE("(%p)->(%p)\n", This
, status
);
1821 return httprequest_get_status(&This
->req
, status
);
1824 static HRESULT WINAPI
ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest
*iface
, BSTR
*status
)
1826 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1827 TRACE("(%p)->(%p)\n", This
, status
);
1828 return httprequest_get_statusText(&This
->req
, status
);
1831 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest
*iface
, IDispatch
**body
)
1833 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1834 TRACE("(%p)->(%p)\n", This
, body
);
1835 return httprequest_get_responseXML(&This
->req
, body
);
1838 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest
*iface
, BSTR
*body
)
1840 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1841 TRACE("(%p)->(%p)\n", This
, body
);
1842 return httprequest_get_responseText(&This
->req
, body
);
1845 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1847 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1848 TRACE("(%p)->(%p)\n", This
, body
);
1849 return httprequest_get_responseBody(&This
->req
, body
);
1852 static HRESULT WINAPI
ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest
*iface
, VARIANT
*body
)
1854 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1855 TRACE("(%p)->(%p)\n", This
, body
);
1856 return httprequest_get_responseStream(&This
->req
, body
);
1859 static HRESULT WINAPI
ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest
*iface
, LONG
*state
)
1861 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1862 TRACE("(%p)->(%p)\n", This
, state
);
1863 return httprequest_get_readyState(&This
->req
, state
);
1866 static HRESULT WINAPI
ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest
*iface
, IDispatch
*sink
)
1868 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1869 TRACE("(%p)->(%p)\n", This
, sink
);
1870 return httprequest_put_onreadystatechange(&This
->req
, sink
);
1873 static HRESULT WINAPI
ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest
*iface
, LONG resolveTimeout
, LONG connectTimeout
,
1874 LONG sendTimeout
, LONG receiveTimeout
)
1876 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1877 FIXME("(%p)->(%d %d %d %d): stub\n", This
, resolveTimeout
, connectTimeout
, sendTimeout
, receiveTimeout
);
1881 static HRESULT WINAPI
ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest
*iface
, VARIANT timeout
, VARIANT_BOOL
*isSuccessful
)
1883 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1884 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_variant(&timeout
), isSuccessful
);
1888 static HRESULT WINAPI
ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT
*value
)
1890 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1891 FIXME("(%p)->(%d %p): stub\n", This
, option
, value
);
1895 static HRESULT WINAPI
ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest
*iface
, SERVERXMLHTTP_OPTION option
, VARIANT value
)
1897 serverhttp
*This
= impl_from_IServerXMLHTTPRequest( iface
);
1898 FIXME("(%p)->(%d %s): stub\n", This
, option
, debugstr_variant(&value
));
1902 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl
=
1904 ServerXMLHTTPRequest_QueryInterface
,
1905 ServerXMLHTTPRequest_AddRef
,
1906 ServerXMLHTTPRequest_Release
,
1907 ServerXMLHTTPRequest_GetTypeInfoCount
,
1908 ServerXMLHTTPRequest_GetTypeInfo
,
1909 ServerXMLHTTPRequest_GetIDsOfNames
,
1910 ServerXMLHTTPRequest_Invoke
,
1911 ServerXMLHTTPRequest_open
,
1912 ServerXMLHTTPRequest_setRequestHeader
,
1913 ServerXMLHTTPRequest_getResponseHeader
,
1914 ServerXMLHTTPRequest_getAllResponseHeaders
,
1915 ServerXMLHTTPRequest_send
,
1916 ServerXMLHTTPRequest_abort
,
1917 ServerXMLHTTPRequest_get_status
,
1918 ServerXMLHTTPRequest_get_statusText
,
1919 ServerXMLHTTPRequest_get_responseXML
,
1920 ServerXMLHTTPRequest_get_responseText
,
1921 ServerXMLHTTPRequest_get_responseBody
,
1922 ServerXMLHTTPRequest_get_responseStream
,
1923 ServerXMLHTTPRequest_get_readyState
,
1924 ServerXMLHTTPRequest_put_onreadystatechange
,
1925 ServerXMLHTTPRequest_setTimeouts
,
1926 ServerXMLHTTPRequest_waitForResponse
,
1927 ServerXMLHTTPRequest_getOption
,
1928 ServerXMLHTTPRequest_setOption
1931 static void init_httprequest(httprequest
*req
)
1933 req
->IXMLHTTPRequest_iface
.lpVtbl
= &XMLHTTPRequestVtbl
;
1934 req
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
1935 req
->IObjectSafety_iface
.lpVtbl
= &ObjectSafetyVtbl
;
1941 req
->uri
= req
->base_uri
= NULL
;
1942 req
->user
= req
->password
= NULL
;
1944 req
->state
= READYSTATE_UNINITIALIZED
;
1949 req
->status_text
= NULL
;
1950 req
->reqheader_size
= 0;
1951 req
->raw_respheaders
= NULL
;
1952 req
->use_utf8_content
= FALSE
;
1954 list_init(&req
->reqheaders
);
1955 list_init(&req
->respheaders
);
1961 HRESULT
XMLHTTPRequest_create(IUnknown
*outer
, void **obj
)
1965 TRACE("(%p, %p)\n", outer
, obj
);
1967 req
= heap_alloc( sizeof (*req
) );
1969 return E_OUTOFMEMORY
;
1971 init_httprequest(req
);
1972 *obj
= &req
->IXMLHTTPRequest_iface
;
1974 TRACE("returning iface %p\n", *obj
);
1979 HRESULT
ServerXMLHTTP_create(IUnknown
*outer
, void **obj
)
1983 TRACE("(%p, %p)\n", outer
, obj
);
1985 req
= heap_alloc( sizeof (*req
) );
1987 return E_OUTOFMEMORY
;
1989 init_httprequest(&req
->req
);
1990 req
->IServerXMLHTTPRequest_iface
.lpVtbl
= &ServerXMLHTTPRequestVtbl
;
1993 *obj
= &req
->IServerXMLHTTPRequest_iface
;
1995 TRACE("returning iface %p\n", *obj
);
2002 HRESULT
XMLHTTPRequest_create(IUnknown
*pUnkOuter
, void **ppObj
)
2004 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
2005 "libxml2 support was not present at compile time.\n");
2009 HRESULT
ServerXMLHTTP_create(IUnknown
*outer
, void **obj
)
2011 MESSAGE("This program tried to use a ServerXMLHTTP object, but\n"
2012 "libxml2 support was not present at compile time.\n");