mshtml: Rename fire_event_obj and dispatch_event.
[wine.git] / dlls / mshtml / xmlhttprequest.c
bloba107fa23416dbc9ea7c67200eb2994f42036a5f9
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 {
96 nsIDOMEventListener nsIDOMEventListener_iface;
97 LONG ref;
98 HTMLXMLHttpRequest *xhr;
99 } XMLHttpReqEventListener;
101 struct HTMLXMLHttpRequest {
102 EventTarget event_target;
103 IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
104 IProvideClassInfo2 IProvideClassInfo2_iface;
105 LONG ref;
106 nsIXMLHttpRequest *nsxhr;
107 XMLHttpReqEventListener *event_listener;
110 static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener)
112 nsIDOMEventTarget *event_target;
113 nsAString str;
114 nsresult nsres;
116 static const WCHAR readystatechangeW[] =
117 {'o','n','r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
119 nsres = nsIXMLHttpRequest_QueryInterface(event_listener->xhr->nsxhr, &IID_nsIDOMEventTarget, (void**)&event_target);
120 assert(nsres == NS_OK);
122 nsAString_InitDepend(&str, readystatechangeW);
123 nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE);
124 nsAString_Finish(&str);
125 nsIDOMEventTarget_Release(event_target);
127 event_listener->xhr->event_listener = NULL;
128 event_listener->xhr = NULL;
129 nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface);
133 static inline XMLHttpReqEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface)
135 return CONTAINING_RECORD(iface, XMLHttpReqEventListener, nsIDOMEventListener_iface);
138 static nsresult NSAPI XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener *iface,
139 nsIIDRef riid, void **result)
141 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
143 if(IsEqualGUID(&IID_nsISupports, riid)) {
144 TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
145 *result = &This->nsIDOMEventListener_iface;
146 }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
147 TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
148 *result = &This->nsIDOMEventListener_iface;
149 }else {
150 *result = NULL;
151 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
152 return NS_NOINTERFACE;
155 nsIDOMEventListener_AddRef(&This->nsIDOMEventListener_iface);
156 return NS_OK;
159 static nsrefcnt NSAPI XMLHttpReqEventListener_AddRef(nsIDOMEventListener *iface)
161 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
162 LONG ref = InterlockedIncrement(&This->ref);
164 TRACE("(%p) ref=%d\n", This, ref);
166 return ref;
169 static nsrefcnt NSAPI XMLHttpReqEventListener_Release(nsIDOMEventListener *iface)
171 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
172 LONG ref = InterlockedDecrement(&This->ref);
174 TRACE("(%p) ref=%d\n", This, ref);
176 if(!ref) {
177 assert(!This->xhr);
178 heap_free(This);
181 return ref;
184 static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *nsevent)
186 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
187 DOMEvent *event;
188 HRESULT hres;
190 TRACE("(%p)\n", This);
192 if(!This->xhr)
193 return NS_OK;
195 hres = create_event_from_nsevent(nsevent, &event);
196 if(SUCCEEDED(hres) ){
197 event->no_event_obj = TRUE;
198 dispatch_event(&This->xhr->event_target, event);
199 IDOMEvent_Release(&event->IDOMEvent_iface);
201 return NS_OK;
204 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
205 XMLHttpReqEventListener_QueryInterface,
206 XMLHttpReqEventListener_AddRef,
207 XMLHttpReqEventListener_Release,
208 XMLHttpReqEventListener_HandleEvent
211 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
213 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
216 static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *iface, REFIID riid, void **ppv)
218 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
220 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
222 if(IsEqualGUID(&IID_IUnknown, riid)) {
223 *ppv = &This->IHTMLXMLHttpRequest_iface;
224 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
225 *ppv = &This->IHTMLXMLHttpRequest_iface;
226 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest, riid)) {
227 *ppv = &This->IHTMLXMLHttpRequest_iface;
228 }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
229 *ppv = &This->IProvideClassInfo2_iface;
230 }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
231 *ppv = &This->IProvideClassInfo2_iface;
232 }else {
233 return EventTarget_QI(&This->event_target, riid, ppv);
236 IUnknown_AddRef((IUnknown*)*ppv);
237 return S_OK;
240 static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface)
242 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
243 LONG ref = InterlockedIncrement(&This->ref);
245 TRACE("(%p) ref=%d\n", This, ref);
247 return ref;
250 static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
252 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
253 LONG ref = InterlockedDecrement(&This->ref);
255 TRACE("(%p) ref=%d\n", This, ref);
257 if(!ref) {
258 if(This->event_listener)
259 detach_xhr_event_listener(This->event_listener);
260 release_event_target(&This->event_target);
261 release_dispex(&This->event_target.dispex);
262 nsIXMLHttpRequest_Release(This->nsxhr);
263 heap_free(This);
266 return ref;
269 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest *iface, UINT *pctinfo)
271 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
272 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
275 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest *iface, UINT iTInfo,
276 LCID lcid, ITypeInfo **ppTInfo)
278 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
280 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
283 static HRESULT WINAPI HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
284 LCID lcid, DISPID *rgDispId)
286 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
288 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
289 lcid, rgDispId);
292 static HRESULT WINAPI HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
293 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
295 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
297 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
298 pDispParams, pVarResult, pExcepInfo, puArgErr);
301 static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p)
303 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
304 UINT16 val;
305 nsresult nsres;
307 TRACE("(%p)->(%p)\n", This, p);
309 if(!p)
310 return E_POINTER;
311 nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &val);
312 if(NS_FAILED(nsres)) {
313 ERR("nsIXMLHttpRequest_GetReadyState failed: %08x\n", nsres);
314 return E_FAIL;
316 *p = val;
317 return S_OK;
320 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *iface, VARIANT *p)
322 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
323 FIXME("(%p)->(%p)\n", This, p);
324 return E_NOTIMPL;
327 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p)
329 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
330 nsAString nsstr;
331 nsresult nsres;
333 TRACE("(%p)->(%p)\n", This, p);
335 if(!p)
336 return E_POINTER;
338 nsAString_Init(&nsstr, NULL);
339 nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr);
340 return return_nsstr(nsres, &nsstr, p);
343 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p)
345 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
346 IXMLDOMDocument *xmldoc = NULL;
347 BSTR str;
348 HRESULT hres;
349 VARIANT_BOOL vbool;
350 IObjectSafety *safety;
352 TRACE("(%p)->(%p)\n", This, p);
354 hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc);
355 if(FAILED(hres)) {
356 ERR("CoCreateInstance failed: %08x\n", hres);
357 return hres;
360 hres = IHTMLXMLHttpRequest_get_responseText(iface, &str);
361 if(FAILED(hres)) {
362 IXMLDOMDocument_Release(xmldoc);
363 ERR("get_responseText failed: %08x\n", hres);
364 return hres;
367 hres = IXMLDOMDocument_loadXML(xmldoc, str, &vbool);
368 SysFreeString(str);
369 if(hres != S_OK || vbool != VARIANT_TRUE)
370 WARN("loadXML failed: %08x, returning an empty xmldoc\n", hres);
372 hres = IXMLDOMDocument_QueryInterface(xmldoc, &IID_IObjectSafety, (void**)&safety);
373 assert(SUCCEEDED(hres));
374 hres = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
375 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER,
376 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER);
377 assert(SUCCEEDED(hres));
378 IObjectSafety_Release(safety);
380 *p = (IDispatch*)xmldoc;
381 return S_OK;
384 static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, LONG *p)
386 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
387 DWORD val;
388 nsresult nsres;
389 TRACE("(%p)->(%p)\n", This, p);
391 if(!p)
392 return E_POINTER;
394 nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val);
395 if(NS_FAILED(nsres)) {
396 ERR("nsIXMLHttpRequest_GetStatus failed: %08x\n", nsres);
397 return E_FAIL;
399 *p = val;
400 if(val == 0)
401 return E_FAIL; /* WinAPI thinks this is an error */
403 return S_OK;
406 static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *iface, BSTR *p)
408 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
409 nsACString nscstr;
410 nsresult nsres;
411 HRESULT hres;
412 LONG state;
414 TRACE("(%p)->(%p)\n", This, p);
416 if(!p)
417 return E_POINTER;
419 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
420 if(FAILED(hres))
421 return hres;
423 if(state < 2) {
424 *p = NULL;
425 return E_FAIL;
428 nsACString_Init(&nscstr, NULL);
429 nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr);
430 return return_nscstr(nsres, &nscstr, p);
433 static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT v)
435 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
437 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
439 return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v);
442 static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p)
444 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
446 TRACE("(%p)->(%p)\n", This, p);
448 return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p);
451 static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface)
453 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
454 nsresult nsres;
456 TRACE("(%p)->()\n", This);
458 nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr);
459 if(NS_FAILED(nsres)) {
460 ERR("nsIXMLHttpRequest_SlowAbort failed: %08x\n", nsres);
461 return E_FAIL;
464 return S_OK;
467 static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
469 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
470 nsACString method, url;
471 nsAString user, password;
472 nsresult nsres;
473 HRESULT hres;
475 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword));
477 if(V_VT(&varAsync) != VT_BOOL) {
478 FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync));
479 return E_FAIL;
482 /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
483 * synchronous requests on the main thread have been deprecated due to the negative
484 * effects to the user experience.
486 if(!V_BOOL(&varAsync)) {
487 FIXME("Synchronous request is not supported yet\n");
488 return E_FAIL;
491 hres = variant_to_nsastr(varUser, &user);
492 if(FAILED(hres))
493 return hres;
494 hres = variant_to_nsastr(varPassword, &password);
495 if(FAILED(hres)) {
496 nsAString_Finish(&user);
497 return hres;
500 hres = bstr_to_nsacstr(bstrMethod, &method);
501 if(FAILED(hres)) {
502 nsAString_Finish(&user);
503 nsAString_Finish(&password);
504 return hres;
506 hres = bstr_to_nsacstr(bstrUrl, &url);
507 if(FAILED(hres)) {
508 nsAString_Finish(&user);
509 nsAString_Finish(&password);
510 nsACString_Finish(&method);
511 return hres;
514 nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, TRUE,
515 &user, &password, 0);
517 nsACString_Finish(&method);
518 nsACString_Finish(&url);
519 nsAString_Finish(&user);
520 nsAString_Finish(&password);
522 if(NS_FAILED(nsres)) {
523 ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres);
524 return E_FAIL;
527 return S_OK;
530 static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
532 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
533 nsIWritableVariant *nsbody = NULL;
534 nsresult nsres = NS_OK;
536 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody));
538 switch(V_VT(&varBody)) {
539 case VT_NULL:
540 case VT_EMPTY:
541 case VT_ERROR:
542 break;
543 case VT_BSTR: {
544 nsAString nsstr;
546 nsbody = create_nsvariant();
547 if(!nsbody)
548 return E_OUTOFMEMORY;
550 nsAString_InitDepend(&nsstr, V_BSTR(&varBody));
551 nsres = nsIWritableVariant_SetAsAString(nsbody, &nsstr);
552 nsAString_Finish(&nsstr);
553 break;
555 default:
556 FIXME("unsupported body type %s\n", debugstr_variant(&varBody));
557 return E_NOTIMPL;
560 if(NS_SUCCEEDED(nsres))
561 nsres = nsIXMLHttpRequest_Send(This->nsxhr, (nsIVariant*)nsbody);
562 if(nsbody)
563 nsIWritableVariant_Release(nsbody);
564 if(NS_FAILED(nsres)) {
565 ERR("nsIXMLHttpRequest_Send failed: %08x\n", nsres);
566 return E_FAIL;
569 return S_OK;
572 static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p)
574 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
575 nsACString nscstr;
576 nsresult nsres;
577 HRESULT hres;
578 LONG state;
580 TRACE("(%p)->(%p)\n", This, p);
582 if(!p)
583 return E_POINTER;
585 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
586 if(FAILED(hres))
587 return hres;
589 if(state < 2) {
590 *p = NULL;
591 return E_FAIL;
594 nsACString_Init(&nscstr, NULL);
595 nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr);
596 return return_nscstr(nsres, &nscstr, p);
599 static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR *p)
601 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
602 nsACString header, ret;
603 char *cstr;
604 nsresult nsres;
605 HRESULT hres;
606 LONG state;
607 TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrHeader), p);
609 if(!p)
610 return E_POINTER;
611 if(!bstrHeader)
612 return E_INVALIDARG;
614 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
615 if(FAILED(hres))
616 return hres;
618 if(state < 2) {
619 *p = NULL;
620 return E_FAIL;
623 cstr = heap_strdupWtoU(bstrHeader);
624 nsACString_InitDepend(&header, cstr);
625 nsACString_Init(&ret, NULL);
627 nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret);
629 nsACString_Finish(&header);
630 heap_free(cstr);
631 return return_nscstr(nsres, &ret, p);
634 static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR bstrValue)
636 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
637 char *header_u, *value_u;
638 nsACString header, value;
639 nsresult nsres;
641 TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
643 header_u = heap_strdupWtoU(bstrHeader);
644 if(bstrHeader && !header_u)
645 return E_OUTOFMEMORY;
647 value_u = heap_strdupWtoU(bstrValue);
648 if(bstrValue && !value_u) {
649 heap_free(header_u);
650 return E_OUTOFMEMORY;
653 nsACString_InitDepend(&header, header_u);
654 nsACString_InitDepend(&value, value_u);
655 nsres = nsIXMLHttpRequest_SetRequestHeader(This->nsxhr, &header, &value);
656 nsACString_Finish(&header);
657 nsACString_Finish(&value);
658 heap_free(header_u);
659 heap_free(value_u);
660 if(NS_FAILED(nsres)) {
661 ERR("SetRequestHeader failed: %08x\n", nsres);
662 return E_FAIL;
665 return S_OK;
668 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl = {
669 HTMLXMLHttpRequest_QueryInterface,
670 HTMLXMLHttpRequest_AddRef,
671 HTMLXMLHttpRequest_Release,
672 HTMLXMLHttpRequest_GetTypeInfoCount,
673 HTMLXMLHttpRequest_GetTypeInfo,
674 HTMLXMLHttpRequest_GetIDsOfNames,
675 HTMLXMLHttpRequest_Invoke,
676 HTMLXMLHttpRequest_get_readyState,
677 HTMLXMLHttpRequest_get_responseBody,
678 HTMLXMLHttpRequest_get_responseText,
679 HTMLXMLHttpRequest_get_responseXML,
680 HTMLXMLHttpRequest_get_status,
681 HTMLXMLHttpRequest_get_statusText,
682 HTMLXMLHttpRequest_put_onreadystatechange,
683 HTMLXMLHttpRequest_get_onreadystatechange,
684 HTMLXMLHttpRequest_abort,
685 HTMLXMLHttpRequest_open,
686 HTMLXMLHttpRequest_send,
687 HTMLXMLHttpRequest_getAllResponseHeaders,
688 HTMLXMLHttpRequest_getResponseHeader,
689 HTMLXMLHttpRequest_setRequestHeader
692 static inline HTMLXMLHttpRequest *impl_from_IProvideClassInfo2(IProvideClassInfo2 *iface)
694 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IProvideClassInfo2_iface);
697 static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, void **ppv)
699 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
700 return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
703 static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo2 *iface)
705 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
706 return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
709 static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo2 *iface)
711 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
712 return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
715 static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI)
717 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
718 TRACE("(%p)->(%p)\n", This, ppTI);
719 return get_class_typeinfo(&CLSID_HTMLXMLHttpRequest, ppTI);
722 static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID)
724 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
725 FIXME("(%p)->(%u %p)\n", This, dwGuidKind, pGUID);
726 return E_NOTIMPL;
729 static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
730 ProvideClassInfo_QueryInterface,
731 ProvideClassInfo_AddRef,
732 ProvideClassInfo_Release,
733 ProvideClassInfo_GetClassInfo,
734 ProvideClassInfo2_GetGUID,
737 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
739 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex);
742 static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, eventid_t eid)
744 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
745 nsIDOMEventTarget *nstarget;
746 nsAString type_str;
747 nsresult nsres;
749 static const WCHAR readystatechangeW[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
751 TRACE("(%p)\n", This);
753 assert(eid == EVENTID_READYSTATECHANGE);
755 if(This->event_listener)
756 return;
758 This->event_listener = heap_alloc(sizeof(*This->event_listener));
759 if(!This->event_listener)
760 return;
762 This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
763 This->event_listener->ref = 1;
764 This->event_listener->xhr = This;
766 nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
767 assert(nsres == NS_OK);
769 nsAString_InitDepend(&type_str, readystatechangeW);
770 nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
771 nsAString_Finish(&type_str);
772 nsIDOMEventTarget_Release(nstarget);
773 if(NS_FAILED(nsres))
774 ERR("AddEventListener failed: %08x\n", nsres);
777 static event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = {
778 {NULL},
779 HTMLXMLHttpRequest_bind_event
782 static const tid_t HTMLXMLHttpRequest_iface_tids[] = {
783 IHTMLXMLHttpRequest_tid,
786 static dispex_static_data_t HTMLXMLHttpRequest_dispex = {
787 &HTMLXMLHttpRequest_event_target_vtbl.dispex_vtbl,
788 DispHTMLXMLHttpRequest_tid,
789 HTMLXMLHttpRequest_iface_tids
793 /* IHTMLXMLHttpRequestFactory */
794 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface)
796 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface);
799 static HRESULT WINAPI HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory *iface, REFIID riid, void **ppv)
801 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
803 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
805 if(IsEqualGUID(&IID_IUnknown, riid)) {
806 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
807 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
808 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
809 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) {
810 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
811 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
812 return *ppv ? S_OK : E_NOINTERFACE;
813 }else {
814 *ppv = NULL;
815 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
816 return E_NOINTERFACE;
819 IUnknown_AddRef((IUnknown*)*ppv);
820 return S_OK;
823 static ULONG WINAPI HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory *iface)
825 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
826 LONG ref = InterlockedIncrement(&This->ref);
828 TRACE("(%p) ref=%d\n", This, ref);
830 return ref;
833 static ULONG WINAPI HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory *iface)
835 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
836 LONG ref = InterlockedDecrement(&This->ref);
838 TRACE("(%p) ref=%d\n", This, ref);
840 if(!ref) {
841 release_dispex(&This->dispex);
842 heap_free(This);
845 return ref;
848 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory *iface, UINT *pctinfo)
850 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
851 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
854 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory *iface, UINT iTInfo,
855 LCID lcid, ITypeInfo **ppTInfo)
857 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
859 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
862 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
863 LCID lcid, DISPID *rgDispId)
865 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
867 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
868 lcid, rgDispId);
871 static HRESULT WINAPI HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
872 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
874 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
876 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
877 pDispParams, pVarResult, pExcepInfo, puArgErr);
880 static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p)
882 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
883 HTMLXMLHttpRequest *ret;
884 nsIXMLHttpRequest *nsxhr;
886 TRACE("(%p)->(%p)\n", This, p);
888 nsxhr = create_nsxhr(This->window->base.outer_window->nswindow);
889 if(!nsxhr)
890 return E_FAIL;
892 ret = heap_alloc_zero(sizeof(*ret));
893 if(!ret) {
894 nsIXMLHttpRequest_Release(nsxhr);
895 return E_OUTOFMEMORY;
897 ret->nsxhr = nsxhr;
899 ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
900 ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl;
901 EventTarget_Init(&ret->event_target, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
902 &HTMLXMLHttpRequest_dispex, COMPAT_MODE_NONE);
903 ret->ref = 1;
905 *p = &ret->IHTMLXMLHttpRequest_iface;
906 return S_OK;
909 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = {
910 HTMLXMLHttpRequestFactory_QueryInterface,
911 HTMLXMLHttpRequestFactory_AddRef,
912 HTMLXMLHttpRequestFactory_Release,
913 HTMLXMLHttpRequestFactory_GetTypeInfoCount,
914 HTMLXMLHttpRequestFactory_GetTypeInfo,
915 HTMLXMLHttpRequestFactory_GetIDsOfNames,
916 HTMLXMLHttpRequestFactory_Invoke,
917 HTMLXMLHttpRequestFactory_create
920 static inline HTMLXMLHttpRequestFactory *factory_from_DispatchEx(DispatchEx *iface)
922 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, dispex);
925 static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WORD flags, DISPPARAMS *params,
926 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
928 HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(iface);
929 IHTMLXMLHttpRequest *xhr;
930 HRESULT hres;
932 TRACE("\n");
934 if(flags != DISPATCH_CONSTRUCT) {
935 FIXME("flags %x not supported\n", flags);
936 return E_NOTIMPL;
939 hres = IHTMLXMLHttpRequestFactory_create(&This->IHTMLXMLHttpRequestFactory_iface, &xhr);
940 if(FAILED(hres))
941 return hres;
943 V_VT(res) = VT_DISPATCH;
944 V_DISPATCH(res) = (IDispatch*)xhr;
945 return S_OK;
948 static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl = {
949 HTMLXMLHttpRequestFactory_value
952 static const tid_t HTMLXMLHttpRequestFactory_iface_tids[] = {
953 IHTMLXMLHttpRequestFactory_tid,
956 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = {
957 &HTMLXMLHttpRequestFactory_dispex_vtbl,
958 IHTMLXMLHttpRequestFactory_tid,
959 HTMLXMLHttpRequestFactory_iface_tids
962 HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpRequestFactory **ret_ptr)
964 HTMLXMLHttpRequestFactory *ret;
966 ret = heap_alloc(sizeof(*ret));
967 if(!ret)
968 return E_OUTOFMEMORY;
970 ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl;
971 ret->ref = 1;
972 ret->window = window;
974 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLXMLHttpRequestFactory_iface,
975 &HTMLXMLHttpRequestFactory_dispex);
977 *ret_ptr = ret;
978 return S_OK;