xref: /reactos/dll/win32/mshtml/xmlhttprequest.c (revision c2c66aff)
1 /*
2  * Copyright 2015 Zhenbo Li
3  *
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.
8  *
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.
13  *
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
17  */
18 
19 #include "mshtml_private.h"
20 
bstr_to_nsacstr(BSTR bstr,nsACString * str)21 static HRESULT bstr_to_nsacstr(BSTR bstr, nsACString *str)
22 {
23     char *cstr = heap_strdupWtoU(bstr);
24     if(!cstr)
25         return E_OUTOFMEMORY;
26     nsACString_Init(str, cstr);
27     heap_free(cstr);
28     return S_OK;
29 }
30 
variant_to_nsastr(VARIANT var,nsAString * ret)31 static HRESULT variant_to_nsastr(VARIANT var, nsAString *ret)
32 {
33     switch(V_VT(&var)) {
34         case VT_NULL:
35         case VT_ERROR:
36         case VT_EMPTY:
37             nsAString_Init(ret, NULL);
38             return S_OK;
39         case VT_BSTR:
40             nsAString_InitDepend(ret, V_BSTR(&var));
41             return S_OK;
42         default:
43             FIXME("Unsupported VARIANT: %s\n", debugstr_variant(&var));
44             return E_INVALIDARG;
45     }
46 }
47 
return_nscstr(nsresult nsres,nsACString * nscstr,BSTR * p)48 static HRESULT return_nscstr(nsresult nsres, nsACString *nscstr, BSTR *p)
49 {
50     const char *str;
51     int len;
52 
53     if(NS_FAILED(nsres)) {
54         ERR("failed: %08x\n", nsres);
55         nsACString_Finish(nscstr);
56         return E_FAIL;
57     }
58 
59     nsACString_GetData(nscstr, &str);
60 
61     if(*str) {
62         len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
63         *p = SysAllocStringLen(NULL, len);
64         if(!*p) {
65             nsACString_Finish(nscstr);
66             return E_OUTOFMEMORY;
67         }
68         MultiByteToWideChar(CP_UTF8, 0, str, -1, *p, len);
69     }else {
70         *p = NULL;
71     }
72 
73     nsACString_Finish(nscstr);
74     return S_OK;
75 }
76 
77 typedef struct XMLHttpReqEventListener XMLHttpReqEventListener;
78 
79 typedef struct {
80     EventTarget event_target;
81     IHTMLXMLHttpRequest IHTMLXMLHttpRequest_iface;
82     LONG ref;
83     nsIXMLHttpRequest *nsxhr;
84     XMLHttpReqEventListener *event_listener;
85 } HTMLXMLHttpRequest;
86 
87 struct XMLHttpReqEventListener {
88     nsIDOMEventListener nsIDOMEventListener_iface;
89     LONG ref;
90     HTMLXMLHttpRequest *xhr;
91 };
92 
detach_xhr_event_listener(XMLHttpReqEventListener * event_listener)93 static void detach_xhr_event_listener(XMLHttpReqEventListener *event_listener)
94 {
95     nsIDOMEventTarget *event_target;
96     nsAString str;
97     nsresult nsres;
98 
99     static const WCHAR readystatechangeW[] =
100         {'o','n','r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
101 
102     nsres = nsIXMLHttpRequest_QueryInterface(event_listener->xhr->nsxhr, &IID_nsIDOMEventTarget, (void**)&event_target);
103     assert(nsres == NS_OK);
104 
105     nsAString_InitDepend(&str, readystatechangeW);
106     nsres = nsIDOMEventTarget_RemoveEventListener(event_target, &str, &event_listener->nsIDOMEventListener_iface, FALSE);
107     nsAString_Finish(&str);
108     nsIDOMEventTarget_Release(event_target);
109 
110     event_listener->xhr->event_listener = NULL;
111     event_listener->xhr = NULL;
112     nsIDOMEventListener_Release(&event_listener->nsIDOMEventListener_iface);
113 }
114 
115 
impl_from_nsIDOMEventListener(nsIDOMEventListener * iface)116 static inline XMLHttpReqEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface)
117 {
118     return CONTAINING_RECORD(iface, XMLHttpReqEventListener, nsIDOMEventListener_iface);
119 }
120 
XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener * iface,nsIIDRef riid,void ** result)121 static nsresult NSAPI XMLHttpReqEventListener_QueryInterface(nsIDOMEventListener *iface,
122         nsIIDRef riid, void **result)
123 {
124     XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
125 
126     if(IsEqualGUID(&IID_nsISupports, riid)) {
127         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
128         *result = &This->nsIDOMEventListener_iface;
129     }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
130         TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
131         *result = &This->nsIDOMEventListener_iface;
132     }else {
133         *result = NULL;
134         TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
135         return NS_NOINTERFACE;
136     }
137 
138     nsIDOMEventListener_AddRef(&This->nsIDOMEventListener_iface);
139     return NS_OK;
140 }
141 
XMLHttpReqEventListener_AddRef(nsIDOMEventListener * iface)142 static nsrefcnt NSAPI XMLHttpReqEventListener_AddRef(nsIDOMEventListener *iface)
143 {
144     XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
145     LONG ref = InterlockedIncrement(&This->ref);
146 
147     TRACE("(%p) ref=%d\n", This, ref);
148 
149     return ref;
150 }
151 
XMLHttpReqEventListener_Release(nsIDOMEventListener * iface)152 static nsrefcnt NSAPI XMLHttpReqEventListener_Release(nsIDOMEventListener *iface)
153 {
154     XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
155     LONG ref = InterlockedDecrement(&This->ref);
156 
157     TRACE("(%p) ref=%d\n", This, ref);
158 
159     if(!ref) {
160         assert(!This->xhr);
161         heap_free(This);
162     }
163 
164     return ref;
165 }
166 
XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener * iface,nsIDOMEvent * event)167 static nsresult NSAPI XMLHttpReqEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *event)
168 {
169     XMLHttpReqEventListener *This = impl_from_nsIDOMEventListener(iface);
170 
171     TRACE("(%p)\n", This);
172 
173     if(!This->xhr)
174         return NS_OK;
175 
176     call_event_handlers(NULL, NULL, &This->xhr->event_target, NULL, EVENTID_READYSTATECHANGE,
177             (IDispatch*)&This->xhr->IHTMLXMLHttpRequest_iface);
178     return NS_OK;
179 }
180 
181 static const nsIDOMEventListenerVtbl XMLHttpReqEventListenerVtbl = {
182     XMLHttpReqEventListener_QueryInterface,
183     XMLHttpReqEventListener_AddRef,
184     XMLHttpReqEventListener_Release,
185     XMLHttpReqEventListener_HandleEvent
186 };
187 
impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest * iface)188 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface)
189 {
190     return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface);
191 }
192 
HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest * iface,REFIID riid,void ** ppv)193 static HRESULT WINAPI HTMLXMLHttpRequest_QueryInterface(IHTMLXMLHttpRequest *iface, REFIID riid, void **ppv)
194 {
195     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
196 
197     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
198 
199     if(IsEqualGUID(&IID_IUnknown, riid)) {
200         *ppv = &This->IHTMLXMLHttpRequest_iface;
201     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
202         *ppv = &This->IHTMLXMLHttpRequest_iface;
203     }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequest, riid)) {
204         *ppv = &This->IHTMLXMLHttpRequest_iface;
205     }else if(dispex_query_interface(&This->event_target.dispex, riid, ppv)) {
206         return *ppv ? S_OK : E_NOINTERFACE;
207     }else {
208         *ppv = NULL;
209         WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
210         return E_NOINTERFACE;
211     }
212 
213     IUnknown_AddRef((IUnknown*)*ppv);
214     return S_OK;
215 }
216 
HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest * iface)217 static ULONG WINAPI HTMLXMLHttpRequest_AddRef(IHTMLXMLHttpRequest *iface)
218 {
219     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
220     LONG ref = InterlockedIncrement(&This->ref);
221 
222     TRACE("(%p) ref=%d\n", This, ref);
223 
224     return ref;
225 }
226 
HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest * iface)227 static ULONG WINAPI HTMLXMLHttpRequest_Release(IHTMLXMLHttpRequest *iface)
228 {
229     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
230     LONG ref = InterlockedDecrement(&This->ref);
231 
232     TRACE("(%p) ref=%d\n", This, ref);
233 
234     if(!ref) {
235         if(This->event_listener)
236             detach_xhr_event_listener(This->event_listener);
237         release_dispex(&This->event_target.dispex);
238         nsIXMLHttpRequest_Release(This->nsxhr);
239         heap_free(This);
240     }
241 
242     return ref;
243 }
244 
HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest * iface,UINT * pctinfo)245 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfoCount(IHTMLXMLHttpRequest *iface, UINT *pctinfo)
246 {
247     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
248     return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
249 }
250 
HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)251 static HRESULT WINAPI HTMLXMLHttpRequest_GetTypeInfo(IHTMLXMLHttpRequest *iface, UINT iTInfo,
252         LCID lcid, ITypeInfo **ppTInfo)
253 {
254     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
255 
256     return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
257 }
258 
HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)259 static HRESULT WINAPI HTMLXMLHttpRequest_GetIDsOfNames(IHTMLXMLHttpRequest *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
260         LCID lcid, DISPID *rgDispId)
261 {
262     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
263 
264     return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
265             lcid, rgDispId);
266 }
267 
HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)268 static HRESULT WINAPI HTMLXMLHttpRequest_Invoke(IHTMLXMLHttpRequest *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
269         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
270 {
271     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
272 
273     return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
274             pDispParams, pVarResult, pExcepInfo, puArgErr);
275 }
276 
HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest * iface,LONG * p)277 static HRESULT WINAPI HTMLXMLHttpRequest_get_readyState(IHTMLXMLHttpRequest *iface, LONG *p)
278 {
279     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
280     UINT16 val;
281     nsresult nsres;
282 
283     TRACE("(%p)->(%p)\n", This, p);
284 
285     if(!p)
286         return E_POINTER;
287     nsres = nsIXMLHttpRequest_GetReadyState(This->nsxhr, &val);
288     if(NS_FAILED(nsres)) {
289         ERR("nsIXMLHttpRequest_GetReadyState failed: %08x\n", nsres);
290         return E_FAIL;
291     }
292     *p = val;
293     return S_OK;
294 }
295 
HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest * iface,VARIANT * p)296 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseBody(IHTMLXMLHttpRequest *iface, VARIANT *p)
297 {
298     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
299     FIXME("(%p)->(%p)\n", This, p);
300     return E_NOTIMPL;
301 }
302 
HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest * iface,BSTR * p)303 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseText(IHTMLXMLHttpRequest *iface, BSTR *p)
304 {
305     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
306     nsAString nsstr;
307     nsresult nsres;
308 
309     TRACE("(%p)->(%p)\n", This, p);
310 
311     if(!p)
312         return E_POINTER;
313 
314     nsAString_Init(&nsstr, NULL);
315     nsres = nsIXMLHttpRequest_GetResponseText(This->nsxhr, &nsstr);
316     return return_nsstr(nsres, &nsstr, p);
317 }
318 
HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest * iface,IDispatch ** p)319 static HRESULT WINAPI HTMLXMLHttpRequest_get_responseXML(IHTMLXMLHttpRequest *iface, IDispatch **p)
320 {
321     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
322     FIXME("(%p)->(%p)\n", This, p);
323     return E_NOTIMPL;
324 }
325 
HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest * iface,LONG * p)326 static HRESULT WINAPI HTMLXMLHttpRequest_get_status(IHTMLXMLHttpRequest *iface, LONG *p)
327 {
328     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
329     DWORD val;
330     nsresult nsres;
331     TRACE("(%p)->(%p)\n", This, p);
332 
333     if(!p)
334         return E_POINTER;
335 
336     nsres = nsIXMLHttpRequest_GetStatus(This->nsxhr, &val);
337     if(NS_FAILED(nsres)) {
338         ERR("nsIXMLHttpRequest_GetStatus failed: %08x\n", nsres);
339         return E_FAIL;
340     }
341     *p = val;
342     if(val == 0)
343         return E_FAIL; /* WinAPI thinks this is an error */
344 
345     return S_OK;
346 }
347 
HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest * iface,BSTR * p)348 static HRESULT WINAPI HTMLXMLHttpRequest_get_statusText(IHTMLXMLHttpRequest *iface, BSTR *p)
349 {
350     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
351     nsACString nscstr;
352     nsresult nsres;
353     HRESULT hres;
354     LONG state;
355 
356     TRACE("(%p)->(%p)\n", This, p);
357 
358     if(!p)
359         return E_POINTER;
360 
361     hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
362     if(FAILED(hres))
363         return hres;
364 
365     if(state < 2) {
366         *p = NULL;
367         return E_FAIL;
368     }
369 
370     nsACString_Init(&nscstr, NULL);
371     nsres = nsIXMLHttpRequest_GetStatusText(This->nsxhr, &nscstr);
372     return return_nscstr(nsres, &nscstr, p);
373 }
374 
HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest * iface,VARIANT v)375 static HRESULT WINAPI HTMLXMLHttpRequest_put_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT v)
376 {
377     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
378 
379     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
380 
381     return set_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, &v);
382 }
383 
HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest * iface,VARIANT * p)384 static HRESULT WINAPI HTMLXMLHttpRequest_get_onreadystatechange(IHTMLXMLHttpRequest *iface, VARIANT *p)
385 {
386     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
387 
388     TRACE("(%p)->(%p)\n", This, p);
389 
390     return get_event_handler(&This->event_target, EVENTID_READYSTATECHANGE, p);
391 }
392 
HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest * iface)393 static HRESULT WINAPI HTMLXMLHttpRequest_abort(IHTMLXMLHttpRequest *iface)
394 {
395     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
396     nsresult nsres;
397 
398     TRACE("(%p)->()\n", This);
399 
400     nsres = nsIXMLHttpRequest_SlowAbort(This->nsxhr);
401     if(NS_FAILED(nsres)) {
402         ERR("nsIXMLHttpRequest_SlowAbort failed: %08x\n", nsres);
403         return E_FAIL;
404     }
405 
406     return S_OK;
407 }
408 
HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest * iface,BSTR bstrMethod,BSTR bstrUrl,VARIANT varAsync,VARIANT varUser,VARIANT varPassword)409 static HRESULT WINAPI HTMLXMLHttpRequest_open(IHTMLXMLHttpRequest *iface, BSTR bstrMethod, BSTR bstrUrl, VARIANT varAsync, VARIANT varUser, VARIANT varPassword)
410 {
411     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
412     nsACString method, url;
413     nsAString user, password;
414     nsresult nsres;
415     HRESULT hres;
416 
417     TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(bstrMethod), debugstr_w(bstrUrl), debugstr_variant(&varAsync), debugstr_variant(&varUser), debugstr_variant(&varPassword));
418 
419     if(V_VT(&varAsync) != VT_BOOL) {
420         FIXME("varAsync not supported: %s\n", debugstr_variant(&varAsync));
421         return E_FAIL;
422     }
423 
424     /* Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27),
425      * synchronous requests on the main thread have been deprecated due to the negative
426      * effects to the user experience.
427      */
428     if(!V_BOOL(&varAsync)) {
429         FIXME("Synchronous request is not supported yet\n");
430         return E_FAIL;
431     }
432 
433     hres = variant_to_nsastr(varUser, &user);
434     if(FAILED(hres))
435         return hres;
436     hres = variant_to_nsastr(varPassword, &password);
437     if(FAILED(hres)) {
438         nsAString_Finish(&user);
439         return hres;
440     }
441 
442     hres = bstr_to_nsacstr(bstrMethod, &method);
443     if(FAILED(hres)) {
444         nsAString_Finish(&user);
445         nsAString_Finish(&password);
446         return hres;
447     }
448     hres = bstr_to_nsacstr(bstrUrl, &url);
449     if(FAILED(hres)) {
450         nsAString_Finish(&user);
451         nsAString_Finish(&password);
452         nsACString_Finish(&method);
453         return hres;
454     }
455 
456     nsres = nsIXMLHttpRequest_Open(This->nsxhr, &method, &url, TRUE,
457             &user, &password, 0);
458 
459     nsACString_Finish(&method);
460     nsACString_Finish(&url);
461     nsAString_Finish(&user);
462     nsAString_Finish(&password);
463 
464     if(NS_FAILED(nsres)) {
465         ERR("nsIXMLHttpRequest_Open failed: %08x\n", nsres);
466         return E_FAIL;
467     }
468 
469     return S_OK;
470 }
471 
HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest * iface,VARIANT varBody)472 static HRESULT WINAPI HTMLXMLHttpRequest_send(IHTMLXMLHttpRequest *iface, VARIANT varBody)
473 {
474     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
475     nsresult nsres;
476 
477     TRACE("(%p)->(%s)\n", This, debugstr_variant(&varBody));
478 
479     switch(V_VT(&varBody)) {
480         case VT_NULL:
481         case VT_EMPTY:
482         case VT_ERROR:
483             break;
484         default:
485             FIXME("varBody(%s) unsupported\n", debugstr_variant(&varBody));
486             return E_FAIL;
487     }
488 
489     nsres = nsIXMLHttpRequest_Send(This->nsxhr, NULL);
490 
491     if(NS_FAILED(nsres)) {
492         ERR("nsIXMLHttpRequest_Send failed: %08x\n", nsres);
493         return E_FAIL;
494     }
495 
496     return S_OK;
497 }
498 
HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest * iface,BSTR * p)499 static HRESULT WINAPI HTMLXMLHttpRequest_getAllResponseHeaders(IHTMLXMLHttpRequest *iface, BSTR *p)
500 {
501     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
502     nsACString nscstr;
503     nsresult nsres;
504     HRESULT hres;
505     LONG state;
506 
507     TRACE("(%p)->(%p)\n", This, p);
508 
509     if(!p)
510         return E_POINTER;
511 
512     hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
513     if(FAILED(hres))
514         return hres;
515 
516     if(state < 2) {
517         *p = NULL;
518         return E_FAIL;
519     }
520 
521     nsACString_Init(&nscstr, NULL);
522     nsres = nsIXMLHttpRequest_GetAllResponseHeaders(This->nsxhr, &nscstr);
523     return return_nscstr(nsres, &nscstr, p);
524 }
525 
HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest * iface,BSTR bstrHeader,BSTR * p)526 static HRESULT WINAPI HTMLXMLHttpRequest_getResponseHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR *p)
527 {
528     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
529     nsACString header, ret;
530     char *cstr;
531     nsresult nsres;
532     HRESULT hres;
533     LONG state;
534     TRACE("(%p)->(%s %p)\n", This, debugstr_w(bstrHeader), p);
535 
536     if(!p)
537         return E_POINTER;
538     if(!bstrHeader)
539         return E_INVALIDARG;
540 
541     hres = IHTMLXMLHttpRequest_get_readyState(iface, &state);
542     if(FAILED(hres))
543         return hres;
544 
545     if(state < 2) {
546         *p = NULL;
547         return E_FAIL;
548     }
549 
550     cstr = heap_strdupWtoU(bstrHeader);
551     nsACString_InitDepend(&header, cstr);
552     nsACString_Init(&ret, NULL);
553 
554     nsres = nsIXMLHttpRequest_GetResponseHeader(This->nsxhr, &header, &ret);
555 
556     nsACString_Finish(&header);
557     heap_free(cstr);
558     return return_nscstr(nsres, &ret, p);
559 }
560 
HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest * iface,BSTR bstrHeader,BSTR bstrValue)561 static HRESULT WINAPI HTMLXMLHttpRequest_setRequestHeader(IHTMLXMLHttpRequest *iface, BSTR bstrHeader, BSTR bstrValue)
562 {
563     HTMLXMLHttpRequest *This = impl_from_IHTMLXMLHttpRequest(iface);
564     FIXME("(%p)->(%s %s)\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue));
565     return E_NOTIMPL;
566 }
567 
568 static const IHTMLXMLHttpRequestVtbl HTMLXMLHttpRequestVtbl = {
569     HTMLXMLHttpRequest_QueryInterface,
570     HTMLXMLHttpRequest_AddRef,
571     HTMLXMLHttpRequest_Release,
572     HTMLXMLHttpRequest_GetTypeInfoCount,
573     HTMLXMLHttpRequest_GetTypeInfo,
574     HTMLXMLHttpRequest_GetIDsOfNames,
575     HTMLXMLHttpRequest_Invoke,
576     HTMLXMLHttpRequest_get_readyState,
577     HTMLXMLHttpRequest_get_responseBody,
578     HTMLXMLHttpRequest_get_responseText,
579     HTMLXMLHttpRequest_get_responseXML,
580     HTMLXMLHttpRequest_get_status,
581     HTMLXMLHttpRequest_get_statusText,
582     HTMLXMLHttpRequest_put_onreadystatechange,
583     HTMLXMLHttpRequest_get_onreadystatechange,
584     HTMLXMLHttpRequest_abort,
585     HTMLXMLHttpRequest_open,
586     HTMLXMLHttpRequest_send,
587     HTMLXMLHttpRequest_getAllResponseHeaders,
588     HTMLXMLHttpRequest_getResponseHeader,
589     HTMLXMLHttpRequest_setRequestHeader
590 };
591 
impl_from_DispatchEx(DispatchEx * iface)592 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface)
593 {
594     return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex);
595 }
596 
HTMLXMLHttpRequest_bind_event(DispatchEx * dispex,int eid)597 static void HTMLXMLHttpRequest_bind_event(DispatchEx *dispex, int eid)
598 {
599     HTMLXMLHttpRequest *This = impl_from_DispatchEx(dispex);
600     nsIDOMEventTarget *nstarget;
601     nsAString type_str;
602     nsresult nsres;
603 
604     static const WCHAR readystatechangeW[] = {'r','e','a','d','y','s','t','a','t','e','c','h','a','n','g','e',0};
605 
606     TRACE("(%p)\n", This);
607 
608     assert(eid == EVENTID_READYSTATECHANGE);
609 
610     if(This->event_listener)
611         return;
612 
613     This->event_listener = heap_alloc(sizeof(*This->event_listener));
614     if(!This->event_listener)
615         return;
616 
617     This->event_listener->nsIDOMEventListener_iface.lpVtbl = &XMLHttpReqEventListenerVtbl;
618     This->event_listener->ref = 1;
619     This->event_listener->xhr = This;
620 
621     nsres = nsIXMLHttpRequest_QueryInterface(This->nsxhr, &IID_nsIDOMEventTarget, (void**)&nstarget);
622     assert(nsres == NS_OK);
623 
624     nsAString_InitDepend(&type_str, readystatechangeW);
625     nsres = nsIDOMEventTarget_AddEventListener(nstarget, &type_str, &This->event_listener->nsIDOMEventListener_iface, FALSE, TRUE, 2);
626     nsAString_Finish(&type_str);
627     nsIDOMEventTarget_Release(nstarget);
628     if(NS_FAILED(nsres))
629         ERR("AddEventListener failed: %08x\n", nsres);
630 }
631 
632 static dispex_static_data_vtbl_t HTMLXMLHttpRequest_dispex_vtbl = {
633     NULL,
634     NULL,
635     NULL,
636     NULL,
637     NULL,
638     HTMLXMLHttpRequest_bind_event
639 };
640 
641 static const tid_t HTMLXMLHttpRequest_iface_tids[] = {
642     IHTMLXMLHttpRequest_tid,
643     0
644 };
645 static dispex_static_data_t HTMLXMLHttpRequest_dispex = {
646     &HTMLXMLHttpRequest_dispex_vtbl,
647     DispHTMLXMLHttpRequest_tid,
648     NULL,
649     HTMLXMLHttpRequest_iface_tids
650 };
651 
652 
653 /* IHTMLXMLHttpRequestFactory */
impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory * iface)654 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface)
655 {
656     return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface);
657 }
658 
HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory * iface,REFIID riid,void ** ppv)659 static HRESULT WINAPI HTMLXMLHttpRequestFactory_QueryInterface(IHTMLXMLHttpRequestFactory *iface, REFIID riid, void **ppv)
660 {
661     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
662 
663     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
664 
665     if(IsEqualGUID(&IID_IUnknown, riid)) {
666         *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
667     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
668         *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
669     }else if(IsEqualGUID(&IID_IHTMLXMLHttpRequestFactory, riid)) {
670         *ppv = &This->IHTMLXMLHttpRequestFactory_iface;
671     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
672         return *ppv ? S_OK : E_NOINTERFACE;
673     }else {
674         *ppv = NULL;
675         WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
676         return E_NOINTERFACE;
677     }
678 
679     IUnknown_AddRef((IUnknown*)*ppv);
680     return S_OK;
681 }
682 
HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory * iface)683 static ULONG WINAPI HTMLXMLHttpRequestFactory_AddRef(IHTMLXMLHttpRequestFactory *iface)
684 {
685     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
686     LONG ref = InterlockedIncrement(&This->ref);
687 
688     TRACE("(%p) ref=%d\n", This, ref);
689 
690     return ref;
691 }
692 
HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory * iface)693 static ULONG WINAPI HTMLXMLHttpRequestFactory_Release(IHTMLXMLHttpRequestFactory *iface)
694 {
695     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
696     LONG ref = InterlockedDecrement(&This->ref);
697 
698     TRACE("(%p) ref=%d\n", This, ref);
699 
700     if(!ref) {
701         release_dispex(&This->dispex);
702         heap_free(This);
703     }
704 
705     return ref;
706 }
707 
HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory * iface,UINT * pctinfo)708 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfoCount(IHTMLXMLHttpRequestFactory *iface, UINT *pctinfo)
709 {
710     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
711     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
712 }
713 
HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)714 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetTypeInfo(IHTMLXMLHttpRequestFactory *iface, UINT iTInfo,
715         LCID lcid, ITypeInfo **ppTInfo)
716 {
717     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
718 
719     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
720 }
721 
HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)722 static HRESULT WINAPI HTMLXMLHttpRequestFactory_GetIDsOfNames(IHTMLXMLHttpRequestFactory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
723         LCID lcid, DISPID *rgDispId)
724 {
725     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
726 
727     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
728             lcid, rgDispId);
729 }
730 
HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)731 static HRESULT WINAPI HTMLXMLHttpRequestFactory_Invoke(IHTMLXMLHttpRequestFactory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
732         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
733 {
734     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
735 
736     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
737             pDispParams, pVarResult, pExcepInfo, puArgErr);
738 }
739 
HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory * iface,IHTMLXMLHttpRequest ** p)740 static HRESULT WINAPI HTMLXMLHttpRequestFactory_create(IHTMLXMLHttpRequestFactory *iface, IHTMLXMLHttpRequest **p)
741 {
742     HTMLXMLHttpRequestFactory *This = impl_from_IHTMLXMLHttpRequestFactory(iface);
743     HTMLXMLHttpRequest        *ret;
744     nsIXMLHttpRequest         *nsxhr;
745 
746     TRACE("(%p)->(%p)\n", This, p);
747 
748     nsxhr = create_nsxhr(This->window->base.outer_window->nswindow);
749     if(!nsxhr)
750         return E_FAIL;
751 
752     ret = heap_alloc_zero(sizeof(*ret));
753     if(!ret) {
754         nsIXMLHttpRequest_Release(nsxhr);
755         return E_OUTOFMEMORY;
756     }
757     ret->nsxhr = nsxhr;
758 
759     ret->IHTMLXMLHttpRequest_iface.lpVtbl = &HTMLXMLHttpRequestVtbl;
760     init_dispex(&ret->event_target.dispex, (IUnknown*)&ret->IHTMLXMLHttpRequest_iface,
761             &HTMLXMLHttpRequest_dispex);
762     ret->ref = 1;
763 
764     *p = &ret->IHTMLXMLHttpRequest_iface;
765     return S_OK;
766 }
767 
768 static const IHTMLXMLHttpRequestFactoryVtbl HTMLXMLHttpRequestFactoryVtbl = {
769     HTMLXMLHttpRequestFactory_QueryInterface,
770     HTMLXMLHttpRequestFactory_AddRef,
771     HTMLXMLHttpRequestFactory_Release,
772     HTMLXMLHttpRequestFactory_GetTypeInfoCount,
773     HTMLXMLHttpRequestFactory_GetTypeInfo,
774     HTMLXMLHttpRequestFactory_GetIDsOfNames,
775     HTMLXMLHttpRequestFactory_Invoke,
776     HTMLXMLHttpRequestFactory_create
777 };
778 
779 static const tid_t HTMLXMLHttpRequestFactory_iface_tids[] = {
780     IHTMLXMLHttpRequestFactory_tid,
781     0
782 };
783 static dispex_static_data_t HTMLXMLHttpRequestFactory_dispex = {
784     NULL,
785     IHTMLXMLHttpRequestFactory_tid,
786     NULL,
787     HTMLXMLHttpRequestFactory_iface_tids
788 };
789 
HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow * window,HTMLXMLHttpRequestFactory ** ret_ptr)790 HRESULT HTMLXMLHttpRequestFactory_Create(HTMLInnerWindow* window, HTMLXMLHttpRequestFactory **ret_ptr)
791 {
792     HTMLXMLHttpRequestFactory *ret;
793 
794     ret = heap_alloc(sizeof(*ret));
795     if(!ret)
796         return E_OUTOFMEMORY;
797 
798     ret->IHTMLXMLHttpRequestFactory_iface.lpVtbl = &HTMLXMLHttpRequestFactoryVtbl;
799     ret->ref = 1;
800     ret->window = window;
801 
802     init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLXMLHttpRequestFactory_iface,
803             &HTMLXMLHttpRequestFactory_dispex);
804 
805     *ret_ptr = ret;
806     return S_OK;
807 }
808