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 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 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 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 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 116 static inline XMLHttpReqEventListener *impl_from_nsIDOMEventListener(nsIDOMEventListener *iface) 117 { 118 return CONTAINING_RECORD(iface, XMLHttpReqEventListener, nsIDOMEventListener_iface); 119 } 120 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 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 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 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 188 static inline HTMLXMLHttpRequest *impl_from_IHTMLXMLHttpRequest(IHTMLXMLHttpRequest *iface) 189 { 190 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, IHTMLXMLHttpRequest_iface); 191 } 192 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 592 static inline HTMLXMLHttpRequest *impl_from_DispatchEx(DispatchEx *iface) 593 { 594 return CONTAINING_RECORD(iface, HTMLXMLHttpRequest, event_target.dispex); 595 } 596 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 */ 654 static inline HTMLXMLHttpRequestFactory *impl_from_IHTMLXMLHttpRequestFactory(IHTMLXMLHttpRequestFactory *iface) 655 { 656 return CONTAINING_RECORD(iface, HTMLXMLHttpRequestFactory, IHTMLXMLHttpRequestFactory_iface); 657 } 658 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 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 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 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 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 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 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 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 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