wined3d: Use context->ops->prepare_upload_bo() in wined3d_device_context_map() if...
[wine.git] / dlls / mshtml / xmlhttprequest.c
blob814162acbbc89e471025d583b511bc72e5485ee3
1 /*
2 * Copyright 2015 Zhenbo Li
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <assert.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
29 #include "wine/debug.h"
31 #include "mshtml_private.h"
32 #include "htmlevent.h"
33 #include "mshtmdid.h"
34 #include "initguid.h"
35 #include "msxml6.h"
36 #include "objsafe.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40 #define MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD MSHTML_DISPID_CUSTOM_MIN
42 static HRESULT bstr_to_nsacstr(BSTR bstr, nsACString *str)
44 char *cstr = heap_strdupWtoU(bstr);
45 if(!cstr)
46 return E_OUTOFMEMORY;
47 nsACString_Init(str, cstr);
48 heap_free(cstr);
49 return S_OK;
52 static HRESULT variant_to_nsastr(VARIANT var, nsAString *ret)
54 switch(V_VT(&var)) {
55 case VT_NULL:
56 case VT_ERROR:
57 case VT_EMPTY:
58 nsAString_Init(ret, NULL);
59 return S_OK;
60 case VT_BSTR:
61 nsAString_InitDepend(ret, V_BSTR(&var));
62 return S_OK;
63 default:
64 FIXME("Unsupported VARIANT: %s\n", debugstr_variant(&var));
65 return E_INVALIDARG;
69 static HRESULT return_nscstr(nsresult nsres, nsACString *nscstr, BSTR *p)
71 const char *str;
72 int len;
74 if(NS_FAILED(nsres)) {
75 ERR("failed: %08x\n", nsres);
76 nsACString_Finish(nscstr);
77 return E_FAIL;
80 nsACString_GetData(nscstr, &str);
82 if(*str) {
83 len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
84 *p = SysAllocStringLen(NULL, len - 1);
85 if(!*p) {
86 nsACString_Finish(nscstr);
87 return E_OUTOFMEMORY;
89 MultiByteToWideChar(CP_UTF8, 0, str, -1, *p, len);
90 }else {
91 *p = NULL;
94 nsACString_Finish(nscstr);
95 return S_OK;
98 typedef struct {
99 nsIDOMEventListener nsIDOMEventListener_iface;
100 LONG ref;
101 HTMLXMLHttpRequest *xhr;
102 BOOL readystatechange_event;
103 BOOL load_event;
104 } XMLHttpReqEventListener;
106 struct HTMLXMLHttpRequest {
107 EventTarget event_target;
108 IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
109 IProvideClassInfo2 IProvideClassInfo2_iface;
110 LONG ref;
111 nsIXMLHttpRequest *nsxhr;
112 XMLHttpReqEventListener *event_listener;
115 static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener)
117 nsIDOMEventTarget *event_target;
118 nsAString str;
119 nsresult nsres;
121 nsres = nsIXMLHttpRequest_QueryInterface(event_listener->xhr->nsxhr, &IID_nsIDOMEventTarget, (void**)&event_target);
122 assert(nsres == NS_OK);
124 if(event_listener->readystatechange_event) {
125 nsAString_InitDepend(&str, L"onreadystatechange");
126 nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE);
127 nsAString_Finish(&str);
128 assert(nsres == NS_OK);
131 if(event_listener->load_event) {
132 nsAString_InitDepend(&str, L"load");
133 nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE);
134 nsAString_Finish(&str);
135 assert(nsres == NS_OK);
138 nsIDOMEventTarget_Release(event_target);
140 event_listener->xhr->event_listener = NULL;
141 event_listener->xhr = NULL;
142 nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface);
146 static inline XMLHttpReqEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface)
148 return CONTAINING_RECORD(iface, XMLHttpReqEventListener, nsIDOMEventListener_iface);
151 static nsresult NSAPI XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener *iface,
152 nsIIDRef riid, void **result)
154 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
156 if(IsEqualGUID(&IID_nsISupports, riid)) {
157 TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
158 *result = &This->nsIDOMEventListener_iface;
159 }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
160 TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
161 *result = &This->nsIDOMEventListener_iface;
162 }else {
163 *result = NULL;
164 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
165 return NS_NOINTERFACE;
168 nsIDOMEventListener_AddRef(&This->nsIDOMEventListener_iface);
169 return NS_OK;
172 static nsrefcnt NSAPI XMLHttpReqEventListener_AddRef(nsIDOMEventListener *iface)
174 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
175 LONG ref = InterlockedIncrement(&This->ref);
177 TRACE("(%p) ref=%d\n", This, ref);
179 return ref;
182 static nsrefcnt NSAPI XMLHttpReqEventListener_Release(nsIDOMEventListener *iface)
184 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
185 LONG ref = InterlockedDecrement(&This->ref);
187 TRACE("(%p) ref=%d\n", This, ref);
189 if(!ref) {
190 assert(!This->xhr);
191 heap_free(This);
194 return ref;
197 static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *nsevent)
199 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
200 DOMEvent *event;
201 HRESULT hres;
203 TRACE("(%p)\n", This);
205 if(!This->xhr)
206 return NS_OK;
208 hres = create_event_from_nsevent(nsevent, dispex_compat_mode(&This->xhr->event_target.dispex), &event);
209 if(SUCCEEDED(hres) ){
210 dispatch_event(&This->xhr->event_target, event);
211 IDOMEvent_Release(&event->IDOMEvent_iface);
213 return NS_OK;
216 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
217 XMLHttpReqEventListener_QueryInterface,
218 XMLHttpReqEventListener_AddRef,
219 XMLHttpReqEventListener_Release,
220 XMLHttpReqEventListener_HandleEvent
223 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
225 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
228 static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *iface, REFIID riid, void **ppv)
230 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
232 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
234 if(IsEqualGUID(&IID_IUnknown, riid)) {
235 *ppv = &This->IHTMLXMLHttpRequest_iface;
236 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
237 *ppv = &This->IHTMLXMLHttpRequest_iface;
238 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest, riid)) {
239 *ppv = &This->IHTMLXMLHttpRequest_iface;
240 }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
241 *ppv = &This->IProvideClassInfo2_iface;
242 }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
243 *ppv = &This->IProvideClassInfo2_iface;
244 }else {
245 return EventTarget_QI(&This->event_target, riid, ppv);
248 IUnknown_AddRef((IUnknown*)*ppv);
249 return S_OK;
252 static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface)
254 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
255 LONG ref = InterlockedIncrement(&This->ref);
257 TRACE("(%p) ref=%d\n", This, ref);
259 return ref;
262 static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
264 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
265 LONG ref = InterlockedDecrement(&This->ref);
267 TRACE("(%p) ref=%d\n", This, ref);
269 if(!ref) {
270 if(This->event_listener)
271 detach_xhr_event_listener(This->event_listener);
272 release_event_target(&This->event_target);
273 release_dispex(&This->event_target.dispex);
274 nsIXMLHttpRequest_Release(This->nsxhr);
275 heap_free(This);
278 return ref;
281 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest *iface, UINT *pctinfo)
283 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
284 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
287 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest *iface, UINT iTInfo,
288 LCID lcid, ITypeInfo **ppTInfo)
290 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
292 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
295 static HRESULT WINAPI HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
296 LCID lcid, DISPID *rgDispId)
298 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
300 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
301 lcid, rgDispId);
304 static HRESULT WINAPI HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
305 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
307 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
309 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
310 pDispParams, pVarResult, pExcepInfo, puArgErr);
313 static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p)
315 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
316 UINT16 val;
317 nsresult nsres;
319 TRACE("(%p)->(%p)\n", This, p);
321 if(!p)
322 return E_POINTER;
323 nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &val);
324 if(NS_FAILED(nsres)) {
325 ERR("nsIXMLHttpRequest_GetReadyState failed: %08x\n", nsres);
326 return E_FAIL;
328 *p = val;
329 return S_OK;
332 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *iface, VARIANT *p)
334 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
335 FIXME("(%p)->(%p)\n", This, p);
336 return E_NOTIMPL;
339 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p)
341 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
342 nsAString nsstr;
343 nsresult nsres;
345 TRACE("(%p)->(%p)\n", This, p);
347 if(!p)
348 return E_POINTER;
350 nsAString_Init(&nsstr, NULL);
351 nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr);
352 return return_nsstr(nsres, &nsstr, p);
355 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p)
357 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
358 IXMLDOMDocument *xmldoc = NULL;
359 BSTR str;
360 HRESULT hres;
361 VARIANT_BOOL vbool;
362 IObjectSafety *safety;
364 TRACE("(%p)->(%p)\n", This, p);
366 hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc);
367 if(FAILED(hres)) {
368 ERR("CoCreateInstance failed: %08x\n", hres);
369 return hres;
372 hres = IHTMLXMLHttpRequest_get_responseText(iface, &str);
373 if(FAILED(hres)) {
374 IXMLDOMDocument_Release(xmldoc);
375 ERR("get_responseText failed: %08x\n", hres);
376 return hres;
379 hres = IXMLDOMDocument_loadXML(xmldoc, str, &vbool);
380 SysFreeString(str);
381 if(hres != S_OK || vbool != VARIANT_TRUE)
382 WARN("loadXML failed: %08x, returning an empty xmldoc\n", hres);
384 hres = IXMLDOMDocument_QueryInterface(xmldoc, &IID_IObjectSafety, (void**)&safety);
385 assert(SUCCEEDED(hres));
386 hres = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
387 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER,
388 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER);
389 assert(SUCCEEDED(hres));
390 IObjectSafety_Release(safety);
392 *p = (IDispatch*)xmldoc;
393 return S_OK;
396 static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, LONG *p)
398 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
399 DWORD val;
400 nsresult nsres;
401 TRACE("(%p)->(%p)\n", This, p);
403 if(!p)
404 return E_POINTER;
406 nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val);
407 if(NS_FAILED(nsres)) {
408 ERR("nsIXMLHttpRequest_GetStatus failed: %08x\n", nsres);
409 return E_FAIL;
411 *p = val;
412 if(val == 0)
413 return E_FAIL; /* WinAPI thinks this is an error */
415 return S_OK;
418 static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *iface, BSTR *p)
420 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
421 nsACString nscstr;
422 nsresult nsres;
423 HRESULT hres;
424 LONG state;
426 TRACE("(%p)->(%p)\n", This, p);
428 if(!p)
429 return E_POINTER;
431 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
432 if(FAILED(hres))
433 return hres;
435 if(state < 2) {
436 *p = NULL;
437 return E_FAIL;
440 nsACString_Init(&nscstr, NULL);
441 nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr);
442 return return_nscstr(nsres, &nscstr, p);
445 static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT v)
447 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
449 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
451 return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v);
454 static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p)
456 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
458 TRACE("(%p)->(%p)\n", This, p);
460 return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p);
463 static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface)
465 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
466 nsresult nsres;
468 TRACE("(%p)->()\n", This);
470 nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr);
471 if(NS_FAILED(nsres)) {
472 ERR("nsIXMLHttpRequest_SlowAbort failed: %08x\n", nsres);
473 return E_FAIL;
476 return S_OK;
479 static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, LCID lcid, WORD flags,
480 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
482 /* If only two arguments were given, implicitly set async to false */
483 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
484 VARIANT args[5];
485 DISPPARAMS new_dp = {args, NULL, ARRAY_SIZE(args), 0};
486 V_VT(args) = VT_EMPTY;
487 V_VT(args+1) = VT_EMPTY;
488 V_VT(args+2) = VT_BOOL;
489 V_BOOL(args+2) = VARIANT_TRUE;
490 args[3] = dp->rgvarg[0];
491 args[4] = dp->rgvarg[1];
493 TRACE("implicit async\n");
495 return IDispatchEx_InvokeEx(&dispex->IDispatchEx_iface, DISPID_IHTMLXMLHTTPREQUEST_OPEN,
496 lcid, flags, &new_dp, res, ei, caller);
499 return S_FALSE; /* fallback to default */
502 static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
504 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
505 nsACString method, url;
506 nsAString user, password;
507 nsresult nsres;
508 HRESULT hres;
510 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword));
512 if(V_VT(&varAsync) != VT_BOOL) {
513 FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync));
514 return E_FAIL;
517 /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
518 * synchronous requests on the main thread have been deprecated due to the negative
519 * effects to the user experience.
521 if(!V_BOOL(&varAsync)) {
522 FIXME("Synchronous request is not supported yet\n");
523 return E_FAIL;
526 hres = variant_to_nsastr(varUser, &user);
527 if(FAILED(hres))
528 return hres;
529 hres = variant_to_nsastr(varPassword, &password);
530 if(FAILED(hres)) {
531 nsAString_Finish(&user);
532 return hres;
535 hres = bstr_to_nsacstr(bstrMethod, &method);
536 if(FAILED(hres)) {
537 nsAString_Finish(&user);
538 nsAString_Finish(&password);
539 return hres;
541 hres = bstr_to_nsacstr(bstrUrl, &url);
542 if(FAILED(hres)) {
543 nsAString_Finish(&user);
544 nsAString_Finish(&password);
545 nsACString_Finish(&method);
546 return hres;
549 nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, TRUE,
550 &user, &password, 0);
552 nsACString_Finish(&method);
553 nsACString_Finish(&url);
554 nsAString_Finish(&user);
555 nsAString_Finish(&password);
557 if(NS_FAILED(nsres)) {
558 ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres);
559 return E_FAIL;
562 return S_OK;
565 static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
567 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
568 nsIWritableVariant *nsbody = NULL;
569 nsresult nsres = NS_OK;
571 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody));
573 switch(V_VT(&varBody)) {
574 case VT_NULL:
575 case VT_EMPTY:
576 case VT_ERROR:
577 break;
578 case VT_BSTR: {
579 nsAString nsstr;
581 nsbody = create_nsvariant();
582 if(!nsbody)
583 return E_OUTOFMEMORY;
585 nsAString_InitDepend(&nsstr, V_BSTR(&varBody));
586 nsres = nsIWritableVariant_SetAsAString(nsbody, &nsstr);
587 nsAString_Finish(&nsstr);
588 break;
590 default:
591 FIXME("unsupported body type %s\n", debugstr_variant(&varBody));
592 return E_NOTIMPL;
595 if(NS_SUCCEEDED(nsres))
596 nsres = nsIXMLHttpRequest_Send(This->nsxhr, (nsIVariant*)nsbody);
597 if(nsbody)
598 nsIWritableVariant_Release(nsbody);
599 if(NS_FAILED(nsres)) {
600 ERR("nsIXMLHttpRequest_Send failed: %08x\n", nsres);
601 return E_FAIL;
604 return S_OK;
607 static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p)
609 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
610 nsACString nscstr;
611 nsresult nsres;
612 HRESULT hres;
613 LONG state;
615 TRACE("(%p)->(%p)\n", This, p);
617 if(!p)
618 return E_POINTER;
620 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
621 if(FAILED(hres))
622 return hres;
624 if(state < 2) {
625 *p = NULL;
626 return E_FAIL;
629 nsACString_Init(&nscstr, NULL);
630 nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr);
631 return return_nscstr(nsres, &nscstr, p);
634 static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR *p)
636 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
637 nsACString header, ret;
638 char *cstr;
639 nsresult nsres;
640 HRESULT hres;
641 LONG state;
642 TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrHeader), p);
644 if(!p)
645 return E_POINTER;
646 if(!bstrHeader)
647 return E_INVALIDARG;
649 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
650 if(FAILED(hres))
651 return hres;
653 if(state < 2) {
654 *p = NULL;
655 return E_FAIL;
658 cstr = heap_strdupWtoU(bstrHeader);
659 nsACString_InitDepend(&header, cstr);
660 nsACString_Init(&ret, NULL);
662 nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret);
664 nsACString_Finish(&header);
665 heap_free(cstr);
666 return return_nscstr(nsres, &ret, p);
669 static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR bstrValue)
671 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
672 char *header_u, *value_u;
673 nsACString header, value;
674 nsresult nsres;
676 TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
678 header_u = heap_strdupWtoU(bstrHeader);
679 if(bstrHeader && !header_u)
680 return E_OUTOFMEMORY;
682 value_u = heap_strdupWtoU(bstrValue);
683 if(bstrValue && !value_u) {
684 heap_free(header_u);
685 return E_OUTOFMEMORY;
688 nsACString_InitDepend(&header, header_u);
689 nsACString_InitDepend(&value, value_u);
690 nsres = nsIXMLHttpRequest_SetRequestHeader(This->nsxhr, &header, &value);
691 nsACString_Finish(&header);
692 nsACString_Finish(&value);
693 heap_free(header_u);
694 heap_free(value_u);
695 if(NS_FAILED(nsres)) {
696 ERR("SetRequestHeader failed: %08x\n", nsres);
697 return E_FAIL;
700 return S_OK;
703 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl = {
704 HTMLXMLHttpRequest_QueryInterface,
705 HTMLXMLHttpRequest_AddRef,
706 HTMLXMLHttpRequest_Release,
707 HTMLXMLHttpRequest_GetTypeInfoCount,
708 HTMLXMLHttpRequest_GetTypeInfo,
709 HTMLXMLHttpRequest_GetIDsOfNames,
710 HTMLXMLHttpRequest_Invoke,
711 HTMLXMLHttpRequest_get_readyState,
712 HTMLXMLHttpRequest_get_responseBody,
713 HTMLXMLHttpRequest_get_responseText,
714 HTMLXMLHttpRequest_get_responseXML,
715 HTMLXMLHttpRequest_get_status,
716 HTMLXMLHttpRequest_get_statusText,
717 HTMLXMLHttpRequest_put_onreadystatechange,
718 HTMLXMLHttpRequest_get_onreadystatechange,
719 HTMLXMLHttpRequest_abort,
720 HTMLXMLHttpRequest_open,
721 HTMLXMLHttpRequest_send,
722 HTMLXMLHttpRequest_getAllResponseHeaders,
723 HTMLXMLHttpRequest_getResponseHeader,
724 HTMLXMLHttpRequest_setRequestHeader
727 static inline HTMLXMLHttpRequest *impl_from_IProvideClassInfo2(IProvideClassInfo2 *iface)
729 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IProvideClassInfo2_iface);
732 static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, void **ppv)
734 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
735 return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
738 static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo2 *iface)
740 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
741 return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
744 static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo2 *iface)
746 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
747 return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
750 static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI)
752 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
753 TRACE("(%p)->(%p)\n", This, ppTI);
754 return get_class_typeinfo(&CLSID_HTMLXMLHttpRequest, ppTI);
757 static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID)
759 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
760 FIXME("(%p)->(%u %p)\n", This, dwGuidKind, pGUID);
761 return E_NOTIMPL;
764 static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
765 ProvideClassInfo_QueryInterface,
766 ProvideClassInfo_AddRef,
767 ProvideClassInfo_Release,
768 ProvideClassInfo_GetClassInfo,
769 ProvideClassInfo2_GetGUID,
772 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
774 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex);
777 static HRESULT HTMLXMLHttpRequest_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
779 /* onload event handler property is supported, but not exposed by any interface. We implement as a custom property. */
780 if(!wcscmp(L"onload", name)) {
781 *dispid = MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD;
782 return S_OK;
785 return DISP_E_UNKNOWNNAME;
788 static HRESULT HTMLXMLHttpRequest_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
789 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
791 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
793 if(id == MSHTML_DISPID_HTMLXMLHTTPREQUEST_ONLOAD) {
794 switch(flags) {
795 case DISPATCH_PROPERTYGET:
796 TRACE("(%p) get onload\n", This);
797 return get_event_handler(&This->event_target, EVENTID_LOAD, res);
799 case DISPATCH_PROPERTYPUT:
800 if(params->cArgs != 1 || (params->cNamedArgs == 1 && *params->rgdispidNamedArgs != DISPID_PROPERTYPUT)
801 || params->cNamedArgs > 1) {
802 FIXME("invalid args\n");
803 return E_INVALIDARG;
806 TRACE("(%p)->(%p) set onload\n", This, params->rgvarg);
807 return set_event_handler(&This->event_target, EVENTID_LOAD, params->rgvarg);
809 default:
810 FIXME("Unimplemented flags %x\n", flags);
811 return E_NOTIMPL;
815 return DISP_E_UNKNOWNNAME;
818 static nsISupports *HTMLXMLHttpRequest_get_gecko_target(DispatchEx *dispex)
820 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
821 return (nsISupports*)This->nsxhr;
824 static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, eventid_t eid)
826 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
827 nsIDOMEventTarget *nstarget;
828 const WCHAR *type_name;
829 nsAString type_str;
830 nsresult nsres;
832 TRACE("(%p)\n", This);
834 switch(eid) {
835 case EVENTID_READYSTATECHANGE:
836 type_name = L"readystatechange";
837 break;
838 case EVENTID_LOAD:
839 type_name = L"load";
840 break;
841 default:
842 return;
845 if(!This->event_listener) {
846 This->event_listener = heap_alloc(sizeof(*This->event_listener));
847 if(!This->event_listener)
848 return;
850 This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
851 This->event_listener->ref = 1;
852 This->event_listener->xhr = This;
853 This->event_listener->readystatechange_event = FALSE;
854 This->event_listener->load_event = FALSE;
857 nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
858 assert(nsres == NS_OK);
860 nsAString_InitDepend(&type_str, type_name);
861 nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
862 nsAString_Finish(&type_str);
863 if(NS_FAILED(nsres))
864 ERR("AddEventListener(%s) failed: %08x\n", debugstr_w(type_name), nsres);
866 nsIDOMEventTarget_Release(nstarget);
868 if(eid == EVENTID_READYSTATECHANGE)
869 This->event_listener->readystatechange_event = TRUE;
870 else
871 This->event_listener->load_event = TRUE;
874 static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode)
876 static const dispex_hook_t xhr_hooks[] = {
877 {DISPID_IHTMLXMLHTTPREQUEST_OPEN, HTMLXMLHttpRequest_open_hook},
878 {DISPID_UNKNOWN}
881 EventTarget_init_dispex_info(info, compat_mode);
882 dispex_info_add_interface(info, IHTMLXMLHttpRequest_tid, compat_mode >= COMPAT_MODE_IE10 ? xhr_hooks : NULL);
885 static event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = {
887 NULL,
888 HTMLXMLHttpRequest_get_dispid,
889 HTMLXMLHttpRequest_invoke
891 HTMLXMLHttpRequest_get_gecko_target,
892 HTMLXMLHttpRequest_bind_event
895 static const tid_t HTMLXMLHttpRequest_iface_tids[] = {
898 static dispex_static_data_t HTMLXMLHttpRequest_dispex = {
899 &HTMLXMLHttpRequest_event_target_vtbl.dispex_vtbl,
900 DispHTMLXMLHttpRequest_tid,
901 HTMLXMLHttpRequest_iface_tids,
902 HTMLXMLHttpRequest_init_dispex_info
906 /* IHTMLXMLHttpRequestFactory */
907 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface)
909 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface);
912 static HRESULT WINAPI HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory *iface, REFIID riid, void **ppv)
914 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
916 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
918 if(IsEqualGUID(&IID_IUnknown, riid)) {
919 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
920 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
921 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
922 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) {
923 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
924 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
925 return *ppv ? S_OK : E_NOINTERFACE;
926 }else {
927 *ppv = NULL;
928 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
929 return E_NOINTERFACE;
932 IUnknown_AddRef((IUnknown*)*ppv);
933 return S_OK;
936 static ULONG WINAPI HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory *iface)
938 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
939 LONG ref = InterlockedIncrement(&This->ref);
941 TRACE("(%p) ref=%d\n", This, ref);
943 return ref;
946 static ULONG WINAPI HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory *iface)
948 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
949 LONG ref = InterlockedDecrement(&This->ref);
951 TRACE("(%p) ref=%d\n", This, ref);
953 if(!ref) {
954 release_dispex(&This->dispex);
955 heap_free(This);
958 return ref;
961 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory *iface, UINT *pctinfo)
963 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
964 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
967 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory *iface, UINT iTInfo,
968 LCID lcid, ITypeInfo **ppTInfo)
970 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
972 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
975 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
976 LCID lcid, DISPID *rgDispId)
978 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
980 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
981 lcid, rgDispId);
984 static HRESULT WINAPI HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
985 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
987 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
989 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
990 pDispParams, pVarResult, pExcepInfo, puArgErr);
993 static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p)
995 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
996 HTMLXMLHttpRequest *ret;
997 nsIXMLHttpRequest *nsxhr;
999 TRACE("(%p)->(%p)\n", This, p);
1001 nsxhr = create_nsxhr(This->window->base.outer_window->nswindow);
1002 if(!nsxhr)
1003 return E_FAIL;
1005 ret = heap_alloc_zero(sizeof(*ret));
1006 if(!ret) {
1007 nsIXMLHttpRequest_Release(nsxhr);
1008 return E_OUTOFMEMORY;
1010 ret->nsxhr = nsxhr;
1012 ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
1013 ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl;
1014 EventTarget_Init(&ret->event_target, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
1015 &HTMLXMLHttpRequest_dispex, This->window->doc->document_mode);
1016 ret->ref = 1;
1018 *p = &ret->IHTMLXMLHttpRequest_iface;
1019 return S_OK;
1022 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = {
1023 HTMLXMLHttpRequestFactory_QueryInterface,
1024 HTMLXMLHttpRequestFactory_AddRef,
1025 HTMLXMLHttpRequestFactory_Release,
1026 HTMLXMLHttpRequestFactory_GetTypeInfoCount,
1027 HTMLXMLHttpRequestFactory_GetTypeInfo,
1028 HTMLXMLHttpRequestFactory_GetIDsOfNames,
1029 HTMLXMLHttpRequestFactory_Invoke,
1030 HTMLXMLHttpRequestFactory_create
1033 static inline HTMLXMLHttpRequestFactory *factory_from_DispatchEx(DispatchEx *iface)
1035 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, dispex);
1038 static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WORD flags, DISPPARAMS *params,
1039 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1041 HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(iface);
1042 IHTMLXMLHttpRequest *xhr;
1043 HRESULT hres;
1045 TRACE("\n");
1047 if(flags != DISPATCH_CONSTRUCT) {
1048 FIXME("flags %x not supported\n", flags);
1049 return E_NOTIMPL;
1052 hres = IHTMLXMLHttpRequestFactory_create(&This->IHTMLXMLHttpRequestFactory_iface, &xhr);
1053 if(FAILED(hres))
1054 return hres;
1056 V_VT(res) = VT_DISPATCH;
1057 V_DISPATCH(res) = (IDispatch*)xhr;
1058 return S_OK;
1061 static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl = {
1062 HTMLXMLHttpRequestFactory_value
1065 static const tid_t HTMLXMLHttpRequestFactory_iface_tids[] = {
1066 IHTMLXMLHttpRequestFactory_tid,
1069 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = {
1070 &HTMLXMLHttpRequestFactory_dispex_vtbl,
1071 IHTMLXMLHttpRequestFactory_tid,
1072 HTMLXMLHttpRequestFactory_iface_tids
1075 HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpRequestFactory **ret_ptr)
1077 HTMLXMLHttpRequestFactory *ret;
1079 ret = heap_alloc(sizeof(*ret));
1080 if(!ret)
1081 return E_OUTOFMEMORY;
1083 ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl;
1084 ret->ref = 1;
1085 ret->window = window;
1087 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLXMLHttpRequestFactory_iface,
1088 &HTMLXMLHttpRequestFactory_dispex, dispex_compat_mode(&window->event_target.dispex));
1090 *ret_ptr = ret;
1091 return S_OK;