webservices: Implement the Message Framing Protocol.
[wine.git] / dlls / mshtml / xmlhttprequest.c
blob1565f9bf3765f5b0f5bac33b890ba95280c79f80
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 *event)
186 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
188 TRACE("(%p)\n", This);
190 if(!This->xhr)
191 return NS_OK;
193 call_event_handlers(NULL, NULL, &This->xhr->event_target, NULL, EVENTID_READYSTATECHANGE,
194 (IDispatch*)&This->xhr->IHTMLXMLHttpRequest_iface);
195 return NS_OK;
198 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
199 XMLHttpReqEventListener_QueryInterface,
200 XMLHttpReqEventListener_AddRef,
201 XMLHttpReqEventListener_Release,
202 XMLHttpReqEventListener_HandleEvent
205 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
207 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
210 static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *iface, REFIID riid, void **ppv)
212 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
214 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
216 if(IsEqualGUID(&IID_IUnknown, riid)) {
217 *ppv = &This->IHTMLXMLHttpRequest_iface;
218 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
219 *ppv = &This->IHTMLXMLHttpRequest_iface;
220 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest, riid)) {
221 *ppv = &This->IHTMLXMLHttpRequest_iface;
222 }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
223 *ppv = &This->IProvideClassInfo2_iface;
224 }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
225 *ppv = &This->IProvideClassInfo2_iface;
226 }else if(dispex_query_interface(&This->event_target.dispex, riid, ppv)) {
227 return *ppv ? S_OK : E_NOINTERFACE;
228 }else {
229 *ppv = NULL;
230 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
231 return E_NOINTERFACE;
234 IUnknown_AddRef((IUnknown*)*ppv);
235 return S_OK;
238 static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface)
240 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
241 LONG ref = InterlockedIncrement(&This->ref);
243 TRACE("(%p) ref=%d\n", This, ref);
245 return ref;
248 static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
250 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
251 LONG ref = InterlockedDecrement(&This->ref);
253 TRACE("(%p) ref=%d\n", This, ref);
255 if(!ref) {
256 if(This->event_listener)
257 detach_xhr_event_listener(This->event_listener);
258 release_event_target(&This->event_target);
259 release_dispex(&This->event_target.dispex);
260 nsIXMLHttpRequest_Release(This->nsxhr);
261 heap_free(This);
264 return ref;
267 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest *iface, UINT *pctinfo)
269 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
270 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
273 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest *iface, UINT iTInfo,
274 LCID lcid, ITypeInfo **ppTInfo)
276 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
278 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
281 static HRESULT WINAPI HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
282 LCID lcid, DISPID *rgDispId)
284 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
286 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
287 lcid, rgDispId);
290 static HRESULT WINAPI HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
291 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
293 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
295 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
296 pDispParams, pVarResult, pExcepInfo, puArgErr);
299 static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p)
301 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
302 UINT16 val;
303 nsresult nsres;
305 TRACE("(%p)->(%p)\n", This, p);
307 if(!p)
308 return E_POINTER;
309 nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &val);
310 if(NS_FAILED(nsres)) {
311 ERR("nsIXMLHttpRequest_GetReadyState failed: %08x\n", nsres);
312 return E_FAIL;
314 *p = val;
315 return S_OK;
318 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *iface, VARIANT *p)
320 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
321 FIXME("(%p)->(%p)\n", This, p);
322 return E_NOTIMPL;
325 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p)
327 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
328 nsAString nsstr;
329 nsresult nsres;
331 TRACE("(%p)->(%p)\n", This, p);
333 if(!p)
334 return E_POINTER;
336 nsAString_Init(&nsstr, NULL);
337 nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr);
338 return return_nsstr(nsres, &nsstr, p);
341 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p)
343 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
344 IXMLDOMDocument *xmldoc = NULL;
345 BSTR str;
346 HRESULT hres;
347 VARIANT_BOOL vbool;
348 IObjectSafety *safety;
350 TRACE("(%p)->(%p)\n", This, p);
352 hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc);
353 if(FAILED(hres)) {
354 ERR("CoCreateInstance failed: %08x\n", hres);
355 return hres;
358 hres = IHTMLXMLHttpRequest_get_responseText(iface, &str);
359 if(FAILED(hres)) {
360 IXMLDOMDocument_Release(xmldoc);
361 ERR("get_responseText failed: %08x\n", hres);
362 return hres;
365 hres = IXMLDOMDocument_loadXML(xmldoc, str, &vbool);
366 SysFreeString(str);
367 if(hres != S_OK || vbool != VARIANT_TRUE)
368 WARN("loadXML failed: %08x, returning an empty xmldoc\n", hres);
370 hres = IXMLDOMDocument_QueryInterface(xmldoc, &IID_IObjectSafety, (void**)&safety);
371 assert(SUCCEEDED(hres));
372 hres = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
373 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER,
374 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER);
375 assert(SUCCEEDED(hres));
376 IObjectSafety_Release(safety);
378 *p = (IDispatch*)xmldoc;
379 return S_OK;
382 static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, LONG *p)
384 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
385 DWORD val;
386 nsresult nsres;
387 TRACE("(%p)->(%p)\n", This, p);
389 if(!p)
390 return E_POINTER;
392 nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val);
393 if(NS_FAILED(nsres)) {
394 ERR("nsIXMLHttpRequest_GetStatus failed: %08x\n", nsres);
395 return E_FAIL;
397 *p = val;
398 if(val == 0)
399 return E_FAIL; /* WinAPI thinks this is an error */
401 return S_OK;
404 static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *iface, BSTR *p)
406 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
407 nsACString nscstr;
408 nsresult nsres;
409 HRESULT hres;
410 LONG state;
412 TRACE("(%p)->(%p)\n", This, p);
414 if(!p)
415 return E_POINTER;
417 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
418 if(FAILED(hres))
419 return hres;
421 if(state < 2) {
422 *p = NULL;
423 return E_FAIL;
426 nsACString_Init(&nscstr, NULL);
427 nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr);
428 return return_nscstr(nsres, &nscstr, p);
431 static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT v)
433 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
435 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
437 return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v);
440 static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p)
442 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
444 TRACE("(%p)->(%p)\n", This, p);
446 return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p);
449 static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface)
451 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
452 nsresult nsres;
454 TRACE("(%p)->()\n", This);
456 nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr);
457 if(NS_FAILED(nsres)) {
458 ERR("nsIXMLHttpRequest_SlowAbort failed: %08x\n", nsres);
459 return E_FAIL;
462 return S_OK;
465 static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
467 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
468 nsACString method, url;
469 nsAString user, password;
470 nsresult nsres;
471 HRESULT hres;
473 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword));
475 if(V_VT(&varAsync) != VT_BOOL) {
476 FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync));
477 return E_FAIL;
480 /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
481 * synchronous requests on the main thread have been deprecated due to the negative
482 * effects to the user experience.
484 if(!V_BOOL(&varAsync)) {
485 FIXME("Synchronous request is not supported yet\n");
486 return E_FAIL;
489 hres = variant_to_nsastr(varUser, &user);
490 if(FAILED(hres))
491 return hres;
492 hres = variant_to_nsastr(varPassword, &password);
493 if(FAILED(hres)) {
494 nsAString_Finish(&user);
495 return hres;
498 hres = bstr_to_nsacstr(bstrMethod, &method);
499 if(FAILED(hres)) {
500 nsAString_Finish(&user);
501 nsAString_Finish(&password);
502 return hres;
504 hres = bstr_to_nsacstr(bstrUrl, &url);
505 if(FAILED(hres)) {
506 nsAString_Finish(&user);
507 nsAString_Finish(&password);
508 nsACString_Finish(&method);
509 return hres;
512 nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, TRUE,
513 &user, &password, 0);
515 nsACString_Finish(&method);
516 nsACString_Finish(&url);
517 nsAString_Finish(&user);
518 nsAString_Finish(&password);
520 if(NS_FAILED(nsres)) {
521 ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres);
522 return E_FAIL;
525 return S_OK;
528 static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
530 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
531 nsIWritableVariant *nsbody = NULL;
532 nsresult nsres = NS_OK;
534 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody));
536 switch(V_VT(&varBody)) {
537 case VT_NULL:
538 case VT_EMPTY:
539 case VT_ERROR:
540 break;
541 case VT_BSTR: {
542 nsAString nsstr;
544 nsbody = create_nsvariant();
545 if(!nsbody)
546 return E_OUTOFMEMORY;
548 nsAString_InitDepend(&nsstr, V_BSTR(&varBody));
549 nsres = nsIWritableVariant_SetAsAString(nsbody, &nsstr);
550 nsAString_Finish(&nsstr);
551 break;
553 default:
554 FIXME("unsupported body type %s\n", debugstr_variant(&varBody));
555 return E_NOTIMPL;
558 if(NS_SUCCEEDED(nsres))
559 nsres = nsIXMLHttpRequest_Send(This->nsxhr, (nsIVariant*)nsbody);
560 if(nsbody)
561 nsIWritableVariant_Release(nsbody);
562 if(NS_FAILED(nsres)) {
563 ERR("nsIXMLHttpRequest_Send failed: %08x\n", nsres);
564 return E_FAIL;
567 return S_OK;
570 static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p)
572 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
573 nsACString nscstr;
574 nsresult nsres;
575 HRESULT hres;
576 LONG state;
578 TRACE("(%p)->(%p)\n", This, p);
580 if(!p)
581 return E_POINTER;
583 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
584 if(FAILED(hres))
585 return hres;
587 if(state < 2) {
588 *p = NULL;
589 return E_FAIL;
592 nsACString_Init(&nscstr, NULL);
593 nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr);
594 return return_nscstr(nsres, &nscstr, p);
597 static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR *p)
599 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
600 nsACString header, ret;
601 char *cstr;
602 nsresult nsres;
603 HRESULT hres;
604 LONG state;
605 TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrHeader), p);
607 if(!p)
608 return E_POINTER;
609 if(!bstrHeader)
610 return E_INVALIDARG;
612 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
613 if(FAILED(hres))
614 return hres;
616 if(state < 2) {
617 *p = NULL;
618 return E_FAIL;
621 cstr = heap_strdupWtoU(bstrHeader);
622 nsACString_InitDepend(&header, cstr);
623 nsACString_Init(&ret, NULL);
625 nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret);
627 nsACString_Finish(&header);
628 heap_free(cstr);
629 return return_nscstr(nsres, &ret, p);
632 static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR bstrValue)
634 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
635 char *header_u, *value_u;
636 nsACString header, value;
637 nsresult nsres;
639 TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
641 header_u = heap_strdupWtoU(bstrHeader);
642 if(bstrHeader && !header_u)
643 return E_OUTOFMEMORY;
645 value_u = heap_strdupWtoU(bstrValue);
646 if(bstrValue && !value_u) {
647 heap_free(header_u);
648 return E_OUTOFMEMORY;
651 nsACString_InitDepend(&header, header_u);
652 nsACString_InitDepend(&value, value_u);
653 nsres = nsIXMLHttpRequest_SetRequestHeader(This->nsxhr, &header, &value);
654 nsACString_Finish(&header);
655 nsACString_Finish(&value);
656 heap_free(header_u);
657 heap_free(value_u);
658 if(NS_FAILED(nsres)) {
659 ERR("SetRequestHeader failed: %08x\n", nsres);
660 return E_FAIL;
663 return S_OK;
666 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl = {
667 HTMLXMLHttpRequest_QueryInterface,
668 HTMLXMLHttpRequest_AddRef,
669 HTMLXMLHttpRequest_Release,
670 HTMLXMLHttpRequest_GetTypeInfoCount,
671 HTMLXMLHttpRequest_GetTypeInfo,
672 HTMLXMLHttpRequest_GetIDsOfNames,
673 HTMLXMLHttpRequest_Invoke,
674 HTMLXMLHttpRequest_get_readyState,
675 HTMLXMLHttpRequest_get_responseBody,
676 HTMLXMLHttpRequest_get_responseText,
677 HTMLXMLHttpRequest_get_responseXML,
678 HTMLXMLHttpRequest_get_status,
679 HTMLXMLHttpRequest_get_statusText,
680 HTMLXMLHttpRequest_put_onreadystatechange,
681 HTMLXMLHttpRequest_get_onreadystatechange,
682 HTMLXMLHttpRequest_abort,
683 HTMLXMLHttpRequest_open,
684 HTMLXMLHttpRequest_send,
685 HTMLXMLHttpRequest_getAllResponseHeaders,
686 HTMLXMLHttpRequest_getResponseHeader,
687 HTMLXMLHttpRequest_setRequestHeader
690 static inline HTMLXMLHttpRequest *impl_from_IProvideClassInfo2(IProvideClassInfo2 *iface)
692 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IProvideClassInfo2_iface);
695 static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, void **ppv)
697 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
698 return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
701 static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo2 *iface)
703 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
704 return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
707 static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo2 *iface)
709 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
710 return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
713 static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI)
715 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
716 TRACE("(%p)->(%p)\n", This, ppTI);
717 return get_class_typeinfo(&CLSID_HTMLXMLHttpRequest, ppTI);
720 static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID)
722 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
723 FIXME("(%p)->(%u %p)\n", This, dwGuidKind, pGUID);
724 return E_NOTIMPL;
727 static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
728 ProvideClassInfo_QueryInterface,
729 ProvideClassInfo_AddRef,
730 ProvideClassInfo_Release,
731 ProvideClassInfo_GetClassInfo,
732 ProvideClassInfo2_GetGUID,
735 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
737 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex);
740 static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, int eid)
742 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
743 nsIDOMEventTarget *nstarget;
744 nsAString type_str;
745 nsresult nsres;
747 static const WCHAR readystatechangeW[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
749 TRACE("(%p)\n", This);
751 assert(eid == EVENTID_READYSTATECHANGE);
753 if(This->event_listener)
754 return;
756 This->event_listener = heap_alloc(sizeof(*This->event_listener));
757 if(!This->event_listener)
758 return;
760 This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
761 This->event_listener->ref = 1;
762 This->event_listener->xhr = This;
764 nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
765 assert(nsres == NS_OK);
767 nsAString_InitDepend(&type_str, readystatechangeW);
768 nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
769 nsAString_Finish(&type_str);
770 nsIDOMEventTarget_Release(nstarget);
771 if(NS_FAILED(nsres))
772 ERR("AddEventListener failed: %08x\n", nsres);
775 static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {
776 NULL,
777 NULL,
778 NULL,
779 NULL,
780 NULL,
781 HTMLXMLHttpRequest_bind_event
784 static const tid_t HTMLXMLHttpRequest_iface_tids[] = {
785 IHTMLXMLHttpRequest_tid,
788 static dispex_static_data_t HTMLXMLHttpRequest_dispex = {
789 &HTMLXMLHttpRequest_dispex_vtbl,
790 DispHTMLXMLHttpRequest_tid,
791 HTMLXMLHttpRequest_iface_tids
795 /* IHTMLXMLHttpRequestFactory */
796 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface)
798 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface);
801 static HRESULT WINAPI HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory *iface, REFIID riid, void **ppv)
803 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
805 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
807 if(IsEqualGUID(&IID_IUnknown, riid)) {
808 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
809 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
810 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
811 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) {
812 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
813 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
814 return *ppv ? S_OK : E_NOINTERFACE;
815 }else {
816 *ppv = NULL;
817 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
818 return E_NOINTERFACE;
821 IUnknown_AddRef((IUnknown*)*ppv);
822 return S_OK;
825 static ULONG WINAPI HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory *iface)
827 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
828 LONG ref = InterlockedIncrement(&This->ref);
830 TRACE("(%p) ref=%d\n", This, ref);
832 return ref;
835 static ULONG WINAPI HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory *iface)
837 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
838 LONG ref = InterlockedDecrement(&This->ref);
840 TRACE("(%p) ref=%d\n", This, ref);
842 if(!ref) {
843 release_dispex(&This->dispex);
844 heap_free(This);
847 return ref;
850 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory *iface, UINT *pctinfo)
852 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
853 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
856 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory *iface, UINT iTInfo,
857 LCID lcid, ITypeInfo **ppTInfo)
859 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
861 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
864 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
865 LCID lcid, DISPID *rgDispId)
867 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
869 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
870 lcid, rgDispId);
873 static HRESULT WINAPI HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
874 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
876 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
878 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
879 pDispParams, pVarResult, pExcepInfo, puArgErr);
882 static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p)
884 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
885 HTMLXMLHttpRequest *ret;
886 nsIXMLHttpRequest *nsxhr;
888 TRACE("(%p)->(%p)\n", This, p);
890 nsxhr = create_nsxhr(This->window->base.outer_window->nswindow);
891 if(!nsxhr)
892 return E_FAIL;
894 ret = heap_alloc_zero(sizeof(*ret));
895 if(!ret) {
896 nsIXMLHttpRequest_Release(nsxhr);
897 return E_OUTOFMEMORY;
899 ret->nsxhr = nsxhr;
901 ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
902 ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl;
903 init_event_target(&ret->event_target);
904 init_dispex(&ret->event_target.dispex, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
905 &HTMLXMLHttpRequest_dispex);
906 ret->ref = 1;
908 *p = &ret->IHTMLXMLHttpRequest_iface;
909 return S_OK;
912 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = {
913 HTMLXMLHttpRequestFactory_QueryInterface,
914 HTMLXMLHttpRequestFactory_AddRef,
915 HTMLXMLHttpRequestFactory_Release,
916 HTMLXMLHttpRequestFactory_GetTypeInfoCount,
917 HTMLXMLHttpRequestFactory_GetTypeInfo,
918 HTMLXMLHttpRequestFactory_GetIDsOfNames,
919 HTMLXMLHttpRequestFactory_Invoke,
920 HTMLXMLHttpRequestFactory_create
923 static inline HTMLXMLHttpRequestFactory *factory_from_DispatchEx(DispatchEx *iface)
925 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, dispex);
928 static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WORD flags, DISPPARAMS *params,
929 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
931 HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(iface);
932 IHTMLXMLHttpRequest *xhr;
933 HRESULT hres;
935 TRACE("\n");
937 if(flags != DISPATCH_CONSTRUCT) {
938 FIXME("flags %x not supported\n", flags);
939 return E_NOTIMPL;
942 hres = IHTMLXMLHttpRequestFactory_create(&This->IHTMLXMLHttpRequestFactory_iface, &xhr);
943 if(FAILED(hres))
944 return hres;
946 V_VT(res) = VT_DISPATCH;
947 V_DISPATCH(res) = (IDispatch*)xhr;
948 return S_OK;
951 static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl = {
952 HTMLXMLHttpRequestFactory_value
955 static const tid_t HTMLXMLHttpRequestFactory_iface_tids[] = {
956 IHTMLXMLHttpRequestFactory_tid,
959 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = {
960 &HTMLXMLHttpRequestFactory_dispex_vtbl,
961 IHTMLXMLHttpRequestFactory_tid,
962 HTMLXMLHttpRequestFactory_iface_tids
965 HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpRequestFactory **ret_ptr)
967 HTMLXMLHttpRequestFactory *ret;
969 ret = heap_alloc(sizeof(*ret));
970 if(!ret)
971 return E_OUTOFMEMORY;
973 ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl;
974 ret->ref = 1;
975 ret->window = window;
977 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLXMLHttpRequestFactory_iface,
978 &HTMLXMLHttpRequestFactory_dispex);
980 *ret_ptr = ret;
981 return S_OK;