msvcp140: Add _ContextCallback implementation.
[wine.git] / dlls / mshtml / xmlhttprequest.c
blobab14c54d5e1a40279e80bc8c9a98df263b78d381
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 "initguid.h"
34 #include "msxml6.h"
35 #include "objsafe.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
39 static HRESULT bstr_to_nsacstr(BSTR bstr, nsACString *str)
41 char *cstr = heap_strdupWtoU(bstr);
42 if(!cstr)
43 return E_OUTOFMEMORY;
44 nsACString_Init(str, cstr);
45 heap_free(cstr);
46 return S_OK;
49 static HRESULT variant_to_nsastr(VARIANT var, nsAString *ret)
51 switch(V_VT(&var)) {
52 case VT_NULL:
53 case VT_ERROR:
54 case VT_EMPTY:
55 nsAString_Init(ret, NULL);
56 return S_OK;
57 case VT_BSTR:
58 nsAString_InitDepend(ret, V_BSTR(&var));
59 return S_OK;
60 default:
61 FIXME("Unsupported VARIANT: %s\n", debugstr_variant(&var));
62 return E_INVALIDARG;
66 static HRESULT return_nscstr(nsresult nsres, nsACString *nscstr, BSTR *p)
68 const char *str;
69 int len;
71 if(NS_FAILED(nsres)) {
72 ERR("failed: %08x\n", nsres);
73 nsACString_Finish(nscstr);
74 return E_FAIL;
77 nsACString_GetData(nscstr, &str);
79 if(*str) {
80 len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
81 *p = SysAllocStringLen(NULL, len);
82 if(!*p) {
83 nsACString_Finish(nscstr);
84 return E_OUTOFMEMORY;
86 MultiByteToWideChar(CP_UTF8, 0, str, -1, *p, len);
87 }else {
88 *p = NULL;
91 nsACString_Finish(nscstr);
92 return S_OK;
95 typedef struct XMLHttpReqEventListener XMLHttpReqEventListener;
97 typedef struct {
98 EventTarget event_target;
99 IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
100 LONG ref;
101 nsIXMLHttpRequest *nsxhr;
102 XMLHttpReqEventListener *event_listener;
103 } HTMLXMLHttpRequest;
105 struct XMLHttpReqEventListener {
106 nsIDOMEventListener nsIDOMEventListener_iface;
107 LONG ref;
108 HTMLXMLHttpRequest *xhr;
111 static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener)
113 nsIDOMEventTarget *event_target;
114 nsAString str;
115 nsresult nsres;
117 static const WCHAR readystatechangeW[] =
118 {'o','n','r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
120 nsres = nsIXMLHttpRequest_QueryInterface(event_listener->xhr->nsxhr, &IID_nsIDOMEventTarget, (void**)&event_target);
121 assert(nsres == NS_OK);
123 nsAString_InitDepend(&str, readystatechangeW);
124 nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE);
125 nsAString_Finish(&str);
126 nsIDOMEventTarget_Release(event_target);
128 event_listener->xhr->event_listener = NULL;
129 event_listener->xhr = NULL;
130 nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface);
134 static inline XMLHttpReqEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface)
136 return CONTAINING_RECORD(iface, XMLHttpReqEventListener, nsIDOMEventListener_iface);
139 static nsresult NSAPI XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener *iface,
140 nsIIDRef riid, void **result)
142 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
144 if(IsEqualGUID(&IID_nsISupports, riid)) {
145 TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
146 *result = &This->nsIDOMEventListener_iface;
147 }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
148 TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
149 *result = &This->nsIDOMEventListener_iface;
150 }else {
151 *result = NULL;
152 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
153 return NS_NOINTERFACE;
156 nsIDOMEventListener_AddRef(&This->nsIDOMEventListener_iface);
157 return NS_OK;
160 static nsrefcnt NSAPI XMLHttpReqEventListener_AddRef(nsIDOMEventListener *iface)
162 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
163 LONG ref = InterlockedIncrement(&This->ref);
165 TRACE("(%p) ref=%d\n", This, ref);
167 return ref;
170 static nsrefcnt NSAPI XMLHttpReqEventListener_Release(nsIDOMEventListener *iface)
172 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
173 LONG ref = InterlockedDecrement(&This->ref);
175 TRACE("(%p) ref=%d\n", This, ref);
177 if(!ref) {
178 assert(!This->xhr);
179 heap_free(This);
182 return ref;
185 static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *event)
187 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
189 TRACE("(%p)\n", This);
191 if(!This->xhr)
192 return NS_OK;
194 call_event_handlers(NULL, NULL, &This->xhr->event_target, NULL, EVENTID_READYSTATECHANGE,
195 (IDispatch*)&This->xhr->IHTMLXMLHttpRequest_iface);
196 return NS_OK;
199 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
200 XMLHttpReqEventListener_QueryInterface,
201 XMLHttpReqEventListener_AddRef,
202 XMLHttpReqEventListener_Release,
203 XMLHttpReqEventListener_HandleEvent
206 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
208 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
211 static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *iface, REFIID riid, void **ppv)
213 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
215 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
217 if(IsEqualGUID(&IID_IUnknown, riid)) {
218 *ppv = &This->IHTMLXMLHttpRequest_iface;
219 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
220 *ppv = &This->IHTMLXMLHttpRequest_iface;
221 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest, riid)) {
222 *ppv = &This->IHTMLXMLHttpRequest_iface;
223 }else if(dispex_query_interface(&This->event_target.dispex, riid, ppv)) {
224 return *ppv ? S_OK : E_NOINTERFACE;
225 }else {
226 *ppv = NULL;
227 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
228 return E_NOINTERFACE;
231 IUnknown_AddRef((IUnknown*)*ppv);
232 return S_OK;
235 static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface)
237 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
238 LONG ref = InterlockedIncrement(&This->ref);
240 TRACE("(%p) ref=%d\n", This, ref);
242 return ref;
245 static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
247 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
248 LONG ref = InterlockedDecrement(&This->ref);
250 TRACE("(%p) ref=%d\n", This, ref);
252 if(!ref) {
253 if(This->event_listener)
254 detach_xhr_event_listener(This->event_listener);
255 release_event_target(&This->event_target);
256 release_dispex(&This->event_target.dispex);
257 nsIXMLHttpRequest_Release(This->nsxhr);
258 heap_free(This);
261 return ref;
264 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest *iface, UINT *pctinfo)
266 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
267 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
270 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest *iface, UINT iTInfo,
271 LCID lcid, ITypeInfo **ppTInfo)
273 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
275 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
278 static HRESULT WINAPI HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
279 LCID lcid, DISPID *rgDispId)
281 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
283 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
284 lcid, rgDispId);
287 static HRESULT WINAPI HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
288 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
290 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
292 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
293 pDispParams, pVarResult, pExcepInfo, puArgErr);
296 static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p)
298 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
299 UINT16 val;
300 nsresult nsres;
302 TRACE("(%p)->(%p)\n", This, p);
304 if(!p)
305 return E_POINTER;
306 nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &val);
307 if(NS_FAILED(nsres)) {
308 ERR("nsIXMLHttpRequest_GetReadyState failed: %08x\n", nsres);
309 return E_FAIL;
311 *p = val;
312 return S_OK;
315 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *iface, VARIANT *p)
317 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
318 FIXME("(%p)->(%p)\n", This, p);
319 return E_NOTIMPL;
322 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p)
324 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
325 nsAString nsstr;
326 nsresult nsres;
328 TRACE("(%p)->(%p)\n", This, p);
330 if(!p)
331 return E_POINTER;
333 nsAString_Init(&nsstr, NULL);
334 nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr);
335 return return_nsstr(nsres, &nsstr, p);
338 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p)
340 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
341 IXMLDOMDocument *xmldoc = NULL;
342 BSTR str;
343 HRESULT hres;
344 VARIANT_BOOL vbool;
345 IObjectSafety *safety;
347 TRACE("(%p)->(%p)\n", This, p);
349 hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc);
350 if(FAILED(hres)) {
351 ERR("CoCreateInstance failed: %08x\n", hres);
352 return hres;
355 hres = IHTMLXMLHttpRequest_get_responseText(iface, &str);
356 if(FAILED(hres)) {
357 IXMLDOMDocument_Release(xmldoc);
358 ERR("get_responseText failed: %08x\n", hres);
359 return hres;
362 hres = IXMLDOMDocument_loadXML(xmldoc, str, &vbool);
363 SysFreeString(str);
364 if(hres != S_OK || vbool != VARIANT_TRUE)
365 WARN("loadXML failed: %08x, returning an empty xmldoc\n", hres);
367 hres = IXMLDOMDocument_QueryInterface(xmldoc, &IID_IObjectSafety, (void**)&safety);
368 assert(SUCCEEDED(hres));
369 hres = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
370 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER,
371 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER);
372 assert(SUCCEEDED(hres));
373 IObjectSafety_Release(safety);
375 *p = (IDispatch*)xmldoc;
376 return S_OK;
379 static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, LONG *p)
381 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
382 DWORD val;
383 nsresult nsres;
384 TRACE("(%p)->(%p)\n", This, p);
386 if(!p)
387 return E_POINTER;
389 nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val);
390 if(NS_FAILED(nsres)) {
391 ERR("nsIXMLHttpRequest_GetStatus failed: %08x\n", nsres);
392 return E_FAIL;
394 *p = val;
395 if(val == 0)
396 return E_FAIL; /* WinAPI thinks this is an error */
398 return S_OK;
401 static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *iface, BSTR *p)
403 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
404 nsACString nscstr;
405 nsresult nsres;
406 HRESULT hres;
407 LONG state;
409 TRACE("(%p)->(%p)\n", This, p);
411 if(!p)
412 return E_POINTER;
414 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
415 if(FAILED(hres))
416 return hres;
418 if(state < 2) {
419 *p = NULL;
420 return E_FAIL;
423 nsACString_Init(&nscstr, NULL);
424 nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr);
425 return return_nscstr(nsres, &nscstr, p);
428 static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT v)
430 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
432 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
434 return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v);
437 static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p)
439 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
441 TRACE("(%p)->(%p)\n", This, p);
443 return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p);
446 static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface)
448 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
449 nsresult nsres;
451 TRACE("(%p)->()\n", This);
453 nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr);
454 if(NS_FAILED(nsres)) {
455 ERR("nsIXMLHttpRequest_SlowAbort failed: %08x\n", nsres);
456 return E_FAIL;
459 return S_OK;
462 static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
464 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
465 nsACString method, url;
466 nsAString user, password;
467 nsresult nsres;
468 HRESULT hres;
470 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword));
472 if(V_VT(&varAsync) != VT_BOOL) {
473 FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync));
474 return E_FAIL;
477 /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
478 * synchronous requests on the main thread have been deprecated due to the negative
479 * effects to the user experience.
481 if(!V_BOOL(&varAsync)) {
482 FIXME("Synchronous request is not supported yet\n");
483 return E_FAIL;
486 hres = variant_to_nsastr(varUser, &user);
487 if(FAILED(hres))
488 return hres;
489 hres = variant_to_nsastr(varPassword, &password);
490 if(FAILED(hres)) {
491 nsAString_Finish(&user);
492 return hres;
495 hres = bstr_to_nsacstr(bstrMethod, &method);
496 if(FAILED(hres)) {
497 nsAString_Finish(&user);
498 nsAString_Finish(&password);
499 return hres;
501 hres = bstr_to_nsacstr(bstrUrl, &url);
502 if(FAILED(hres)) {
503 nsAString_Finish(&user);
504 nsAString_Finish(&password);
505 nsACString_Finish(&method);
506 return hres;
509 nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, TRUE,
510 &user, &password, 0);
512 nsACString_Finish(&method);
513 nsACString_Finish(&url);
514 nsAString_Finish(&user);
515 nsAString_Finish(&password);
517 if(NS_FAILED(nsres)) {
518 ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres);
519 return E_FAIL;
522 return S_OK;
525 static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
527 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
528 nsIWritableVariant *nsbody = NULL;
529 nsresult nsres = NS_OK;
531 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody));
533 switch(V_VT(&varBody)) {
534 case VT_NULL:
535 case VT_EMPTY:
536 case VT_ERROR:
537 break;
538 case VT_BSTR: {
539 nsAString nsstr;
541 nsbody = create_nsvariant();
542 if(!nsbody)
543 return E_OUTOFMEMORY;
545 nsAString_InitDepend(&nsstr, V_BSTR(&varBody));
546 nsres = nsIWritableVariant_SetAsAString(nsbody, &nsstr);
547 nsAString_Finish(&nsstr);
548 break;
550 default:
551 FIXME("unsupported body type %s\n", debugstr_variant(&varBody));
552 return E_NOTIMPL;
555 if(NS_SUCCEEDED(nsres))
556 nsres = nsIXMLHttpRequest_Send(This->nsxhr, (nsIVariant*)nsbody);
557 if(nsbody)
558 nsIWritableVariant_Release(nsbody);
559 if(NS_FAILED(nsres)) {
560 ERR("nsIXMLHttpRequest_Send failed: %08x\n", nsres);
561 return E_FAIL;
564 return S_OK;
567 static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p)
569 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
570 nsACString nscstr;
571 nsresult nsres;
572 HRESULT hres;
573 LONG state;
575 TRACE("(%p)->(%p)\n", This, p);
577 if(!p)
578 return E_POINTER;
580 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
581 if(FAILED(hres))
582 return hres;
584 if(state < 2) {
585 *p = NULL;
586 return E_FAIL;
589 nsACString_Init(&nscstr, NULL);
590 nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr);
591 return return_nscstr(nsres, &nscstr, p);
594 static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR *p)
596 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
597 nsACString header, ret;
598 char *cstr;
599 nsresult nsres;
600 HRESULT hres;
601 LONG state;
602 TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrHeader), p);
604 if(!p)
605 return E_POINTER;
606 if(!bstrHeader)
607 return E_INVALIDARG;
609 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
610 if(FAILED(hres))
611 return hres;
613 if(state < 2) {
614 *p = NULL;
615 return E_FAIL;
618 cstr = heap_strdupWtoU(bstrHeader);
619 nsACString_InitDepend(&header, cstr);
620 nsACString_Init(&ret, NULL);
622 nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret);
624 nsACString_Finish(&header);
625 heap_free(cstr);
626 return return_nscstr(nsres, &ret, p);
629 static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR bstrValue)
631 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
632 char *header_u, *value_u;
633 nsACString header, value;
634 nsresult nsres;
636 TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
638 header_u = heap_strdupWtoU(bstrHeader);
639 if(bstrHeader && !header_u)
640 return E_OUTOFMEMORY;
642 value_u = heap_strdupWtoU(bstrValue);
643 if(bstrValue && !value_u) {
644 heap_free(header_u);
645 return E_OUTOFMEMORY;
648 nsACString_InitDepend(&header, header_u);
649 nsACString_InitDepend(&value, value_u);
650 nsres = nsIXMLHttpRequest_SetRequestHeader(This->nsxhr, &header, &value);
651 nsACString_Finish(&header);
652 nsACString_Finish(&value);
653 heap_free(header_u);
654 heap_free(value_u);
655 if(NS_FAILED(nsres)) {
656 ERR("SetRequestHeader failed: %08x\n", nsres);
657 return E_FAIL;
660 return S_OK;
663 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl = {
664 HTMLXMLHttpRequest_QueryInterface,
665 HTMLXMLHttpRequest_AddRef,
666 HTMLXMLHttpRequest_Release,
667 HTMLXMLHttpRequest_GetTypeInfoCount,
668 HTMLXMLHttpRequest_GetTypeInfo,
669 HTMLXMLHttpRequest_GetIDsOfNames,
670 HTMLXMLHttpRequest_Invoke,
671 HTMLXMLHttpRequest_get_readyState,
672 HTMLXMLHttpRequest_get_responseBody,
673 HTMLXMLHttpRequest_get_responseText,
674 HTMLXMLHttpRequest_get_responseXML,
675 HTMLXMLHttpRequest_get_status,
676 HTMLXMLHttpRequest_get_statusText,
677 HTMLXMLHttpRequest_put_onreadystatechange,
678 HTMLXMLHttpRequest_get_onreadystatechange,
679 HTMLXMLHttpRequest_abort,
680 HTMLXMLHttpRequest_open,
681 HTMLXMLHttpRequest_send,
682 HTMLXMLHttpRequest_getAllResponseHeaders,
683 HTMLXMLHttpRequest_getResponseHeader,
684 HTMLXMLHttpRequest_setRequestHeader
687 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
689 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex);
692 static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, int eid)
694 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
695 nsIDOMEventTarget *nstarget;
696 nsAString type_str;
697 nsresult nsres;
699 static const WCHAR readystatechangeW[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
701 TRACE("(%p)\n", This);
703 assert(eid == EVENTID_READYSTATECHANGE);
705 if(This->event_listener)
706 return;
708 This->event_listener = heap_alloc(sizeof(*This->event_listener));
709 if(!This->event_listener)
710 return;
712 This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
713 This->event_listener->ref = 1;
714 This->event_listener->xhr = This;
716 nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
717 assert(nsres == NS_OK);
719 nsAString_InitDepend(&type_str, readystatechangeW);
720 nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
721 nsAString_Finish(&type_str);
722 nsIDOMEventTarget_Release(nstarget);
723 if(NS_FAILED(nsres))
724 ERR("AddEventListener failed: %08x\n", nsres);
727 static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {
728 NULL,
729 NULL,
730 NULL,
731 NULL,
732 NULL,
733 HTMLXMLHttpRequest_bind_event
736 static const tid_t HTMLXMLHttpRequest_iface_tids[] = {
737 IHTMLXMLHttpRequest_tid,
740 static dispex_static_data_t HTMLXMLHttpRequest_dispex = {
741 &HTMLXMLHttpRequest_dispex_vtbl,
742 DispHTMLXMLHttpRequest_tid,
743 HTMLXMLHttpRequest_iface_tids
747 /* IHTMLXMLHttpRequestFactory */
748 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface)
750 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface);
753 static HRESULT WINAPI HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory *iface, REFIID riid, void **ppv)
755 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
757 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
759 if(IsEqualGUID(&IID_IUnknown, riid)) {
760 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
761 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
762 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
763 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) {
764 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
765 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
766 return *ppv ? S_OK : E_NOINTERFACE;
767 }else {
768 *ppv = NULL;
769 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
770 return E_NOINTERFACE;
773 IUnknown_AddRef((IUnknown*)*ppv);
774 return S_OK;
777 static ULONG WINAPI HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory *iface)
779 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
780 LONG ref = InterlockedIncrement(&This->ref);
782 TRACE("(%p) ref=%d\n", This, ref);
784 return ref;
787 static ULONG WINAPI HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory *iface)
789 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
790 LONG ref = InterlockedDecrement(&This->ref);
792 TRACE("(%p) ref=%d\n", This, ref);
794 if(!ref) {
795 release_dispex(&This->dispex);
796 heap_free(This);
799 return ref;
802 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory *iface, UINT *pctinfo)
804 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
805 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
808 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory *iface, UINT iTInfo,
809 LCID lcid, ITypeInfo **ppTInfo)
811 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
813 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
816 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
817 LCID lcid, DISPID *rgDispId)
819 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
821 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
822 lcid, rgDispId);
825 static HRESULT WINAPI HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
826 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
828 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
830 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
831 pDispParams, pVarResult, pExcepInfo, puArgErr);
834 static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p)
836 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
837 HTMLXMLHttpRequest *ret;
838 nsIXMLHttpRequest *nsxhr;
840 TRACE("(%p)->(%p)\n", This, p);
842 nsxhr = create_nsxhr(This->window->base.outer_window->nswindow);
843 if(!nsxhr)
844 return E_FAIL;
846 ret = heap_alloc_zero(sizeof(*ret));
847 if(!ret) {
848 nsIXMLHttpRequest_Release(nsxhr);
849 return E_OUTOFMEMORY;
851 ret->nsxhr = nsxhr;
853 ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
854 init_event_target(&ret->event_target);
855 init_dispex(&ret->event_target.dispex, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
856 &HTMLXMLHttpRequest_dispex);
857 ret->ref = 1;
859 *p = &ret->IHTMLXMLHttpRequest_iface;
860 return S_OK;
863 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = {
864 HTMLXMLHttpRequestFactory_QueryInterface,
865 HTMLXMLHttpRequestFactory_AddRef,
866 HTMLXMLHttpRequestFactory_Release,
867 HTMLXMLHttpRequestFactory_GetTypeInfoCount,
868 HTMLXMLHttpRequestFactory_GetTypeInfo,
869 HTMLXMLHttpRequestFactory_GetIDsOfNames,
870 HTMLXMLHttpRequestFactory_Invoke,
871 HTMLXMLHttpRequestFactory_create
874 static inline HTMLXMLHttpRequestFactory *factory_from_DispatchEx(DispatchEx *iface)
876 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, dispex);
879 static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WORD flags, DISPPARAMS *params,
880 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
882 HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(iface);
883 IHTMLXMLHttpRequest *xhr;
884 HRESULT hres;
886 TRACE("\n");
888 if(flags != DISPATCH_CONSTRUCT) {
889 FIXME("flags %x not supported\n", flags);
890 return E_NOTIMPL;
893 hres = IHTMLXMLHttpRequestFactory_create(&This->IHTMLXMLHttpRequestFactory_iface, &xhr);
894 if(FAILED(hres))
895 return hres;
897 V_VT(res) = VT_DISPATCH;
898 V_DISPATCH(res) = (IDispatch*)xhr;
899 return S_OK;
902 static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl = {
903 HTMLXMLHttpRequestFactory_value
906 static const tid_t HTMLXMLHttpRequestFactory_iface_tids[] = {
907 IHTMLXMLHttpRequestFactory_tid,
910 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = {
911 &HTMLXMLHttpRequestFactory_dispex_vtbl,
912 IHTMLXMLHttpRequestFactory_tid,
913 HTMLXMLHttpRequestFactory_iface_tids
916 HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpRequestFactory **ret_ptr)
918 HTMLXMLHttpRequestFactory *ret;
920 ret = heap_alloc(sizeof(*ret));
921 if(!ret)
922 return E_OUTOFMEMORY;
924 ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl;
925 ret->ref = 1;
926 ret->window = window;
928 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLXMLHttpRequestFactory_iface,
929 &HTMLXMLHttpRequestFactory_dispex);
931 *ret_ptr = ret;
932 return S_OK;