windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / mshtml / xmlhttprequest.c
blob17f29396b8faef95fbaefbcbde92db47551af965
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>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
32 #include "mshtmdid.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 = strdupWtoU(bstr);
42 if(!cstr)
43 return E_OUTOFMEMORY;
44 nsACString_Init(str, cstr);
45 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: %08lx\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 - 1);
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 static const eventid_t events[] = {
96 EVENTID_READYSTATECHANGE,
97 EVENTID_LOAD,
98 EVENTID_LOADSTART,
99 EVENTID_LOADEND,
100 EVENTID_PROGRESS,
101 EVENTID_ABORT,
102 EVENTID_ERROR,
103 EVENTID_TIMEOUT,
106 typedef enum {
107 response_type_empty,
108 response_type_text,
109 response_type_doc,
110 response_type_arraybuf,
111 response_type_blob,
112 response_type_stream
113 } response_type_t;
115 static const struct {
116 const WCHAR *str;
117 const WCHAR *nsxhr_str;
118 } response_type_desc[] = {
119 [response_type_empty] = { L"", L"" },
120 [response_type_text] = { L"text", L"" },
121 [response_type_doc] = { L"document", L"" }, /* FIXME */
122 [response_type_arraybuf] = { L"arraybuffer", L"arraybuffer" },
123 [response_type_blob] = { L"blob", L"arraybuffer" },
124 [response_type_stream] = { L"ms-stream", L"arraybuffer" } /* FIXME */
127 typedef struct {
128 nsIDOMEventListener nsIDOMEventListener_iface;
129 LONG ref;
130 HTMLXMLHttpRequest *xhr;
131 } XMLHttpReqEventListener;
133 struct HTMLXMLHttpRequest {
134 EventTarget event_target;
135 IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
136 IHTMLXMLHttpRequest2 IHTMLXMLHttpRequest2_iface;
137 IWineXMLHttpRequestPrivate IWineXMLHttpRequestPrivate_iface;
138 IProvideClassInfo2 IProvideClassInfo2_iface;
139 LONG ref;
140 LONG task_magic;
141 LONG ready_state;
142 response_type_t response_type;
143 BOOLEAN synchronous;
144 DWORD magic;
145 DWORD pending_events_magic;
146 HTMLInnerWindow *window;
147 nsIXMLHttpRequest *nsxhr;
148 XMLHttpReqEventListener *event_listener;
149 DOMEvent *pending_progress_event;
152 static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener)
154 nsIDOMEventTarget *event_target;
155 nsresult nsres;
156 nsAString str;
157 unsigned i;
159 nsres = nsIXMLHttpRequest_QueryInterface(event_listener->xhr->nsxhr, &IID_nsIDOMEventTarget, (void**)&event_target);
160 assert(nsres == NS_OK);
162 for(i = 0; i < ARRAY_SIZE(events) ; i++) {
163 nsAString_InitDepend(&str, get_event_name(events[i]));
164 nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE);
165 nsAString_Finish(&str);
166 assert(nsres == NS_OK);
169 nsIDOMEventTarget_Release(event_target);
171 event_listener->xhr = NULL;
172 nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface);
175 static void synthesize_pending_events(HTMLXMLHttpRequest *xhr)
177 DWORD magic = xhr->pending_events_magic;
178 UINT16 ready_state = xhr->ready_state;
179 BOOLEAN send_load, send_loadend;
180 DOMEvent *event;
181 HRESULT hres;
183 if(xhr->magic != magic)
184 return;
186 /* Make sure further events are synthesized with a new task */
187 xhr->pending_events_magic = magic - 1;
189 /* Synthesize the necessary events that led us to this current state */
190 nsIXMLHttpRequest_GetReadyState(xhr->nsxhr, &ready_state);
191 if(ready_state == READYSTATE_UNINITIALIZED)
192 return;
194 /* Synchronous XHRs only send readyState changes before DONE in IE9 and below */
195 if(xhr->synchronous && dispex_compat_mode(&xhr->event_target.dispex) > COMPAT_MODE_IE9) {
196 if(ready_state < READYSTATE_INTERACTIVE) {
197 xhr->ready_state = ready_state;
198 return;
200 xhr->ready_state = max(xhr->ready_state, READYSTATE_INTERACTIVE);
203 IHTMLXMLHttpRequest_AddRef(&xhr->IHTMLXMLHttpRequest_iface);
205 send_loadend = send_load = (xhr->ready_state != ready_state && ready_state == READYSTATE_COMPLETE);
206 for(;;) {
207 if(xhr->pending_progress_event &&
208 xhr->ready_state == (xhr->pending_progress_event->event_id == EVENTID_PROGRESS ? READYSTATE_INTERACTIVE : READYSTATE_COMPLETE))
210 DOMEvent *pending_progress_event = xhr->pending_progress_event;
211 xhr->pending_progress_event = NULL;
213 if(pending_progress_event->event_id != EVENTID_PROGRESS) {
214 send_load = FALSE;
215 send_loadend = TRUE;
218 dispatch_event(&xhr->event_target, pending_progress_event);
219 IDOMEvent_Release(&pending_progress_event->IDOMEvent_iface);
220 if(xhr->magic != magic)
221 goto ret;
224 if(xhr->ready_state >= ready_state)
225 break;
227 xhr->ready_state++;
228 hres = create_document_event(xhr->window->doc, EVENTID_READYSTATECHANGE, &event);
229 if(SUCCEEDED(hres)) {
230 dispatch_event(&xhr->event_target, event);
231 IDOMEvent_Release(&event->IDOMEvent_iface);
232 if(xhr->magic != magic)
233 goto ret;
237 if(send_load) {
238 hres = create_document_event(xhr->window->doc, EVENTID_LOAD, &event);
239 if(SUCCEEDED(hres)) {
240 dispatch_event(&xhr->event_target, event);
241 IDOMEvent_Release(&event->IDOMEvent_iface);
242 if(xhr->magic != magic)
243 goto ret;
247 if(send_loadend) {
248 hres = create_document_event(xhr->window->doc, EVENTID_LOADEND, &event);
249 if(SUCCEEDED(hres)) {
250 dispatch_event(&xhr->event_target, event);
251 IDOMEvent_Release(&event->IDOMEvent_iface);
252 if(xhr->magic != magic)
253 goto ret;
257 ret:
258 IHTMLXMLHttpRequest_Release(&xhr->IHTMLXMLHttpRequest_iface);
261 static nsresult sync_xhr_send(HTMLXMLHttpRequest *xhr, nsIVariant *nsbody)
263 thread_data_t *thread_data = get_thread_data(TRUE);
264 HTMLXMLHttpRequest *prev_blocking_xhr;
265 HTMLInnerWindow *window = xhr->window;
266 nsresult nsres;
268 if(!thread_data)
269 return NS_ERROR_OUT_OF_MEMORY;
270 prev_blocking_xhr = thread_data->blocking_xhr;
272 /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
273 * synchronous requests on the main thread have been deprecated due to the negative
274 * effects to the user experience. However, they still work. The larger issue is that
275 * it is broken because it still dispatches async XHR and some other events, while all
276 * other major browsers don't, including IE, so we have to filter them out during Send.
278 * They will need to be queued and dispatched later, after Send returns, otherwise it
279 * breaks JavaScript single-threaded expectations (JS code will switch from blocking in
280 * Send to executing some event handler, then returning back to Send, messing its state).
282 * Of course we can't just delay dispatching the events, because the state won't match
283 * for each event later on, to what it's supposed to be (most notably, XHR's readyState).
284 * We'll keep snapshots and synthesize them when unblocked for async XHR events.
286 * Note that while queuing an event this way would not work correctly with their default
287 * behavior in Gecko (preventDefault() can't be called because we need to *delay* the
288 * default, rather than prevent it completely), Gecko does suppress events reaching the
289 * document during the sync XHR event loop, so those we do not handle manually. If we
290 * find an event that has defaults on Gecko's side and isn't delayed by Gecko, we need
291 * to figure out a way to handle it...
293 * For details (and bunch of problems to consider) see: https://bugzil.la/697151
295 window->base.outer_window->readystate_locked++;
296 window->blocking_depth++;
297 thread_data->blocking_xhr = xhr;
298 nsres = nsIXMLHttpRequest_Send(xhr->nsxhr, nsbody);
299 thread_data->blocking_xhr = prev_blocking_xhr;
300 window->base.outer_window->readystate_locked--;
302 if(!--window->blocking_depth)
303 unblock_tasks_and_timers(thread_data);
305 /* Process any pending events now since they were part of the blocked send() above */
306 synthesize_pending_events(xhr);
308 return nsres;
311 struct pending_xhr_events_task {
312 event_task_t header;
313 HTMLXMLHttpRequest *xhr;
316 static void pending_xhr_events_proc(event_task_t *_task)
318 struct pending_xhr_events_task *task = (struct pending_xhr_events_task*)_task;
319 synthesize_pending_events(task->xhr);
322 static void pending_xhr_events_destr(event_task_t *_task)
327 static inline XMLHttpReqEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface)
329 return CONTAINING_RECORD(iface, XMLHttpReqEventListener, nsIDOMEventListener_iface);
332 static nsresult NSAPI XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener *iface,
333 nsIIDRef riid, void **result)
335 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
337 if(IsEqualGUID(&IID_nsISupports, riid)) {
338 TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
339 *result = &This->nsIDOMEventListener_iface;
340 }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
341 TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
342 *result = &This->nsIDOMEventListener_iface;
343 }else {
344 *result = NULL;
345 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
346 return NS_NOINTERFACE;
349 nsIDOMEventListener_AddRef(&This->nsIDOMEventListener_iface);
350 return NS_OK;
353 static nsrefcnt NSAPI XMLHttpReqEventListener_AddRef(nsIDOMEventListener *iface)
355 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
356 LONG ref = InterlockedIncrement(&This->ref);
358 TRACE("(%p) ref=%ld\n", This, ref);
360 return ref;
363 static nsrefcnt NSAPI XMLHttpReqEventListener_Release(nsIDOMEventListener *iface)
365 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
366 LONG ref = InterlockedDecrement(&This->ref);
368 TRACE("(%p) ref=%ld\n", This, ref);
370 if(!ref) {
371 assert(!This->xhr);
372 free(This);
375 return ref;
378 static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *nsevent)
380 XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
381 HTMLXMLHttpRequest *blocking_xhr = NULL;
382 thread_data_t *thread_data;
383 compat_mode_t compat_mode;
384 LONG ready_state;
385 DOMEvent *event;
386 HRESULT hres;
387 UINT16 val;
389 TRACE("(%p)\n", This);
391 if(!This->xhr)
392 return NS_OK;
394 ready_state = This->xhr->ready_state;
395 if(NS_SUCCEEDED(nsIXMLHttpRequest_GetReadyState(This->xhr->nsxhr, &val)))
396 ready_state = val;
398 if((thread_data = get_thread_data(FALSE)))
399 blocking_xhr = thread_data->blocking_xhr;
401 compat_mode = dispex_compat_mode(&This->xhr->event_target.dispex);
402 hres = create_event_from_nsevent(nsevent, compat_mode, &event);
403 if(FAILED(hres)) {
404 if(!blocking_xhr || This->xhr == blocking_xhr)
405 This->xhr->ready_state = ready_state;
406 return NS_ERROR_OUT_OF_MEMORY;
409 if(blocking_xhr) {
410 BOOL has_pending_events = (This->xhr->magic == This->xhr->pending_events_magic);
412 if(has_pending_events || This->xhr != blocking_xhr) {
413 switch(event->event_id) {
414 case EVENTID_PROGRESS:
415 case EVENTID_ABORT:
416 case EVENTID_ERROR:
417 case EVENTID_TIMEOUT:
418 if(This->xhr->pending_progress_event)
419 IDOMEvent_Release(&This->xhr->pending_progress_event->IDOMEvent_iface);
420 This->xhr->pending_progress_event = event;
421 break;
422 default:
423 IDOMEvent_Release(&event->IDOMEvent_iface);
424 break;
427 if(!has_pending_events) {
428 if(!This->xhr->synchronous) {
429 struct pending_xhr_events_task *task;
431 remove_target_tasks(This->xhr->task_magic);
433 if(!(task = malloc(sizeof(*task))))
434 return NS_ERROR_OUT_OF_MEMORY;
436 task->header.target_magic = This->xhr->task_magic;
437 task->header.thread_blocked = TRUE;
438 task->header.proc = pending_xhr_events_proc;
439 task->header.destr = pending_xhr_events_destr;
440 task->header.window = This->xhr->window;
441 task->xhr = This->xhr;
442 IHTMLWindow2_AddRef(&This->xhr->window->base.IHTMLWindow2_iface);
444 list_add_after(thread_data->pending_xhr_events_tail, &task->header.entry);
445 thread_data->pending_xhr_events_tail = &task->header.entry;
447 This->xhr->pending_events_magic = This->xhr->magic;
448 return NS_OK;
451 /* Synthesize pending events that a nested sync XHR might have blocked us on */
452 if(This->xhr == blocking_xhr)
453 synthesize_pending_events(This->xhr);
454 return NS_OK;
457 /* Workaround weird Gecko behavior with nested sync XHRs, where it sends readyState changes
458 for OPENED (or possibly other states than DONE), unlike IE10+ and non-nested sync XHRs... */
459 if(ready_state < READYSTATE_COMPLETE && event->event_id == EVENTID_READYSTATECHANGE) {
460 IDOMEvent_Release(&event->IDOMEvent_iface);
461 This->xhr->ready_state = ready_state;
462 return NS_OK;
465 /* IE10+ only send readystatechange event when it is DONE for sync XHRs, but older modes
466 send all the others here, including OPENED state change (even if it was opened earlier). */
467 if(compat_mode < COMPAT_MODE_IE10 && This->xhr->ready_state < READYSTATE_COMPLETE && (
468 event->event_id == EVENTID_READYSTATECHANGE || event->event_id == EVENTID_PROGRESS || event->event_id == EVENTID_LOADSTART)) {
469 DOMEvent *readystatechange_event;
470 DWORD magic = This->xhr->magic;
471 unsigned i;
473 for(i = READYSTATE_LOADING; i < READYSTATE_COMPLETE; i++) {
474 hres = create_document_event(This->xhr->window->doc, EVENTID_READYSTATECHANGE, &readystatechange_event);
475 if(FAILED(hres))
476 break;
478 This->xhr->ready_state = i;
479 dispatch_event(&This->xhr->event_target, readystatechange_event);
480 IDOMEvent_Release(&readystatechange_event->IDOMEvent_iface);
482 if(This->xhr->magic != magic) {
483 IDOMEvent_Release(&event->IDOMEvent_iface);
484 return NS_OK;
490 This->xhr->ready_state = ready_state;
491 dispatch_event(&This->xhr->event_target, event);
492 IDOMEvent_Release(&event->IDOMEvent_iface);
493 return NS_OK;
496 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
497 XMLHttpReqEventListener_QueryInterface,
498 XMLHttpReqEventListener_AddRef,
499 XMLHttpReqEventListener_Release,
500 XMLHttpReqEventListener_HandleEvent
503 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
505 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
508 static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *iface, REFIID riid, void **ppv)
510 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
512 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
514 if(IsEqualGUID(&IID_IUnknown, riid)) {
515 *ppv = &This->IHTMLXMLHttpRequest_iface;
516 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
517 *ppv = &This->IHTMLXMLHttpRequest_iface;
518 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest, riid)) {
519 *ppv = &This->IHTMLXMLHttpRequest_iface;
520 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest2, riid)) {
521 *ppv = &This->IHTMLXMLHttpRequest2_iface;
522 }else if(IsEqualGUID(&IID_IWineXMLHttpRequestPrivate, riid)) {
523 *ppv = &This->IWineXMLHttpRequestPrivate_iface;
524 }else if(IsEqualGUID(&IID_IProvideClassInfo, riid)) {
525 *ppv = &This->IProvideClassInfo2_iface;
526 }else if(IsEqualGUID(&IID_IProvideClassInfo2, riid)) {
527 *ppv = &This->IProvideClassInfo2_iface;
528 }else {
529 return EventTarget_QI(&This->event_target, riid, ppv);
532 IUnknown_AddRef((IUnknown*)*ppv);
533 return S_OK;
536 static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface)
538 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
539 LONG ref = InterlockedIncrement(&This->ref);
541 TRACE("(%p) ref=%ld\n", This, ref);
543 return ref;
546 static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
548 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
549 LONG ref = InterlockedDecrement(&This->ref);
551 TRACE("(%p) ref=%ld\n", This, ref);
553 if(!ref) {
554 remove_target_tasks(This->task_magic);
555 detach_xhr_event_listener(This->event_listener);
556 if(This->pending_progress_event)
557 IDOMEvent_Release(&This->pending_progress_event->IDOMEvent_iface);
558 IHTMLWindow2_Release(&This->window->base.IHTMLWindow2_iface);
559 release_event_target(&This->event_target);
560 release_dispex(&This->event_target.dispex);
561 nsIXMLHttpRequest_Release(This->nsxhr);
562 free(This);
565 return ref;
568 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest *iface, UINT *pctinfo)
570 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
571 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
574 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest *iface, UINT iTInfo,
575 LCID lcid, ITypeInfo **ppTInfo)
577 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
579 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
582 static HRESULT WINAPI HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
583 LCID lcid, DISPID *rgDispId)
585 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
587 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
588 lcid, rgDispId);
591 static HRESULT WINAPI HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
592 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
594 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
596 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
597 pDispParams, pVarResult, pExcepInfo, puArgErr);
600 static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p)
602 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
604 TRACE("(%p)->(%p)\n", This, p);
606 if(!p)
607 return E_POINTER;
608 *p = This->ready_state;
609 return S_OK;
612 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *iface, VARIANT *p)
614 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
615 FIXME("(%p)->(%p)\n", This, p);
616 return E_NOTIMPL;
619 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p)
621 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
622 nsAString nsstr;
623 nsresult nsres;
625 TRACE("(%p)->(%p)\n", This, p);
627 if(!p)
628 return E_POINTER;
630 if(This->ready_state < READYSTATE_INTERACTIVE) {
631 *p = NULL;
632 return S_OK;
635 nsAString_Init(&nsstr, NULL);
636 nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr);
637 return return_nsstr(nsres, &nsstr, p);
640 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p)
642 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
643 IXMLDOMDocument *xmldoc = NULL;
644 BSTR str;
645 HRESULT hres;
646 VARIANT_BOOL vbool;
647 IObjectSafety *safety;
649 TRACE("(%p)->(%p)\n", This, p);
651 if(This->ready_state < READYSTATE_COMPLETE) {
652 *p = NULL;
653 return S_OK;
656 if(dispex_compat_mode(&This->event_target.dispex) >= COMPAT_MODE_IE10) {
657 nsIDOMDocument *nsdoc;
658 nsresult nsres;
660 nsres = nsIXMLHttpRequest_GetResponseXML(This->nsxhr, &nsdoc);
661 if(NS_FAILED(nsres))
662 return map_nsresult(nsres);
663 if(!nsdoc) {
664 *p = NULL;
665 return S_OK;
667 nsIDOMDocument_Release(nsdoc);
670 hres = CoCreateInstance(&CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&xmldoc);
671 if(FAILED(hres)) {
672 ERR("CoCreateInstance failed: %08lx\n", hres);
673 return hres;
676 hres = IHTMLXMLHttpRequest_get_responseText(iface, &str);
677 if(FAILED(hres)) {
678 IXMLDOMDocument_Release(xmldoc);
679 ERR("get_responseText failed: %08lx\n", hres);
680 return hres;
683 hres = IXMLDOMDocument_loadXML(xmldoc, str, &vbool);
684 SysFreeString(str);
685 if(hres != S_OK || vbool != VARIANT_TRUE)
686 WARN("loadXML failed: %08lx, returning an empty xmldoc\n", hres);
688 hres = IXMLDOMDocument_QueryInterface(xmldoc, &IID_IObjectSafety, (void**)&safety);
689 assert(SUCCEEDED(hres));
690 hres = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
691 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER,
692 INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER);
693 assert(SUCCEEDED(hres));
694 IObjectSafety_Release(safety);
696 *p = (IDispatch*)xmldoc;
697 return S_OK;
700 static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, LONG *p)
702 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
703 UINT32 val;
704 nsresult nsres;
705 TRACE("(%p)->(%p)\n", This, p);
707 if(!p)
708 return E_POINTER;
710 if(This->ready_state < READYSTATE_LOADED) {
711 *p = 0;
712 return E_FAIL;
715 nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val);
716 if(NS_FAILED(nsres)) {
717 ERR("nsIXMLHttpRequest_GetStatus failed: %08lx\n", nsres);
718 return E_FAIL;
720 *p = val;
721 if(val == 0)
722 return E_FAIL; /* WinAPI thinks this is an error */
724 return S_OK;
727 static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *iface, BSTR *p)
729 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
730 nsACString nscstr;
731 nsresult nsres;
733 TRACE("(%p)->(%p)\n", This, p);
735 if(!p)
736 return E_POINTER;
738 if(This->ready_state < READYSTATE_LOADED) {
739 *p = NULL;
740 return E_FAIL;
743 nsACString_Init(&nscstr, NULL);
744 nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr);
745 return return_nscstr(nsres, &nscstr, p);
748 static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT v)
750 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
752 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
754 return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v);
757 static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p)
759 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
761 TRACE("(%p)->(%p)\n", This, p);
763 return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p);
766 static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface)
768 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
769 DWORD prev_magic = This->magic;
770 UINT16 ready_state;
771 nsresult nsres;
773 TRACE("(%p)->()\n", This);
775 This->magic++;
776 nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr);
777 if(NS_FAILED(nsres)) {
778 ERR("nsIXMLHttpRequest_SlowAbort failed: %08lx\n", nsres);
779 This->magic = prev_magic;
780 return E_FAIL;
783 /* Gecko changed to READYSTATE_UNINITIALIZED if it did abort */
784 nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &ready_state);
785 if(NS_SUCCEEDED(nsres))
786 This->ready_state = ready_state;
787 return S_OK;
790 static HRESULT HTMLXMLHttpRequest_open_hook(DispatchEx *dispex, WORD flags,
791 DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
793 /* If only two arguments were given, implicitly set async to false */
794 if((flags & DISPATCH_METHOD) && dp->cArgs == 2 && !dp->cNamedArgs) {
795 VARIANT args[5];
796 DISPPARAMS new_dp = {args, NULL, ARRAY_SIZE(args), 0};
797 V_VT(args) = VT_EMPTY;
798 V_VT(args+1) = VT_EMPTY;
799 V_VT(args+2) = VT_BOOL;
800 V_BOOL(args+2) = VARIANT_TRUE;
801 args[3] = dp->rgvarg[0];
802 args[4] = dp->rgvarg[1];
804 TRACE("implicit async\n");
806 return dispex_call_builtin(dispex, DISPID_IHTMLXMLHTTPREQUEST_OPEN, &new_dp, res, ei, caller);
809 return S_FALSE; /* fallback to default */
812 static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
814 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
815 BOOLEAN prev_synchronous;
816 nsAString user, password;
817 nsACString method, url;
818 unsigned opt_argc = 1;
819 DWORD prev_magic;
820 nsresult nsres;
821 HRESULT hres;
823 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword));
825 if(V_VT(&varAsync) != VT_BOOL) {
826 LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
827 hres = VariantChangeTypeEx(&varAsync, &varAsync, lcid, 0, VT_BOOL);
828 if(FAILED(hres)) {
829 WARN("Failed to convert varAsync to BOOL: %#lx\n", hres);
830 return hres;
834 hres = variant_to_nsastr(varUser, &user);
835 if(FAILED(hres))
836 return hres;
837 hres = variant_to_nsastr(varPassword, &password);
838 if(FAILED(hres)) {
839 nsAString_Finish(&user);
840 return hres;
843 hres = bstr_to_nsacstr(bstrMethod, &method);
844 if(FAILED(hres)) {
845 nsAString_Finish(&user);
846 nsAString_Finish(&password);
847 return hres;
849 hres = bstr_to_nsacstr(bstrUrl, &url);
850 if(FAILED(hres)) {
851 nsAString_Finish(&user);
852 nsAString_Finish(&password);
853 nsACString_Finish(&method);
854 return hres;
857 /* Set this here, Gecko dispatches nested sync XHR readyState changes for OPENED (see HandleEvent) */
858 prev_magic = This->magic;
859 prev_synchronous = This->synchronous;
860 This->synchronous = !V_BOOL(&varAsync);
861 This->magic++;
863 if(V_VT(&varPassword) != VT_EMPTY && V_VT(&varPassword) != VT_ERROR)
864 opt_argc += 2;
865 else if(V_VT(&varUser) != VT_EMPTY && V_VT(&varUser) != VT_ERROR)
866 opt_argc += 1;
867 nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, !!V_BOOL(&varAsync), &user, &password, opt_argc);
869 nsACString_Finish(&method);
870 nsACString_Finish(&url);
871 nsAString_Finish(&user);
872 nsAString_Finish(&password);
874 if(NS_FAILED(nsres)) {
875 ERR("nsIXMLHttpRequest_Open failed: %08lx\n", nsres);
876 This->magic = prev_magic;
877 This->synchronous = prev_synchronous;
878 return E_FAIL;
881 return S_OK;
884 static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
886 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
887 nsIWritableVariant *nsbody = NULL;
888 nsresult nsres = NS_OK;
890 TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody));
892 switch(V_VT(&varBody)) {
893 case VT_NULL:
894 case VT_EMPTY:
895 case VT_ERROR:
896 break;
897 case VT_BSTR: {
898 nsAString nsstr;
900 nsbody = create_nsvariant();
901 if(!nsbody)
902 return E_OUTOFMEMORY;
904 nsAString_InitDepend(&nsstr, V_BSTR(&varBody));
905 nsres = nsIWritableVariant_SetAsAString(nsbody, &nsstr);
906 nsAString_Finish(&nsstr);
907 break;
909 default:
910 FIXME("unsupported body type %s\n", debugstr_variant(&varBody));
911 return E_NOTIMPL;
914 if(NS_SUCCEEDED(nsres)) {
915 if(This->synchronous)
916 nsres = sync_xhr_send(This, (nsIVariant*)nsbody);
917 else
918 nsres = nsIXMLHttpRequest_Send(This->nsxhr, (nsIVariant*)nsbody);
921 if(nsbody)
922 nsIWritableVariant_Release(nsbody);
923 if(NS_FAILED(nsres)) {
924 ERR("nsIXMLHttpRequest_Send failed: %08lx\n", nsres);
925 return map_nsresult(nsres);
928 return S_OK;
931 static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p)
933 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
934 nsACString nscstr;
935 nsresult nsres;
937 TRACE("(%p)->(%p)\n", This, p);
939 if(!p)
940 return E_POINTER;
942 if(This->ready_state < READYSTATE_LOADED) {
943 *p = NULL;
944 return E_FAIL;
947 nsACString_Init(&nscstr, NULL);
948 nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr);
949 return return_nscstr(nsres, &nscstr, p);
952 static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR *p)
954 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
955 nsACString header, ret;
956 char *cstr;
957 nsresult nsres;
958 TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrHeader), p);
960 if(!p)
961 return E_POINTER;
962 if(!bstrHeader)
963 return E_INVALIDARG;
965 if(This->ready_state < READYSTATE_LOADED) {
966 *p = NULL;
967 return E_FAIL;
970 cstr = strdupWtoU(bstrHeader);
971 nsACString_InitDepend(&header, cstr);
972 nsACString_Init(&ret, NULL);
974 nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret);
976 nsACString_Finish(&header);
977 free(cstr);
978 return return_nscstr(nsres, &ret, p);
981 static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR bstrValue)
983 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
984 char *header_u, *value_u;
985 nsACString header, value;
986 nsresult nsres;
988 TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
990 header_u = strdupWtoU(bstrHeader);
991 if(bstrHeader && !header_u)
992 return E_OUTOFMEMORY;
994 value_u = strdupWtoU(bstrValue);
995 if(bstrValue && !value_u) {
996 free(header_u);
997 return E_OUTOFMEMORY;
1000 nsACString_InitDepend(&header, header_u);
1001 nsACString_InitDepend(&value, value_u);
1002 nsres = nsIXMLHttpRequest_SetRequestHeader(This->nsxhr, &header, &value);
1003 nsACString_Finish(&header);
1004 nsACString_Finish(&value);
1005 free(header_u);
1006 free(value_u);
1007 if(NS_FAILED(nsres)) {
1008 ERR("SetRequestHeader failed: %08lx\n", nsres);
1009 return E_FAIL;
1012 return S_OK;
1015 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl = {
1016 HTMLXMLHttpRequest_QueryInterface,
1017 HTMLXMLHttpRequest_AddRef,
1018 HTMLXMLHttpRequest_Release,
1019 HTMLXMLHttpRequest_GetTypeInfoCount,
1020 HTMLXMLHttpRequest_GetTypeInfo,
1021 HTMLXMLHttpRequest_GetIDsOfNames,
1022 HTMLXMLHttpRequest_Invoke,
1023 HTMLXMLHttpRequest_get_readyState,
1024 HTMLXMLHttpRequest_get_responseBody,
1025 HTMLXMLHttpRequest_get_responseText,
1026 HTMLXMLHttpRequest_get_responseXML,
1027 HTMLXMLHttpRequest_get_status,
1028 HTMLXMLHttpRequest_get_statusText,
1029 HTMLXMLHttpRequest_put_onreadystatechange,
1030 HTMLXMLHttpRequest_get_onreadystatechange,
1031 HTMLXMLHttpRequest_abort,
1032 HTMLXMLHttpRequest_open,
1033 HTMLXMLHttpRequest_send,
1034 HTMLXMLHttpRequest_getAllResponseHeaders,
1035 HTMLXMLHttpRequest_getResponseHeader,
1036 HTMLXMLHttpRequest_setRequestHeader
1039 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest2(IHTMLXMLHttpRequest2 *iface)
1041 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest2_iface);
1044 static HRESULT WINAPI HTMLXMLHttpRequest2_QueryInterface(IHTMLXMLHttpRequest2 *iface, REFIID riid, void **ppv)
1046 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1047 return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
1050 static ULONG WINAPI HTMLXMLHttpRequest2_AddRef(IHTMLXMLHttpRequest2 *iface)
1052 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1053 return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
1056 static ULONG WINAPI HTMLXMLHttpRequest2_Release(IHTMLXMLHttpRequest2 *iface)
1058 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1059 return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
1062 static HRESULT WINAPI HTMLXMLHttpRequest2_GetTypeInfoCount(IHTMLXMLHttpRequest2 *iface, UINT *pctinfo)
1064 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1065 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1068 static HRESULT WINAPI HTMLXMLHttpRequest2_GetTypeInfo(IHTMLXMLHttpRequest2 *iface, UINT iTInfo,
1069 LCID lcid, ITypeInfo **ppTInfo)
1071 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1072 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1075 static HRESULT WINAPI HTMLXMLHttpRequest2_GetIDsOfNames(IHTMLXMLHttpRequest2 *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1076 LCID lcid, DISPID *rgDispId)
1078 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1079 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1080 lcid, rgDispId);
1083 static HRESULT WINAPI HTMLXMLHttpRequest2_Invoke(IHTMLXMLHttpRequest2 *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1084 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1086 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1087 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
1088 pDispParams, pVarResult, pExcepInfo, puArgErr);
1091 static HRESULT WINAPI HTMLXMLHttpRequest2_put_timeout(IHTMLXMLHttpRequest2 *iface, LONG v)
1093 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1095 TRACE("(%p)->(%ld)\n", This, v);
1097 if(v < 0)
1098 return E_INVALIDARG;
1099 return map_nsresult(nsIXMLHttpRequest_SetTimeout(This->nsxhr, v));
1102 static HRESULT WINAPI HTMLXMLHttpRequest2_get_timeout(IHTMLXMLHttpRequest2 *iface, LONG *p)
1104 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1105 nsresult nsres;
1106 UINT32 timeout;
1108 TRACE("(%p)->(%p)\n", This, p);
1110 if(!p)
1111 return E_POINTER;
1113 nsres = nsIXMLHttpRequest_GetTimeout(This->nsxhr, &timeout);
1114 *p = timeout;
1115 return map_nsresult(nsres);
1118 static HRESULT WINAPI HTMLXMLHttpRequest2_put_ontimeout(IHTMLXMLHttpRequest2 *iface, VARIANT v)
1120 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1122 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1124 return set_event_handler(&This->event_target, EVENTID_TIMEOUT, &v);
1127 static HRESULT WINAPI HTMLXMLHttpRequest2_get_ontimeout(IHTMLXMLHttpRequest2 *iface, VARIANT *p)
1129 HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest2(iface);
1131 TRACE("(%p)->(%p)\n", This, p);
1133 return get_event_handler(&This->event_target, EVENTID_TIMEOUT, p);
1136 static const IHTMLXMLHttpRequest2Vtbl HTMLXMLHttpRequest2Vtbl = {
1137 HTMLXMLHttpRequest2_QueryInterface,
1138 HTMLXMLHttpRequest2_AddRef,
1139 HTMLXMLHttpRequest2_Release,
1140 HTMLXMLHttpRequest2_GetTypeInfoCount,
1141 HTMLXMLHttpRequest2_GetTypeInfo,
1142 HTMLXMLHttpRequest2_GetIDsOfNames,
1143 HTMLXMLHttpRequest2_Invoke,
1144 HTMLXMLHttpRequest2_put_timeout,
1145 HTMLXMLHttpRequest2_get_timeout,
1146 HTMLXMLHttpRequest2_put_ontimeout,
1147 HTMLXMLHttpRequest2_get_ontimeout
1150 static inline HTMLXMLHttpRequest *impl_from_IWineXMLHttpRequestPrivate(IWineXMLHttpRequestPrivate *iface)
1152 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IWineXMLHttpRequestPrivate_iface);
1155 static HRESULT WINAPI HTMLXMLHttpRequest_private_QueryInterface(IWineXMLHttpRequestPrivate *iface, REFIID riid, void **ppv)
1157 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1158 return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
1161 static ULONG WINAPI HTMLXMLHttpRequest_private_AddRef(IWineXMLHttpRequestPrivate *iface)
1163 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1164 return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
1167 static ULONG WINAPI HTMLXMLHttpRequest_private_Release(IWineXMLHttpRequestPrivate *iface)
1169 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1170 return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
1173 static HRESULT WINAPI HTMLXMLHttpRequest_private_GetTypeInfoCount(IWineXMLHttpRequestPrivate *iface, UINT *pctinfo)
1175 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1176 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1179 static HRESULT WINAPI HTMLXMLHttpRequest_private_GetTypeInfo(IWineXMLHttpRequestPrivate *iface, UINT iTInfo,
1180 LCID lcid, ITypeInfo **ppTInfo)
1182 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1183 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1186 static HRESULT WINAPI HTMLXMLHttpRequest_private_GetIDsOfNames(IWineXMLHttpRequestPrivate *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1187 LCID lcid, DISPID *rgDispId)
1189 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1190 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1191 lcid, rgDispId);
1194 static HRESULT WINAPI HTMLXMLHttpRequest_private_Invoke(IWineXMLHttpRequestPrivate *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1195 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1197 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1198 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
1199 pDispParams, pVarResult, pExcepInfo, puArgErr);
1202 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_response(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
1204 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1205 HRESULT hres = S_OK;
1207 TRACE("(%p)->(%p)\n", This, p);
1209 switch(This->response_type) {
1210 case response_type_empty:
1211 case response_type_text:
1212 hres = IHTMLXMLHttpRequest_get_responseText(&This->IHTMLXMLHttpRequest_iface, &V_BSTR(p));
1213 if(SUCCEEDED(hres))
1214 V_VT(p) = VT_BSTR;
1215 break;
1217 case response_type_doc:
1218 FIXME("response_type_doc\n");
1219 return E_NOTIMPL;
1221 case response_type_arraybuf:
1222 case response_type_blob:
1223 if(This->ready_state < READYSTATE_COMPLETE) {
1224 V_VT(p) = VT_EMPTY;
1225 break;
1227 if(This->response_type == response_type_arraybuf) {
1228 FIXME("response_type_arraybuf\n");
1229 return E_NOTIMPL;
1231 FIXME("response_type_blob\n");
1232 return E_NOTIMPL;
1234 case response_type_stream:
1235 FIXME("response_type_stream\n");
1236 return E_NOTIMPL;
1238 default:
1239 assert(0);
1242 return hres;
1245 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_responseType(IWineXMLHttpRequestPrivate *iface, BSTR v)
1247 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1248 nsAString nsstr;
1249 nsresult nsres;
1250 unsigned i;
1252 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
1254 if(This->ready_state < READYSTATE_LOADING || This->ready_state > READYSTATE_INTERACTIVE) {
1255 /* FIXME: Return InvalidStateError */
1256 return E_FAIL;
1259 for(i = 0; i < ARRAY_SIZE(response_type_desc); i++)
1260 if(!wcscmp(v, response_type_desc[i].str))
1261 break;
1262 if(i >= ARRAY_SIZE(response_type_desc))
1263 return S_OK;
1265 nsAString_InitDepend(&nsstr, response_type_desc[i].nsxhr_str);
1266 nsres = nsIXMLHttpRequest_SetResponseType(This->nsxhr, &nsstr);
1267 nsAString_Finish(&nsstr);
1268 if(NS_FAILED(nsres))
1269 return map_nsresult(nsres);
1271 This->response_type = i;
1272 return S_OK;
1275 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_responseType(IWineXMLHttpRequestPrivate *iface, BSTR *p)
1277 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1279 TRACE("(%p)->(%p)\n", This, p);
1281 *p = SysAllocString(response_type_desc[This->response_type].str);
1282 return *p ? S_OK : E_OUTOFMEMORY;
1285 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_upload(IWineXMLHttpRequestPrivate *iface, IDispatch **p)
1287 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1289 FIXME("(%p)->(%p)\n", This, p);
1291 return E_NOTIMPL;
1294 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_withCredentials(IWineXMLHttpRequestPrivate *iface, VARIANT_BOOL v)
1296 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1298 TRACE("(%p)->(%x)\n", This, v);
1300 return map_nsresult(nsIXMLHttpRequest_SetWithCredentials(This->nsxhr, !!v));
1303 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_withCredentials(IWineXMLHttpRequestPrivate *iface, VARIANT_BOOL *p)
1305 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1306 nsresult nsres;
1307 cpp_bool b;
1309 TRACE("(%p)->(%p)\n", This, p);
1311 nsres = nsIXMLHttpRequest_GetWithCredentials(This->nsxhr, &b);
1312 if(NS_FAILED(nsres))
1313 return map_nsresult(nsres);
1314 *p = b ? VARIANT_TRUE : VARIANT_FALSE;
1315 return S_OK;
1318 static HRESULT WINAPI HTMLXMLHttpRequest_private_overrideMimeType(IWineXMLHttpRequestPrivate *iface, BSTR mimeType)
1320 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1321 static const WCHAR generic_type[] = L"application/octet-stream";
1322 const WCHAR *type = NULL;
1323 WCHAR *lowercase = NULL;
1324 nsAString nsstr;
1325 nsresult nsres;
1327 TRACE("(%p)->(%s)\n", This, debugstr_w(mimeType));
1329 if(mimeType) {
1330 if(mimeType[0]) {
1331 if(!(lowercase = wcsdup(mimeType)))
1332 return E_OUTOFMEMORY;
1333 _wcslwr(lowercase);
1334 type = lowercase;
1335 }else
1336 type = generic_type;
1339 nsAString_InitDepend(&nsstr, type);
1340 nsres = nsIXMLHttpRequest_SlowOverrideMimeType(This->nsxhr, &nsstr);
1341 nsAString_Finish(&nsstr);
1342 free(lowercase);
1343 return map_nsresult(nsres);
1346 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onerror(IWineXMLHttpRequestPrivate *iface, VARIANT v)
1348 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1350 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1352 return set_event_handler(&This->event_target, EVENTID_ERROR, &v);
1355 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onerror(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
1357 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1359 TRACE("(%p)->(%p)\n", This, p);
1361 return get_event_handler(&This->event_target, EVENTID_ERROR, p);
1364 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onabort(IWineXMLHttpRequestPrivate *iface, VARIANT v)
1366 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1368 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1370 return set_event_handler(&This->event_target, EVENTID_ABORT, &v);
1373 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onabort(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
1375 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1377 TRACE("(%p)->(%p)\n", This, p);
1379 return get_event_handler(&This->event_target, EVENTID_ABORT, p);
1382 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onprogress(IWineXMLHttpRequestPrivate *iface, VARIANT v)
1384 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1386 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1388 return set_event_handler(&This->event_target, EVENTID_PROGRESS, &v);
1391 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onprogress(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
1393 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1395 TRACE("(%p)->(%p)\n", This, p);
1397 return get_event_handler(&This->event_target, EVENTID_PROGRESS, p);
1400 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadstart(IWineXMLHttpRequestPrivate *iface, VARIANT v)
1402 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1404 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1406 return set_event_handler(&This->event_target, EVENTID_LOADSTART, &v);
1409 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadstart(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
1411 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1413 TRACE("(%p)->(%p)\n", This, p);
1415 return get_event_handler(&This->event_target, EVENTID_LOADSTART, p);
1418 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onloadend(IWineXMLHttpRequestPrivate *iface, VARIANT v)
1420 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1422 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1424 return set_event_handler(&This->event_target, EVENTID_LOADEND, &v);
1427 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onloadend(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
1429 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1431 TRACE("(%p)->(%p)\n", This, p);
1433 return get_event_handler(&This->event_target, EVENTID_LOADEND, p);
1436 static HRESULT WINAPI HTMLXMLHttpRequest_private_put_onload(IWineXMLHttpRequestPrivate *iface, VARIANT v)
1438 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1440 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1442 return set_event_handler(&This->event_target, EVENTID_LOAD, &v);
1445 static HRESULT WINAPI HTMLXMLHttpRequest_private_get_onload(IWineXMLHttpRequestPrivate *iface, VARIANT *p)
1447 HTMLXMLHttpRequest *This = impl_from_IWineXMLHttpRequestPrivate(iface);
1449 TRACE("(%p)->(%p)\n", This, p);
1451 return get_event_handler(&This->event_target, EVENTID_LOAD, p);
1454 static const IWineXMLHttpRequestPrivateVtbl WineXMLHttpRequestPrivateVtbl = {
1455 HTMLXMLHttpRequest_private_QueryInterface,
1456 HTMLXMLHttpRequest_private_AddRef,
1457 HTMLXMLHttpRequest_private_Release,
1458 HTMLXMLHttpRequest_private_GetTypeInfoCount,
1459 HTMLXMLHttpRequest_private_GetTypeInfo,
1460 HTMLXMLHttpRequest_private_GetIDsOfNames,
1461 HTMLXMLHttpRequest_private_Invoke,
1462 HTMLXMLHttpRequest_private_get_response,
1463 HTMLXMLHttpRequest_private_put_responseType,
1464 HTMLXMLHttpRequest_private_get_responseType,
1465 HTMLXMLHttpRequest_private_get_upload,
1466 HTMLXMLHttpRequest_private_put_withCredentials,
1467 HTMLXMLHttpRequest_private_get_withCredentials,
1468 HTMLXMLHttpRequest_private_overrideMimeType,
1469 HTMLXMLHttpRequest_private_put_onerror,
1470 HTMLXMLHttpRequest_private_get_onerror,
1471 HTMLXMLHttpRequest_private_put_onabort,
1472 HTMLXMLHttpRequest_private_get_onabort,
1473 HTMLXMLHttpRequest_private_put_onprogress,
1474 HTMLXMLHttpRequest_private_get_onprogress,
1475 HTMLXMLHttpRequest_private_put_onloadstart,
1476 HTMLXMLHttpRequest_private_get_onloadstart,
1477 HTMLXMLHttpRequest_private_put_onloadend,
1478 HTMLXMLHttpRequest_private_get_onloadend,
1479 HTMLXMLHttpRequest_private_put_onload,
1480 HTMLXMLHttpRequest_private_get_onload
1483 static inline HTMLXMLHttpRequest *impl_from_IProvideClassInfo2(IProvideClassInfo2 *iface)
1485 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IProvideClassInfo2_iface);
1488 static HRESULT WINAPI ProvideClassInfo_QueryInterface(IProvideClassInfo2 *iface, REFIID riid, void **ppv)
1490 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
1491 return IHTMLXMLHttpRequest_QueryInterface(&This->IHTMLXMLHttpRequest_iface, riid, ppv);
1494 static ULONG WINAPI ProvideClassInfo_AddRef(IProvideClassInfo2 *iface)
1496 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
1497 return IHTMLXMLHttpRequest_AddRef(&This->IHTMLXMLHttpRequest_iface);
1500 static ULONG WINAPI ProvideClassInfo_Release(IProvideClassInfo2 *iface)
1502 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
1503 return IHTMLXMLHttpRequest_Release(&This->IHTMLXMLHttpRequest_iface);
1506 static HRESULT WINAPI ProvideClassInfo_GetClassInfo(IProvideClassInfo2 *iface, ITypeInfo **ppTI)
1508 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
1509 TRACE("(%p)->(%p)\n", This, ppTI);
1510 return get_class_typeinfo(&CLSID_HTMLXMLHttpRequest, ppTI);
1513 static HRESULT WINAPI ProvideClassInfo2_GetGUID(IProvideClassInfo2 *iface, DWORD dwGuidKind, GUID *pGUID)
1515 HTMLXMLHttpRequest *This = impl_from_IProvideClassInfo2(iface);
1516 FIXME("(%p)->(%lu %p)\n", This, dwGuidKind, pGUID);
1517 return E_NOTIMPL;
1520 static const IProvideClassInfo2Vtbl ProvideClassInfo2Vtbl = {
1521 ProvideClassInfo_QueryInterface,
1522 ProvideClassInfo_AddRef,
1523 ProvideClassInfo_Release,
1524 ProvideClassInfo_GetClassInfo,
1525 ProvideClassInfo2_GetGUID,
1528 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
1530 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex);
1533 static nsISupports *HTMLXMLHttpRequest_get_gecko_target(DispatchEx *dispex)
1535 HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
1536 return (nsISupports*)This->nsxhr;
1539 static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, eventid_t eid)
1541 /* Do nothing. To be able to track state and queue events manually, when blocked
1542 * by sync XHRs in their send() event loop, we always register the handlers. */
1545 static void HTMLXMLHttpRequest_init_dispex_info(dispex_data_t *info, compat_mode_t compat_mode)
1547 static const dispex_hook_t xhr_hooks[] = {
1548 {DISPID_IHTMLXMLHTTPREQUEST_OPEN, HTMLXMLHttpRequest_open_hook},
1549 {DISPID_UNKNOWN}
1551 static const dispex_hook_t private_hooks[] = {
1552 {DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSE},
1553 {DISPID_IWINEXMLHTTPREQUESTPRIVATE_RESPONSETYPE},
1554 {DISPID_IWINEXMLHTTPREQUESTPRIVATE_UPLOAD},
1555 {DISPID_IWINEXMLHTTPREQUESTPRIVATE_WITHCREDENTIALS},
1556 {DISPID_EVPROP_ONERROR},
1557 {DISPID_EVPROP_ONABORT},
1558 {DISPID_EVPROP_PROGRESS},
1559 {DISPID_EVPROP_LOADSTART},
1560 {DISPID_EVPROP_LOADEND},
1562 /* IE10 only */
1563 {DISPID_IWINEXMLHTTPREQUESTPRIVATE_OVERRIDEMIMETYPE},
1564 {DISPID_UNKNOWN}
1566 const dispex_hook_t *const private_ie10_hooks = private_hooks + ARRAY_SIZE(private_hooks) - 2;
1568 EventTarget_init_dispex_info(info, compat_mode);
1569 dispex_info_add_interface(info, IHTMLXMLHttpRequest_tid, compat_mode >= COMPAT_MODE_IE10 ? xhr_hooks : NULL);
1570 dispex_info_add_interface(info, IWineXMLHttpRequestPrivate_tid,
1571 compat_mode < COMPAT_MODE_IE10 ? private_hooks :
1572 compat_mode < COMPAT_MODE_IE11 ? private_ie10_hooks : NULL);
1575 static event_target_vtbl_t HTMLXMLHttpRequest_event_target_vtbl = {
1577 NULL,
1579 HTMLXMLHttpRequest_get_gecko_target,
1580 HTMLXMLHttpRequest_bind_event
1583 static const tid_t HTMLXMLHttpRequest_iface_tids[] = {
1584 IHTMLXMLHttpRequest2_tid,
1587 static dispex_static_data_t HTMLXMLHttpRequest_dispex = {
1588 L"XMLHttpRequest",
1589 &HTMLXMLHttpRequest_event_target_vtbl.dispex_vtbl,
1590 DispHTMLXMLHttpRequest_tid,
1591 HTMLXMLHttpRequest_iface_tids,
1592 HTMLXMLHttpRequest_init_dispex_info
1596 /* IHTMLXMLHttpRequestFactory */
1597 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface)
1599 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface);
1602 static HRESULT WINAPI HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory *iface, REFIID riid, void **ppv)
1604 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1606 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1608 if(IsEqualGUID(&IID_IUnknown, riid)) {
1609 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
1610 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1611 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
1612 }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) {
1613 *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
1614 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1615 return *ppv ? S_OK : E_NOINTERFACE;
1616 }else {
1617 *ppv = NULL;
1618 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1619 return E_NOINTERFACE;
1622 IUnknown_AddRef((IUnknown*)*ppv);
1623 return S_OK;
1626 static ULONG WINAPI HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory *iface)
1628 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1629 LONG ref = InterlockedIncrement(&This->ref);
1631 TRACE("(%p) ref=%ld\n", This, ref);
1633 return ref;
1636 static ULONG WINAPI HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory *iface)
1638 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1639 LONG ref = InterlockedDecrement(&This->ref);
1641 TRACE("(%p) ref=%ld\n", This, ref);
1643 if(!ref) {
1644 release_dispex(&This->dispex);
1645 free(This);
1648 return ref;
1651 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory *iface, UINT *pctinfo)
1653 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1654 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1657 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory *iface, UINT iTInfo,
1658 LCID lcid, ITypeInfo **ppTInfo)
1660 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1662 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1665 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1666 LCID lcid, DISPID *rgDispId)
1668 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1670 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1671 lcid, rgDispId);
1674 static HRESULT WINAPI HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1675 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1677 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1679 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
1680 pDispParams, pVarResult, pExcepInfo, puArgErr);
1683 static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p)
1685 HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
1686 HTMLXMLHttpRequest *ret;
1687 nsIXMLHttpRequest *nsxhr;
1688 nsIDOMEventTarget *nstarget;
1689 XMLHttpReqEventListener *event_listener;
1690 nsresult nsres;
1691 unsigned i;
1693 TRACE("(%p)->(%p)\n", This, p);
1695 nsxhr = create_nsxhr(This->window->base.outer_window->nswindow);
1696 if(!nsxhr)
1697 return E_FAIL;
1699 ret = calloc(1, sizeof(*ret));
1700 if(!ret) {
1701 nsIXMLHttpRequest_Release(nsxhr);
1702 return E_OUTOFMEMORY;
1705 event_listener = malloc(sizeof(*event_listener));
1706 if(!event_listener) {
1707 free(ret);
1708 nsIXMLHttpRequest_Release(nsxhr);
1709 return E_OUTOFMEMORY;
1712 ret->nsxhr = nsxhr;
1713 ret->window = This->window;
1714 ret->task_magic = get_task_target_magic();
1715 IHTMLWindow2_AddRef(&This->window->base.IHTMLWindow2_iface);
1717 ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
1718 ret->IHTMLXMLHttpRequest2_iface.lpVtbl = &HTMLXMLHttpRequest2Vtbl;
1719 ret->IWineXMLHttpRequestPrivate_iface.lpVtbl = &WineXMLHttpRequestPrivateVtbl;
1720 ret->IProvideClassInfo2_iface.lpVtbl = &ProvideClassInfo2Vtbl;
1721 EventTarget_Init(&ret->event_target, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
1722 &HTMLXMLHttpRequest_dispex, This->window->doc->document_mode);
1723 ret->ref = 1;
1725 /* Always register the handlers because we need them to track state */
1726 event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
1727 event_listener->ref = 1;
1728 event_listener->xhr = ret;
1729 ret->event_listener = event_listener;
1731 nsres = nsIXMLHttpRequest_QueryInterface(nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
1732 assert(nsres == NS_OK);
1734 for(i = 0; i < ARRAY_SIZE(events); i++) {
1735 const WCHAR *name = get_event_name(events[i]);
1736 nsAString type_str;
1738 nsAString_InitDepend(&type_str, name);
1739 nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
1740 nsAString_Finish(&type_str);
1741 if(NS_FAILED(nsres)) {
1742 WARN("AddEventListener(%s) failed: %08lx\n", debugstr_w(name), nsres);
1743 IHTMLXMLHttpRequest_Release(&ret->IHTMLXMLHttpRequest_iface);
1744 return map_nsresult(nsres);
1747 nsIDOMEventTarget_Release(nstarget);
1749 *p = &ret->IHTMLXMLHttpRequest_iface;
1750 return S_OK;
1753 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = {
1754 HTMLXMLHttpRequestFactory_QueryInterface,
1755 HTMLXMLHttpRequestFactory_AddRef,
1756 HTMLXMLHttpRequestFactory_Release,
1757 HTMLXMLHttpRequestFactory_GetTypeInfoCount,
1758 HTMLXMLHttpRequestFactory_GetTypeInfo,
1759 HTMLXMLHttpRequestFactory_GetIDsOfNames,
1760 HTMLXMLHttpRequestFactory_Invoke,
1761 HTMLXMLHttpRequestFactory_create
1764 static inline HTMLXMLHttpRequestFactory *factory_from_DispatchEx(DispatchEx *iface)
1766 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, dispex);
1769 static HRESULT HTMLXMLHttpRequestFactory_value(DispatchEx *iface, LCID lcid, WORD flags, DISPPARAMS *params,
1770 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1772 HTMLXMLHttpRequestFactory *This = factory_from_DispatchEx(iface);
1773 IHTMLXMLHttpRequest *xhr;
1774 HRESULT hres;
1776 TRACE("\n");
1778 if(flags != DISPATCH_CONSTRUCT) {
1779 FIXME("flags %x not supported\n", flags);
1780 return E_NOTIMPL;
1783 hres = IHTMLXMLHttpRequestFactory_create(&This->IHTMLXMLHttpRequestFactory_iface, &xhr);
1784 if(FAILED(hres))
1785 return hres;
1787 V_VT(res) = VT_DISPATCH;
1788 V_DISPATCH(res) = (IDispatch*)xhr;
1789 return S_OK;
1792 static const dispex_static_data_vtbl_t HTMLXMLHttpRequestFactory_dispex_vtbl = {
1793 HTMLXMLHttpRequestFactory_value
1796 static const tid_t HTMLXMLHttpRequestFactory_iface_tids[] = {
1797 IHTMLXMLHttpRequestFactory_tid,
1800 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = {
1801 L"Function",
1802 &HTMLXMLHttpRequestFactory_dispex_vtbl,
1803 IHTMLXMLHttpRequestFactory_tid,
1804 HTMLXMLHttpRequestFactory_iface_tids
1807 HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpRequestFactory **ret_ptr)
1809 HTMLXMLHttpRequestFactory *ret;
1811 ret = malloc(sizeof(*ret));
1812 if(!ret)
1813 return E_OUTOFMEMORY;
1815 ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl;
1816 ret->ref = 1;
1817 ret->window = window;
1819 init_dispatch(&ret->dispex, (IUnknown*)&ret->IHTMLXMLHttpRequestFactory_iface,
1820 &HTMLXMLHttpRequestFactory_dispex, dispex_compat_mode(&window->event_target.dispex));
1822 *ret_ptr = ret;
1823 return S_OK;