shlwapi/tests: Add some tests for memory stream.
[wine.git] / dlls / mshtml / xmlhttprequest.c
blob51645709506add8637210a840bb5eacf7b3d4f33
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 dispatch_event(&This->xhr->event_target, event);
198 IDOMEvent_Release(&event->IDOMEvent_iface);
200 return NS_OK;
203 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
204 XMLHttpReqEventListener_QueryInterface,
205 XMLHttpReqEventListener_AddRef,
206 XMLHttpReqEventListener_Release,
207 XMLHttpReqEventListener_HandleEvent
210 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
212 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
215 static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *iface, REFIID riid, void **ppv)
217 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
219 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
221 if(IsEqualGUID(&IID_IUnknown, riid)) {
222 *ppv = &This->IHTMLXMLHttpRequest_iface;
223 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
224 *ppv = &This->IHTMLXMLHttpRequest_iface;
225 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest, riid)) {
226 *ppv = &This->IHTMLXMLHttpRequest_iface;
227 }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
228 *ppv = &This->IProvideClassInfo2_iface;
229 }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
230 *ppv = &This->IProvideClassInfo2_iface;
231 }else {
232 return EventTarget_QI(&This->event_target, riid, ppv);
235 IUnknown_AddRef((IUnknown*)*ppv);
236 return S_OK;
239 static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface)
241 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
242 LONG ref = InterlockedIncrement(&This->ref);
244 TRACE("(%p) ref=%d\n", This, ref);
246 return ref;
249 static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
251 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
252 LONG ref = InterlockedDecrement(&This->ref);
254 TRACE("(%p) ref=%d\n", This, ref);
256 if(!ref) {
257 if(This->event_listener)
258 detach_xhr_event_listener(This->event_listener);
259 release_event_target(&This->event_target);
260 release_dispex(&This->event_target.dispex);
261 nsIXMLHttpRequest_Release(This->nsxhr);
262 heap_free(This);
265 return ref;
268 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest *iface, UINT *pctinfo)
270 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
271 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
274 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest *iface, UINT iTInfo,
275 LCID lcid, ITypeInfo **ppTInfo)
277 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
279 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
282 static HRESULT WINAPI HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
283 LCID lcid, DISPID *rgDispId)
285 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
287 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
288 lcid, rgDispId);
291 static HRESULT WINAPI HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
292 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
294 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
296 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
297 pDispParams, pVarResult, pExcepInfo, puArgErr);
300 static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p)
302 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
303 UINT16 val;
304 nsresult nsres;
306 TRACE("(%p)->(%p)\n", This, p);
308 if(!p)
309 return E_POINTER;
310 nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &val);
311 if(NS_FAILED(nsres)) {
312 ERR("nsIXMLHttpRequest_GetReadyState failed: %08x\n", nsres);
313 return E_FAIL;
315 *p = val;
316 return S_OK;
319 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *iface, VARIANT *p)
321 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
322 FIXME("(%p)->(%p)\n", This, p);
323 return E_NOTIMPL;
326 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p)
328 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
329 nsAString nsstr;
330 nsresult nsres;
332 TRACE("(%p)->(%p)\n", This, p);
334 if(!p)
335 return E_POINTER;
337 nsAString_Init(&nsstr, NULL);
338 nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr);
339 return return_nsstr(nsres, &nsstr, p);
342 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p)
344 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
345 IXMLDOMDocument *xmldoc = NULL;
346 BSTR str;
347 HRESULT hres;
348 VARIANT_BOOL vbool;
349 IObjectSafety *safety;
351 TRACE("(%p)->(%p)\n", This, p);
353 hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc);
354 if(FAILED(hres)) {
355 ERR("CoCreateInstance failed: %08x\n", hres);
356 return hres;
359 hres = IHTMLXMLHttpRequest_get_responseText(iface, &str);
360 if(FAILED(hres)) {
361 IXMLDOMDocument_Release(xmldoc);
362 ERR("get_responseText failed: %08x\n", hres);
363 return hres;
366 hres = IXMLDOMDocument_loadXML(xmldoc, str, &vbool);
367 SysFreeString(str);
368 if(hres != S_OK || vbool != VARIANT_TRUE)
369 WARN("loadXML failed: %08x, returning an empty xmldoc\n", hres);
371 hres = IXMLDOMDocument_QueryInterface(xmldoc, &IID_IObjectSafety, (void**)&safety);
372 assert(SUCCEEDED(hres));
373 hres = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
374 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER,
375 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER);
376 assert(SUCCEEDED(hres));
377 IObjectSafety_Release(safety);
379 *p = (IDispatch*)xmldoc;
380 return S_OK;
383 static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, LONG *p)
385 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
386 DWORD val;
387 nsresult nsres;
388 TRACE("(%p)->(%p)\n", This, p);
390 if(!p)
391 return E_POINTER;
393 nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val);
394 if(NS_FAILED(nsres)) {
395 ERR("nsIXMLHttpRequest_GetStatus failed: %08x\n", nsres);
396 return E_FAIL;
398 *p = val;
399 if(val == 0)
400 return E_FAIL; /* WinAPI thinks this is an error */
402 return S_OK;
405 static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *iface, BSTR *p)
407 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
408 nsACString nscstr;
409 nsresult nsres;
410 HRESULT hres;
411 LONG state;
413 TRACE("(%p)->(%p)\n", This, p);
415 if(!p)
416 return E_POINTER;
418 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
419 if(FAILED(hres))
420 return hres;
422 if(state < 2) {
423 *p = NULL;
424 return E_FAIL;
427 nsACString_Init(&nscstr, NULL);
428 nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr);
429 return return_nscstr(nsres, &nscstr, p);
432 static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT v)
434 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
436 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
438 return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v);
441 static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p)
443 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
445 TRACE("(%p)->(%p)\n", This, p);
447 return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p);
450 static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface)
452 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
453 nsresult nsres;
455 TRACE("(%p)->()\n", This);
457 nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr);
458 if(NS_FAILED(nsres)) {
459 ERR("nsIXMLHttpRequest_SlowAbort failed: %08x\n", nsres);
460 return E_FAIL;
463 return S_OK;
466 static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
468 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
469 nsACString method, url;
470 nsAString user, password;
471 nsresult nsres;
472 HRESULT hres;
474 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword));
476 if(V_VT(&varAsync) != VT_BOOL) {
477 FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync));
478 return E_FAIL;
481 /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
482 * synchronous requests on the main thread have been deprecated due to the negative
483 * effects to the user experience.
485 if(!V_BOOL(&varAsync)) {
486 FIXME("Synchronous request is not supported yet\n");
487 return E_FAIL;
490 hres = variant_to_nsastr(varUser, &user);
491 if(FAILED(hres))
492 return hres;
493 hres = variant_to_nsastr(varPassword, &password);
494 if(FAILED(hres)) {
495 nsAString_Finish(&user);
496 return hres;
499 hres = bstr_to_nsacstr(bstrMethod, &method);
500 if(FAILED(hres)) {
501 nsAString_Finish(&user);
502 nsAString_Finish(&password);
503 return hres;
505 hres = bstr_to_nsacstr(bstrUrl, &url);
506 if(FAILED(hres)) {
507 nsAString_Finish(&user);
508 nsAString_Finish(&password);
509 nsACString_Finish(&method);
510 return hres;
513 nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, TRUE,
514 &user, &password, 0);
516 nsACString_Finish(&method);
517 nsACString_Finish(&url);
518 nsAString_Finish(&user);
519 nsAString_Finish(&password);
521 if(NS_FAILED(nsres)) {
522 ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres);
523 return E_FAIL;
526 return S_OK;
529 static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
531 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
532 nsIWritableVariant *nsbody = NULL;
533 nsresult nsres = NS_OK;
535 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody));
537 switch(V_VT(&varBody)) {
538 case VT_NULL:
539 case VT_EMPTY:
540 case VT_ERROR:
541 break;
542 case VT_BSTR: {
543 nsAString nsstr;
545 nsbody = create_nsvariant();
546 if(!nsbody)
547 return E_OUTOFMEMORY;
549 nsAString_InitDepend(&nsstr, V_BSTR(&varBody));
550 nsres = nsIWritableVariant_SetAsAString(nsbody, &nsstr);
551 nsAString_Finish(&nsstr);
552 break;
554 default:
555 FIXME("unsupported body type %s\n", debugstr_variant(&varBody));
556 return E_NOTIMPL;
559 if(NS_SUCCEEDED(nsres))
560 nsres = nsIXMLHttpRequest_Send(This->nsxhr, (nsIVariant*)nsbody);
561 if(nsbody)
562 nsIWritableVariant_Release(nsbody);
563 if(NS_FAILED(nsres)) {
564 ERR("nsIXMLHttpRequest_Send failed: %08x\n", nsres);
565 return E_FAIL;
568 return S_OK;
571 static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p)
573 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
574 nsACString nscstr;
575 nsresult nsres;
576 HRESULT hres;
577 LONG state;
579 TRACE("(%p)->(%p)\n", This, p);
581 if(!p)
582 return E_POINTER;
584 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
585 if(FAILED(hres))
586 return hres;
588 if(state < 2) {
589 *p = NULL;
590 return E_FAIL;
593 nsACString_Init(&nscstr, NULL);
594 nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr);
595 return return_nscstr(nsres, &nscstr, p);
598 static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR *p)
600 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
601 nsACString header, ret;
602 char *cstr;
603 nsresult nsres;
604 HRESULT hres;
605 LONG state;
606 TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrHeader), p);
608 if(!p)
609 return E_POINTER;
610 if(!bstrHeader)
611 return E_INVALIDARG;
613 hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
614 if(FAILED(hres))
615 return hres;
617 if(state < 2) {
618 *p = NULL;
619 return E_FAIL;
622 cstr = heap_strdupWtoU(bstrHeader);
623 nsACString_InitDepend(&header, cstr);
624 nsACString_Init(&ret, NULL);
626 nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret);
628 nsACString_Finish(&header);
629 heap_free(cstr);
630 return return_nscstr(nsres, &ret, p);
633 static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR bstrValue)
635 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
636 char *header_u, *value_u;
637 nsACString header, value;
638 nsresult nsres;
640 TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
642 header_u = heap_strdupWtoU(bstrHeader);
643 if(bstrHeader && !header_u)
644 return E_OUTOFMEMORY;
646 value_u = heap_strdupWtoU(bstrValue);
647 if(bstrValue && !value_u) {
648 heap_free(header_u);
649 return E_OUTOFMEMORY;
652 nsACString_InitDepend(&header, header_u);
653 nsACString_InitDepend(&value, value_u);
654 nsres = nsIXMLHttpRequest_SetRequestHeader(This->nsxhr, &header, &value);
655 nsACString_Finish(&header);
656 nsACString_Finish(&value);
657 heap_free(header_u);
658 heap_free(value_u);
659 if(NS_FAILED(nsres)) {
660 ERR("SetRequestHeader failed: %08x\n", nsres);
661 return E_FAIL;
664 return S_OK;
667 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl = {
668 HTMLXMLHttpRequest_QueryInterface,
669 HTMLXMLHttpRequest_AddRef,
670 HTMLXMLHttpRequest_Release,
671 HTMLXMLHttpRequest_GetTypeInfoCount,
672 HTMLXMLHttpRequest_GetTypeInfo,
673 HTMLXMLHttpRequest_GetIDsOfNames,
674 HTMLXMLHttpRequest_Invoke,
675 HTMLXMLHttpRequest_get_readyState,
676 HTMLXMLHttpRequest_get_responseBody,
677 HTMLXMLHttpRequest_get_responseText,
678 HTMLXMLHttpRequest_get_responseXML,
679 HTMLXMLHttpRequest_get_status,
680 HTMLXMLHttpRequest_get_statusText,
681 HTMLXMLHttpRequest_put_onreadystatechange,
682 HTMLXMLHttpRequest_get_onreadystatechange,
683 HTMLXMLHttpRequest_abort,
684 HTMLXMLHttpRequest_open,
685 HTMLXMLHttpRequest_send,
686 HTMLXMLHttpRequest_getAllResponseHeaders,
687 HTMLXMLHttpRequest_getResponseHeader,
688 HTMLXMLHttpRequest_setRequestHeader
691 static inline HTMLXMLHttpRequest *impl_from_IProvideClassInfo2(IProvideClassInfo2 *iface)
693 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IProvideClassInfo2_iface);
696 static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, void **ppv)
698 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
699 return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
702 static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo2 *iface)
704 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
705 return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
708 static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo2 *iface)
710 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
711 return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
714 static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI)
716 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
717 TRACE("(%p)->(%p)\n", This, ppTI);
718 return get_class_typeinfo(&CLSID_HTMLXMLHttpRequest, ppTI);
721 static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID)
723 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
724 FIXME("(%p)->(%u %p)\n", This, dwGuidKind, pGUID);
725 return E_NOTIMPL;
728 static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
729 ProvideClassInfo_QueryInterface,
730 ProvideClassInfo_AddRef,
731 ProvideClassInfo_Release,
732 ProvideClassInfo_GetClassInfo,
733 ProvideClassInfo2_GetGUID,
736 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
738 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex);
741 static nsISupports *HTMLXMLHttpRequest_get_gecko_target(DispatchEx *dispex)
743 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
744 return (nsISupports*)This->nsxhr;
747 static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, eventid_t eid)
749 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
750 nsIDOMEventTarget *nstarget;
751 nsAString type_str;
752 nsresult nsres;
754 static const WCHAR readystatechangeW[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
756 TRACE("(%p)\n", This);
758 if(eid != EVENTID_READYSTATECHANGE || This->event_listener)
759 return;
761 This->event_listener = heap_alloc(sizeof(*This->event_listener));
762 if(!This->event_listener)
763 return;
765 This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
766 This->event_listener->ref = 1;
767 This->event_listener->xhr = This;
769 nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
770 assert(nsres == NS_OK);
772 nsAString_InitDepend(&type_str, readystatechangeW);
773 nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
774 nsAString_Finish(&type_str);
775 nsIDOMEventTarget_Release(nstarget);
776 if(NS_FAILED(nsres))
777 ERR("AddEventListener failed: %08x\n", nsres);
780 static event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = {
781 {NULL},
782 HTMLXMLHttpRequest_get_gecko_target,
783 HTMLXMLHttpRequest_bind_event
786 static const tid_t HTMLXMLHttpRequest_iface_tids[] = {
787 IHTMLXMLHttpRequest_tid,
790 static dispex_static_data_t HTMLXMLHttpRequest_dispex = {
791 &HTMLXMLHttpRequest_event_target_vtbl.dispex_vtbl,
792 DispHTMLXMLHttpRequest_tid,
793 HTMLXMLHttpRequest_iface_tids,
794 EventTarget_init_dispex_info
798 /* IHTMLXMLHttpRequestFactory */
799 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface)
801 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface);
804 static HRESULT WINAPI HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory *iface, REFIID riid, void **ppv)
806 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
808 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
810 if(IsEqualGUID(&IID_IUnknown, riid)) {
811 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
812 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
813 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
814 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) {
815 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
816 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
817 return *ppv ? S_OK : E_NOINTERFACE;
818 }else {
819 *ppv = NULL;
820 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
821 return E_NOINTERFACE;
824 IUnknown_AddRef((IUnknown*)*ppv);
825 return S_OK;
828 static ULONG WINAPI HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory *iface)
830 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
831 LONG ref = InterlockedIncrement(&This->ref);
833 TRACE("(%p) ref=%d\n", This, ref);
835 return ref;
838 static ULONG WINAPI HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory *iface)
840 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
841 LONG ref = InterlockedDecrement(&This->ref);
843 TRACE("(%p) ref=%d\n", This, ref);
845 if(!ref) {
846 release_dispex(&This->dispex);
847 heap_free(This);
850 return ref;
853 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory *iface, UINT *pctinfo)
855 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
856 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
859 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory *iface, UINT iTInfo,
860 LCID lcid, ITypeInfo **ppTInfo)
862 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
864 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
867 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
868 LCID lcid, DISPID *rgDispId)
870 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
872 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
873 lcid, rgDispId);
876 static HRESULT WINAPI HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
877 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
879 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
881 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
882 pDispParams, pVarResult, pExcepInfo, puArgErr);
885 static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p)
887 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
888 HTMLXMLHttpRequest *ret;
889 nsIXMLHttpRequest *nsxhr;
891 TRACE("(%p)->(%p)\n", This, p);
893 nsxhr = create_nsxhr(This->window->base.outer_window->nswindow);
894 if(!nsxhr)
895 return E_FAIL;
897 ret = heap_alloc_zero(sizeof(*ret));
898 if(!ret) {
899 nsIXMLHttpRequest_Release(nsxhr);
900 return E_OUTOFMEMORY;
902 ret->nsxhr = nsxhr;
904 ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
905 ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl;
906 EventTarget_Init(&ret->event_target, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
907 &HTMLXMLHttpRequest_dispex, This->window->doc->document_mode);
908 ret->ref = 1;
910 *p = &ret->IHTMLXMLHttpRequest_iface;
911 return S_OK;
914 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = {
915 HTMLXMLHttpRequestFactory_QueryInterface,
916 HTMLXMLHttpRequestFactory_AddRef,
917 HTMLXMLHttpRequestFactory_Release,
918 HTMLXMLHttpRequestFactory_GetTypeInfoCount,
919 HTMLXMLHttpRequestFactory_GetTypeInfo,
920 HTMLXMLHttpRequestFactory_GetIDsOfNames,
921 HTMLXMLHttpRequestFactory_Invoke,
922 HTMLXMLHttpRequestFactory_create
925 static inline HTMLXMLHttpRequestFactory *factory_from_DispatchEx(DispatchEx *iface)
927 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, dispex);
930 static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WORD flags, DISPPARAMS *params,
931 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
933 HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(iface);
934 IHTMLXMLHttpRequest *xhr;
935 HRESULT hres;
937 TRACE("\n");
939 if(flags != DISPATCH_CONSTRUCT) {
940 FIXME("flags %x not supported\n", flags);
941 return E_NOTIMPL;
944 hres = IHTMLXMLHttpRequestFactory_create(&This->IHTMLXMLHttpRequestFactory_iface, &xhr);
945 if(FAILED(hres))
946 return hres;
948 V_VT(res) = VT_DISPATCH;
949 V_DISPATCH(res) = (IDispatch*)xhr;
950 return S_OK;
953 static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl = {
954 HTMLXMLHttpRequestFactory_value
957 static const tid_t HTMLXMLHttpRequestFactory_iface_tids[] = {
958 IHTMLXMLHttpRequestFactory_tid,
961 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = {
962 &HTMLXMLHttpRequestFactory_dispex_vtbl,
963 IHTMLXMLHttpRequestFactory_tid,
964 HTMLXMLHttpRequestFactory_iface_tids
967 HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpRequestFactory **ret_ptr)
969 HTMLXMLHttpRequestFactory *ret;
971 ret = heap_alloc(sizeof(*ret));
972 if(!ret)
973 return E_OUTOFMEMORY;
975 ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl;
976 ret->ref = 1;
977 ret->window = window;
979 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLXMLHttpRequestFactory_iface,
980 &HTMLXMLHttpRequestFactory_dispex);
982 *ret_ptr = ret;
983 return S_OK;