1 /* 2 * IXMLHTTPRequest implementation 3 * 4 * Copyright 2008 Alistair Leslie-Hughes 5 * Copyright 2010-2012 Nikolay Sivov for CodeWeavers 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 #define NONAMELESSUNION 24 25 #include "config.h" 26 27 #include <stdarg.h> 28 #ifdef HAVE_LIBXML2 29 # include <libxml/parser.h> 30 # include <libxml/xmlerror.h> 31 # include <libxml/encoding.h> 32 #endif 33 34 #include "windef.h" 35 #include "winbase.h" 36 #include "wingdi.h" 37 #include "wininet.h" 38 #include "winreg.h" 39 #include "winuser.h" 40 #include "ole2.h" 41 #include "mshtml.h" 42 #include "msxml6.h" 43 #include "objsafe.h" 44 #include "docobj.h" 45 #include "shlwapi.h" 46 47 #include "msxml_private.h" 48 49 #include "wine/debug.h" 50 51 #ifdef HAVE_LIBXML2 52 53 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 54 55 static const WCHAR colspaceW[] = {':',' ',0}; 56 static const WCHAR crlfW[] = {'\r','\n',0}; 57 static const DWORD safety_supported_options = 58 INTERFACESAFE_FOR_UNTRUSTED_CALLER | 59 INTERFACESAFE_FOR_UNTRUSTED_DATA | 60 INTERFACE_USES_SECURITY_MANAGER; 61 62 typedef struct BindStatusCallback BindStatusCallback; 63 64 struct httpheader 65 { 66 struct list entry; 67 BSTR header; 68 BSTR value; 69 }; 70 71 typedef struct 72 { 73 IXMLHTTPRequest IXMLHTTPRequest_iface; 74 IObjectWithSite IObjectWithSite_iface; 75 IObjectSafety IObjectSafety_iface; 76 ISupportErrorInfo ISupportErrorInfo_iface; 77 LONG ref; 78 79 READYSTATE state; 80 IDispatch *sink; 81 82 /* request */ 83 BINDVERB verb; 84 BSTR custom; 85 IUri *uri; 86 IUri *base_uri; 87 BOOL async; 88 struct list reqheaders; 89 /* cached resulting custom request headers string length in WCHARs */ 90 LONG reqheader_size; 91 /* use UTF-8 content type */ 92 BOOL use_utf8_content; 93 94 /* response headers */ 95 struct list respheaders; 96 BSTR raw_respheaders; 97 98 /* credentials */ 99 BSTR user; 100 BSTR password; 101 102 /* bind callback */ 103 BindStatusCallback *bsc; 104 LONG status; 105 BSTR status_text; 106 107 /* IObjectWithSite*/ 108 IUnknown *site; 109 110 /* IObjectSafety */ 111 DWORD safeopt; 112 } httprequest; 113 114 typedef struct 115 { 116 httprequest req; 117 IServerXMLHTTPRequest IServerXMLHTTPRequest_iface; 118 } serverhttp; 119 120 static inline httprequest *impl_from_IXMLHTTPRequest( IXMLHTTPRequest *iface ) 121 { 122 return CONTAINING_RECORD(iface, httprequest, IXMLHTTPRequest_iface); 123 } 124 125 static inline httprequest *impl_from_IObjectWithSite(IObjectWithSite *iface) 126 { 127 return CONTAINING_RECORD(iface, httprequest, IObjectWithSite_iface); 128 } 129 130 static inline httprequest *impl_from_IObjectSafety(IObjectSafety *iface) 131 { 132 return CONTAINING_RECORD(iface, httprequest, IObjectSafety_iface); 133 } 134 135 static inline httprequest *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface) 136 { 137 return CONTAINING_RECORD(iface, httprequest, ISupportErrorInfo_iface); 138 } 139 140 static inline serverhttp *impl_from_IServerXMLHTTPRequest(IServerXMLHTTPRequest *iface) 141 { 142 return CONTAINING_RECORD(iface, serverhttp, IServerXMLHTTPRequest_iface); 143 } 144 145 static void httprequest_setreadystate(httprequest *This, READYSTATE state) 146 { 147 READYSTATE last = This->state; 148 static const char* readystates[] = { 149 "READYSTATE_UNINITIALIZED", 150 "READYSTATE_LOADING", 151 "READYSTATE_LOADED", 152 "READYSTATE_INTERACTIVE", 153 "READYSTATE_COMPLETE"}; 154 155 This->state = state; 156 157 TRACE("state %s\n", readystates[state]); 158 159 if (This->sink && last != state) 160 { 161 DISPPARAMS params; 162 163 memset(¶ms, 0, sizeof(params)); 164 IDispatch_Invoke(This->sink, 0, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, 0, 0, 0); 165 } 166 } 167 168 static void free_response_headers(httprequest *This) 169 { 170 struct httpheader *header, *header2; 171 172 LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->respheaders, struct httpheader, entry) 173 { 174 list_remove(&header->entry); 175 SysFreeString(header->header); 176 SysFreeString(header->value); 177 heap_free(header); 178 } 179 180 SysFreeString(This->raw_respheaders); 181 This->raw_respheaders = NULL; 182 } 183 184 static void free_request_headers(httprequest *This) 185 { 186 struct httpheader *header, *header2; 187 188 LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry) 189 { 190 list_remove(&header->entry); 191 SysFreeString(header->header); 192 SysFreeString(header->value); 193 heap_free(header); 194 } 195 } 196 197 struct BindStatusCallback 198 { 199 IBindStatusCallback IBindStatusCallback_iface; 200 IHttpNegotiate IHttpNegotiate_iface; 201 IAuthenticate IAuthenticate_iface; 202 LONG ref; 203 204 IBinding *binding; 205 httprequest *request; 206 207 /* response data */ 208 IStream *stream; 209 210 /* request body data */ 211 HGLOBAL body; 212 }; 213 214 static inline BindStatusCallback *impl_from_IBindStatusCallback( IBindStatusCallback *iface ) 215 { 216 return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallback_iface); 217 } 218 219 static inline BindStatusCallback *impl_from_IHttpNegotiate( IHttpNegotiate *iface ) 220 { 221 return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate_iface); 222 } 223 224 static inline BindStatusCallback *impl_from_IAuthenticate( IAuthenticate *iface ) 225 { 226 return CONTAINING_RECORD(iface, BindStatusCallback, IAuthenticate_iface); 227 } 228 229 static void BindStatusCallback_Detach(BindStatusCallback *bsc) 230 { 231 if (bsc) 232 { 233 if (bsc->binding) IBinding_Abort(bsc->binding); 234 bsc->request->bsc = NULL; 235 bsc->request = NULL; 236 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface); 237 } 238 } 239 240 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, 241 REFIID riid, void **ppv) 242 { 243 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 244 245 *ppv = NULL; 246 247 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); 248 249 if (IsEqualGUID(&IID_IUnknown, riid) || 250 IsEqualGUID(&IID_IBindStatusCallback, riid)) 251 { 252 *ppv = &This->IBindStatusCallback_iface; 253 } 254 else if (IsEqualGUID(&IID_IHttpNegotiate, riid)) 255 { 256 *ppv = &This->IHttpNegotiate_iface; 257 } 258 else if (IsEqualGUID(&IID_IAuthenticate, riid)) 259 { 260 *ppv = &This->IAuthenticate_iface; 261 } 262 else if (IsEqualGUID(&IID_IServiceProvider, riid) || 263 IsEqualGUID(&IID_IBindStatusCallbackEx, riid) || 264 IsEqualGUID(&IID_IInternetProtocol, riid) || 265 IsEqualGUID(&IID_IHttpNegotiate2, riid)) 266 { 267 return E_NOINTERFACE; 268 } 269 270 if (*ppv) 271 { 272 IBindStatusCallback_AddRef(iface); 273 return S_OK; 274 } 275 276 FIXME("Unsupported riid = %s\n", debugstr_guid(riid)); 277 278 return E_NOINTERFACE; 279 } 280 281 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface) 282 { 283 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 284 LONG ref = InterlockedIncrement(&This->ref); 285 286 TRACE("(%p) ref = %d\n", This, ref); 287 288 return ref; 289 } 290 291 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface) 292 { 293 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 294 LONG ref = InterlockedDecrement(&This->ref); 295 296 TRACE("(%p) ref = %d\n", This, ref); 297 298 if (!ref) 299 { 300 if (This->binding) IBinding_Release(This->binding); 301 if (This->stream) IStream_Release(This->stream); 302 if (This->body) GlobalFree(This->body); 303 heap_free(This); 304 } 305 306 return ref; 307 } 308 309 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, 310 DWORD reserved, IBinding *pbind) 311 { 312 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 313 314 TRACE("(%p)->(%d %p)\n", This, reserved, pbind); 315 316 if (!pbind) return E_INVALIDARG; 317 318 This->binding = pbind; 319 IBinding_AddRef(pbind); 320 321 httprequest_setreadystate(This->request, READYSTATE_LOADED); 322 323 return CreateStreamOnHGlobal(NULL, TRUE, &This->stream); 324 } 325 326 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pPriority) 327 { 328 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 329 330 TRACE("(%p)->(%p)\n", This, pPriority); 331 332 return E_NOTIMPL; 333 } 334 335 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved) 336 { 337 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 338 339 TRACE("(%p)->(%d)\n", This, reserved); 340 341 return E_NOTIMPL; 342 } 343 344 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, 345 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) 346 { 347 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 348 349 TRACE("(%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, 350 debugstr_w(szStatusText)); 351 352 return S_OK; 353 } 354 355 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, 356 HRESULT hr, LPCWSTR error) 357 { 358 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 359 360 TRACE("(%p)->(0x%08x %s)\n", This, hr, debugstr_w(error)); 361 362 if (This->binding) 363 { 364 IBinding_Release(This->binding); 365 This->binding = NULL; 366 } 367 368 if (hr == S_OK) 369 { 370 BindStatusCallback_Detach(This->request->bsc); 371 This->request->bsc = This; 372 httprequest_setreadystate(This->request, READYSTATE_COMPLETE); 373 } 374 375 return S_OK; 376 } 377 378 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, 379 DWORD *bind_flags, BINDINFO *pbindinfo) 380 { 381 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 382 383 TRACE("(%p)->(%p %p)\n", This, bind_flags, pbindinfo); 384 385 *bind_flags = 0; 386 if (This->request->async) *bind_flags |= BINDF_ASYNCHRONOUS; 387 388 if (This->request->verb != BINDVERB_GET && This->body) 389 { 390 pbindinfo->stgmedData.tymed = TYMED_HGLOBAL; 391 pbindinfo->stgmedData.u.hGlobal = This->body; 392 pbindinfo->cbstgmedData = GlobalSize(This->body); 393 /* callback owns passed body pointer */ 394 IBindStatusCallback_QueryInterface(iface, &IID_IUnknown, (void**)&pbindinfo->stgmedData.pUnkForRelease); 395 } 396 397 pbindinfo->dwBindVerb = This->request->verb; 398 if (This->request->verb == BINDVERB_CUSTOM) 399 { 400 pbindinfo->szCustomVerb = CoTaskMemAlloc(SysStringByteLen(This->request->custom)+sizeof(WCHAR)); 401 strcpyW(pbindinfo->szCustomVerb, This->request->custom); 402 } 403 404 return S_OK; 405 } 406 407 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, 408 DWORD flags, DWORD size, FORMATETC *format, STGMEDIUM *stgmed) 409 { 410 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 411 DWORD read, written; 412 BYTE buf[4096]; 413 HRESULT hr; 414 415 TRACE("(%p)->(%08x %d %p %p)\n", This, flags, size, format, stgmed); 416 417 do 418 { 419 hr = IStream_Read(stgmed->u.pstm, buf, sizeof(buf), &read); 420 if (hr != S_OK) break; 421 422 hr = IStream_Write(This->stream, buf, read, &written); 423 } while((hr == S_OK) && written != 0 && read != 0); 424 425 httprequest_setreadystate(This->request, READYSTATE_INTERACTIVE); 426 427 return S_OK; 428 } 429 430 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, 431 REFIID riid, IUnknown *punk) 432 { 433 BindStatusCallback *This = impl_from_IBindStatusCallback(iface); 434 435 FIXME("(%p)->(%s %p): stub\n", This, debugstr_guid(riid), punk); 436 437 return E_NOTIMPL; 438 } 439 440 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { 441 BindStatusCallback_QueryInterface, 442 BindStatusCallback_AddRef, 443 BindStatusCallback_Release, 444 BindStatusCallback_OnStartBinding, 445 BindStatusCallback_GetPriority, 446 BindStatusCallback_OnLowResource, 447 BindStatusCallback_OnProgress, 448 BindStatusCallback_OnStopBinding, 449 BindStatusCallback_GetBindInfo, 450 BindStatusCallback_OnDataAvailable, 451 BindStatusCallback_OnObjectAvailable 452 }; 453 454 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate *iface, 455 REFIID riid, void **ppv) 456 { 457 BindStatusCallback *This = impl_from_IHttpNegotiate(iface); 458 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv); 459 } 460 461 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate *iface) 462 { 463 BindStatusCallback *This = impl_from_IHttpNegotiate(iface); 464 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface); 465 } 466 467 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate *iface) 468 { 469 BindStatusCallback *This = impl_from_IHttpNegotiate(iface); 470 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface); 471 } 472 473 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *iface, 474 LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR *add_headers) 475 { 476 static const WCHAR content_type_utf8W[] = {'C','o','n','t','e','n','t','-','T','y','p','e',':',' ', 477 't','e','x','t','/','p','l','a','i','n',';','c','h','a','r','s','e','t','=','u','t','f','-','8','\r','\n',0}; 478 static const WCHAR refererW[] = {'R','e','f','e','r','e','r',':',' ',0}; 479 480 BindStatusCallback *This = impl_from_IHttpNegotiate(iface); 481 const struct httpheader *entry; 482 BSTR base_uri = NULL; 483 WCHAR *buff, *ptr; 484 int size = 0; 485 486 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(url), debugstr_w(headers), reserved, add_headers); 487 488 *add_headers = NULL; 489 490 if (This->request->use_utf8_content) 491 size = sizeof(content_type_utf8W); 492 493 if (!list_empty(&This->request->reqheaders)) 494 size += This->request->reqheader_size*sizeof(WCHAR); 495 496 if (This->request->base_uri) 497 { 498 IUri_GetRawUri(This->request->base_uri, &base_uri); 499 size += SysStringLen(base_uri)*sizeof(WCHAR) + sizeof(refererW) + sizeof(crlfW); 500 } 501 502 if (!size) 503 { 504 SysFreeString(base_uri); 505 return S_OK; 506 } 507 508 buff = CoTaskMemAlloc(size); 509 if (!buff) 510 { 511 SysFreeString(base_uri); 512 return E_OUTOFMEMORY; 513 } 514 515 ptr = buff; 516 if (This->request->use_utf8_content) 517 { 518 lstrcpyW(ptr, content_type_utf8W); 519 ptr += ARRAY_SIZE(content_type_utf8W) - 1; 520 } 521 522 if (base_uri) 523 { 524 strcpyW(ptr, refererW); 525 strcatW(ptr, base_uri); 526 strcatW(ptr, crlfW); 527 ptr += strlenW(refererW) + SysStringLen(base_uri) + strlenW(crlfW); 528 SysFreeString(base_uri); 529 } 530 531 /* user headers */ 532 LIST_FOR_EACH_ENTRY(entry, &This->request->reqheaders, struct httpheader, entry) 533 { 534 lstrcpyW(ptr, entry->header); 535 ptr += SysStringLen(entry->header); 536 537 lstrcpyW(ptr, colspaceW); 538 ptr += ARRAY_SIZE(colspaceW) - 1; 539 540 lstrcpyW(ptr, entry->value); 541 ptr += SysStringLen(entry->value); 542 543 lstrcpyW(ptr, crlfW); 544 ptr += ARRAY_SIZE(crlfW) - 1; 545 } 546 547 *add_headers = buff; 548 549 return S_OK; 550 } 551 552 static void add_response_header(httprequest *This, const WCHAR *data, int len) 553 { 554 struct httpheader *entry; 555 const WCHAR *ptr = data; 556 BSTR header, value; 557 558 while (*ptr) 559 { 560 if (*ptr == ':') 561 { 562 header = SysAllocStringLen(data, ptr-data); 563 /* skip leading spaces for a value */ 564 while (*++ptr == ' ') 565 ; 566 value = SysAllocStringLen(ptr, len-(ptr-data)); 567 break; 568 } 569 ptr++; 570 } 571 572 if (!*ptr) return; 573 574 /* new header */ 575 TRACE("got header %s:%s\n", debugstr_w(header), debugstr_w(value)); 576 577 entry = heap_alloc(sizeof(*entry)); 578 entry->header = header; 579 entry->value = value; 580 list_add_head(&This->respheaders, &entry->entry); 581 } 582 583 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD code, 584 LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders) 585 { 586 BindStatusCallback *This = impl_from_IHttpNegotiate(iface); 587 588 TRACE("(%p)->(%d %s %s %p)\n", This, code, debugstr_w(resp_headers), 589 debugstr_w(req_headers), add_reqheaders); 590 591 This->request->status = code; 592 /* store headers and status text */ 593 free_response_headers(This->request); 594 SysFreeString(This->request->status_text); 595 This->request->status_text = NULL; 596 if (resp_headers) 597 { 598 const WCHAR *ptr, *line, *status_text; 599 600 ptr = line = resp_headers; 601 602 /* skip HTTP-Version */ 603 ptr = strchrW(ptr, ' '); 604 if (ptr) 605 { 606 /* skip Status-Code */ 607 ptr = strchrW(++ptr, ' '); 608 if (ptr) 609 { 610 status_text = ++ptr; 611 /* now it supposed to end with CRLF */ 612 while (*ptr) 613 { 614 if (*ptr == '\r' && *(ptr+1) == '\n') 615 { 616 line = ptr + 2; 617 This->request->status_text = SysAllocStringLen(status_text, ptr-status_text); 618 TRACE("status text %s\n", debugstr_w(This->request->status_text)); 619 break; 620 } 621 ptr++; 622 } 623 } 624 } 625 626 /* store as unparsed string for now */ 627 This->request->raw_respheaders = SysAllocString(line); 628 } 629 630 return S_OK; 631 } 632 633 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl = { 634 BSCHttpNegotiate_QueryInterface, 635 BSCHttpNegotiate_AddRef, 636 BSCHttpNegotiate_Release, 637 BSCHttpNegotiate_BeginningTransaction, 638 BSCHttpNegotiate_OnResponse 639 }; 640 641 static HRESULT WINAPI Authenticate_QueryInterface(IAuthenticate *iface, 642 REFIID riid, void **ppv) 643 { 644 BindStatusCallback *This = impl_from_IAuthenticate(iface); 645 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv); 646 } 647 648 static ULONG WINAPI Authenticate_AddRef(IAuthenticate *iface) 649 { 650 BindStatusCallback *This = impl_from_IAuthenticate(iface); 651 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface); 652 } 653 654 static ULONG WINAPI Authenticate_Release(IAuthenticate *iface) 655 { 656 BindStatusCallback *This = impl_from_IAuthenticate(iface); 657 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface); 658 } 659 660 static HRESULT WINAPI Authenticate_Authenticate(IAuthenticate *iface, 661 HWND *hwnd, LPWSTR *username, LPWSTR *password) 662 { 663 BindStatusCallback *This = impl_from_IAuthenticate(iface); 664 httprequest *request = This->request; 665 666 TRACE("(%p)->(%p %p %p)\n", This, hwnd, username, password); 667 668 if (request->user && *request->user) 669 { 670 if (hwnd) *hwnd = NULL; 671 *username = CoTaskMemAlloc(SysStringByteLen(request->user)+sizeof(WCHAR)); 672 *password = CoTaskMemAlloc(SysStringByteLen(request->password)+sizeof(WCHAR)); 673 if (!*username || !*password) 674 { 675 CoTaskMemFree(*username); 676 CoTaskMemFree(*password); 677 return E_OUTOFMEMORY; 678 } 679 680 memcpy(*username, request->user, SysStringByteLen(request->user)+sizeof(WCHAR)); 681 memcpy(*password, request->password, SysStringByteLen(request->password)+sizeof(WCHAR)); 682 } 683 684 return S_OK; 685 } 686 687 static const IAuthenticateVtbl AuthenticateVtbl = { 688 Authenticate_QueryInterface, 689 Authenticate_AddRef, 690 Authenticate_Release, 691 Authenticate_Authenticate 692 }; 693 694 static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback **obj, const VARIANT *body) 695 { 696 BindStatusCallback *bsc; 697 IBindCtx *pbc; 698 HRESULT hr; 699 int size; 700 701 hr = CreateBindCtx(0, &pbc); 702 if (hr != S_OK) return hr; 703 704 bsc = heap_alloc(sizeof(*bsc)); 705 if (!bsc) 706 { 707 IBindCtx_Release(pbc); 708 return E_OUTOFMEMORY; 709 } 710 711 bsc->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl; 712 bsc->IHttpNegotiate_iface.lpVtbl = &BSCHttpNegotiateVtbl; 713 bsc->IAuthenticate_iface.lpVtbl = &AuthenticateVtbl; 714 bsc->ref = 1; 715 bsc->request = This; 716 bsc->binding = NULL; 717 bsc->stream = NULL; 718 bsc->body = NULL; 719 720 TRACE("(%p)->(%p)\n", This, bsc); 721 722 This->use_utf8_content = FALSE; 723 724 if (This->verb != BINDVERB_GET) 725 { 726 void *send_data, *ptr; 727 SAFEARRAY *sa = NULL; 728 729 if (V_VT(body) == (VT_VARIANT|VT_BYREF)) 730 body = V_VARIANTREF(body); 731 732 switch (V_VT(body)) 733 { 734 case VT_BSTR: 735 { 736 int len = SysStringLen(V_BSTR(body)); 737 const WCHAR *str = V_BSTR(body); 738 UINT i, cp = CP_ACP; 739 740 for (i = 0; i < len; i++) 741 { 742 if (str[i] > 127) 743 { 744 cp = CP_UTF8; 745 break; 746 } 747 } 748 749 size = WideCharToMultiByte(cp, 0, str, len, NULL, 0, NULL, NULL); 750 if (!(ptr = heap_alloc(size))) 751 { 752 heap_free(bsc); 753 return E_OUTOFMEMORY; 754 } 755 WideCharToMultiByte(cp, 0, str, len, ptr, size, NULL, NULL); 756 if (cp == CP_UTF8) This->use_utf8_content = TRUE; 757 break; 758 } 759 case VT_ARRAY|VT_UI1: 760 { 761 sa = V_ARRAY(body); 762 if ((hr = SafeArrayAccessData(sa, &ptr)) != S_OK) 763 { 764 heap_free(bsc); 765 return hr; 766 } 767 if ((hr = SafeArrayGetUBound(sa, 1, &size)) != S_OK) 768 { 769 SafeArrayUnaccessData(sa); 770 heap_free(bsc); 771 return hr; 772 } 773 size++; 774 break; 775 } 776 default: 777 FIXME("unsupported body data type %d\n", V_VT(body)); 778 /* fall through */ 779 case VT_EMPTY: 780 case VT_ERROR: 781 case VT_NULL: 782 ptr = NULL; 783 size = 0; 784 break; 785 } 786 787 if (size) 788 { 789 bsc->body = GlobalAlloc(GMEM_FIXED, size); 790 if (!bsc->body) 791 { 792 if (V_VT(body) == VT_BSTR) 793 heap_free(ptr); 794 else if (V_VT(body) == (VT_ARRAY|VT_UI1)) 795 SafeArrayUnaccessData(sa); 796 797 heap_free(bsc); 798 return E_OUTOFMEMORY; 799 } 800 801 send_data = GlobalLock(bsc->body); 802 memcpy(send_data, ptr, size); 803 GlobalUnlock(bsc->body); 804 } 805 806 if (V_VT(body) == VT_BSTR) 807 heap_free(ptr); 808 else if (V_VT(body) == (VT_ARRAY|VT_UI1)) 809 SafeArrayUnaccessData(sa); 810 } 811 812 hr = RegisterBindStatusCallback(pbc, &bsc->IBindStatusCallback_iface, NULL, 0); 813 if (hr == S_OK) 814 { 815 IMoniker *moniker; 816 817 hr = CreateURLMonikerEx2(NULL, This->uri, &moniker, URL_MK_UNIFORM); 818 if (hr == S_OK) 819 { 820 IStream *stream; 821 822 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (void**)&stream); 823 IMoniker_Release(moniker); 824 if (stream) IStream_Release(stream); 825 } 826 IBindCtx_Release(pbc); 827 } 828 829 if (FAILED(hr)) 830 { 831 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface); 832 bsc = NULL; 833 } 834 835 *obj = bsc; 836 return hr; 837 } 838 839 static HRESULT verify_uri(httprequest *This, IUri *uri) 840 { 841 DWORD scheme, base_scheme; 842 BSTR host, base_host; 843 HRESULT hr; 844 845 if(!(This->safeopt & INTERFACESAFE_FOR_UNTRUSTED_DATA)) 846 return S_OK; 847 848 if(!This->base_uri) 849 return E_ACCESSDENIED; 850 851 hr = IUri_GetScheme(uri, &scheme); 852 if(FAILED(hr)) 853 return hr; 854 855 hr = IUri_GetScheme(This->base_uri, &base_scheme); 856 if(FAILED(hr)) 857 return hr; 858 859 if(scheme != base_scheme) { 860 WARN("Schemes don't match\n"); 861 return E_ACCESSDENIED; 862 } 863 864 if(scheme == INTERNET_SCHEME_UNKNOWN) { 865 FIXME("Unknown scheme\n"); 866 return E_ACCESSDENIED; 867 } 868 869 hr = IUri_GetHost(uri, &host); 870 if(FAILED(hr)) 871 return hr; 872 873 hr = IUri_GetHost(This->base_uri, &base_host); 874 if(SUCCEEDED(hr)) { 875 if(strcmpiW(host, base_host)) { 876 WARN("Hosts don't match\n"); 877 hr = E_ACCESSDENIED; 878 } 879 SysFreeString(base_host); 880 } 881 882 SysFreeString(host); 883 return hr; 884 } 885 886 static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url, 887 VARIANT async, VARIANT user, VARIANT password) 888 { 889 static const WCHAR MethodHeadW[] = {'H','E','A','D',0}; 890 static const WCHAR MethodGetW[] = {'G','E','T',0}; 891 static const WCHAR MethodPutW[] = {'P','U','T',0}; 892 static const WCHAR MethodPostW[] = {'P','O','S','T',0}; 893 static const WCHAR MethodDeleteW[] = {'D','E','L','E','T','E',0}; 894 static const WCHAR MethodPropFindW[] = {'P','R','O','P','F','I','N','D',0}; 895 VARIANT str, is_async; 896 IUri *uri; 897 HRESULT hr; 898 899 if (!method || !url) return E_INVALIDARG; 900 901 /* free previously set data */ 902 if(This->uri) { 903 IUri_Release(This->uri); 904 This->uri = NULL; 905 } 906 907 SysFreeString(This->user); 908 SysFreeString(This->password); 909 This->user = This->password = NULL; 910 free_request_headers(This); 911 912 if (!strcmpiW(method, MethodGetW)) 913 { 914 This->verb = BINDVERB_GET; 915 } 916 else if (!strcmpiW(method, MethodPutW)) 917 { 918 This->verb = BINDVERB_PUT; 919 } 920 else if (!strcmpiW(method, MethodPostW)) 921 { 922 This->verb = BINDVERB_POST; 923 } 924 else if (!strcmpiW(method, MethodDeleteW) || 925 !strcmpiW(method, MethodHeadW) || 926 !strcmpiW(method, MethodPropFindW)) 927 { 928 This->verb = BINDVERB_CUSTOM; 929 SysReAllocString(&This->custom, method); 930 } 931 else 932 { 933 FIXME("unsupported request type %s\n", debugstr_w(method)); 934 This->verb = -1; 935 return E_FAIL; 936 } 937 938 if(This->base_uri) 939 hr = CoInternetCombineUrlEx(This->base_uri, url, 0, &uri, 0); 940 else 941 hr = CreateUri(url, 0, 0, &uri); 942 if(FAILED(hr)) { 943 WARN("Could not create IUri object: %08x\n", hr); 944 return hr; 945 } 946 947 hr = verify_uri(This, uri); 948 if(FAILED(hr)) { 949 IUri_Release(uri); 950 return hr; 951 } 952 953 VariantInit(&str); 954 hr = VariantChangeType(&str, &user, 0, VT_BSTR); 955 if (hr == S_OK) 956 This->user = V_BSTR(&str); 957 958 VariantInit(&str); 959 hr = VariantChangeType(&str, &password, 0, VT_BSTR); 960 if (hr == S_OK) 961 This->password = V_BSTR(&str); 962 963 /* add authentication info */ 964 if (This->user && *This->user) 965 { 966 IUriBuilder *builder; 967 968 hr = CreateIUriBuilder(uri, 0, 0, &builder); 969 if (hr == S_OK) 970 { 971 IUri *full_uri; 972 973 IUriBuilder_SetUserName(builder, This->user); 974 IUriBuilder_SetPassword(builder, This->password); 975 hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &full_uri); 976 if (hr == S_OK) 977 { 978 IUri_Release(uri); 979 uri = full_uri; 980 } 981 else 982 WARN("failed to create modified uri, 0x%08x\n", hr); 983 IUriBuilder_Release(builder); 984 } 985 else 986 WARN("IUriBuilder creation failed, 0x%08x\n", hr); 987 } 988 989 This->uri = uri; 990 991 VariantInit(&is_async); 992 hr = VariantChangeType(&is_async, &async, 0, VT_BOOL); 993 This->async = hr == S_OK && V_BOOL(&is_async); 994 995 httprequest_setreadystate(This, READYSTATE_LOADING); 996 997 return S_OK; 998 } 999 1000 static HRESULT httprequest_setRequestHeader(httprequest *This, BSTR header, BSTR value) 1001 { 1002 struct httpheader *entry; 1003 1004 if (!header || !*header) return E_INVALIDARG; 1005 if (This->state != READYSTATE_LOADING) return E_FAIL; 1006 if (!value) return E_INVALIDARG; 1007 1008 /* replace existing header value if already added */ 1009 LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct httpheader, entry) 1010 { 1011 if (lstrcmpW(entry->header, header) == 0) 1012 { 1013 LONG length = SysStringLen(entry->value); 1014 HRESULT hr; 1015 1016 hr = SysReAllocString(&entry->value, value) ? S_OK : E_OUTOFMEMORY; 1017 1018 if (hr == S_OK) 1019 This->reqheader_size += (SysStringLen(entry->value) - length); 1020 1021 return hr; 1022 } 1023 } 1024 1025 entry = heap_alloc(sizeof(*entry)); 1026 if (!entry) return E_OUTOFMEMORY; 1027 1028 /* new header */ 1029 entry->header = SysAllocString(header); 1030 entry->value = SysAllocString(value); 1031 1032 /* header length including null terminator */ 1033 This->reqheader_size += SysStringLen(entry->header) + ARRAY_SIZE(colspaceW) + 1034 SysStringLen(entry->value) + ARRAY_SIZE(crlfW) - 1; 1035 1036 list_add_head(&This->reqheaders, &entry->entry); 1037 1038 return S_OK; 1039 } 1040 1041 static HRESULT httprequest_getResponseHeader(httprequest *This, BSTR header, BSTR *value) 1042 { 1043 struct httpheader *entry; 1044 1045 if (!header) return E_INVALIDARG; 1046 if (!value) return E_POINTER; 1047 1048 if (This->raw_respheaders && list_empty(&This->respheaders)) 1049 { 1050 WCHAR *ptr, *line; 1051 1052 ptr = line = This->raw_respheaders; 1053 while (*ptr) 1054 { 1055 if (*ptr == '\r' && *(ptr+1) == '\n') 1056 { 1057 add_response_header(This, line, ptr-line); 1058 ptr++; line = ++ptr; 1059 continue; 1060 } 1061 ptr++; 1062 } 1063 } 1064 1065 LIST_FOR_EACH_ENTRY(entry, &This->respheaders, struct httpheader, entry) 1066 { 1067 if (!strcmpiW(entry->header, header)) 1068 { 1069 *value = SysAllocString(entry->value); 1070 TRACE("header value %s\n", debugstr_w(*value)); 1071 return S_OK; 1072 } 1073 } 1074 1075 return S_FALSE; 1076 } 1077 1078 static HRESULT httprequest_getAllResponseHeaders(httprequest *This, BSTR *respheaders) 1079 { 1080 if (!respheaders) return E_POINTER; 1081 1082 *respheaders = SysAllocString(This->raw_respheaders); 1083 1084 return S_OK; 1085 } 1086 1087 static HRESULT httprequest_send(httprequest *This, VARIANT body) 1088 { 1089 BindStatusCallback *bsc = NULL; 1090 HRESULT hr; 1091 1092 if (This->state != READYSTATE_LOADING) return E_FAIL; 1093 1094 hr = BindStatusCallback_create(This, &bsc, &body); 1095 if (FAILED(hr)) 1096 /* success path to detach it is OnStopBinding call */ 1097 BindStatusCallback_Detach(bsc); 1098 1099 return hr; 1100 } 1101 1102 static HRESULT httprequest_abort(httprequest *This) 1103 { 1104 BindStatusCallback_Detach(This->bsc); 1105 1106 httprequest_setreadystate(This, READYSTATE_UNINITIALIZED); 1107 1108 return S_OK; 1109 } 1110 1111 static HRESULT httprequest_get_status(httprequest *This, LONG *status) 1112 { 1113 if (!status) return E_POINTER; 1114 1115 *status = This->status; 1116 1117 return This->state == READYSTATE_COMPLETE ? S_OK : E_FAIL; 1118 } 1119 1120 static HRESULT httprequest_get_statusText(httprequest *This, BSTR *status) 1121 { 1122 if (!status) return E_POINTER; 1123 if (This->state != READYSTATE_COMPLETE) return E_FAIL; 1124 1125 *status = SysAllocString(This->status_text); 1126 1127 return S_OK; 1128 } 1129 1130 static HRESULT httprequest_get_responseText(httprequest *This, BSTR *body) 1131 { 1132 HGLOBAL hglobal; 1133 HRESULT hr; 1134 1135 if (!body) return E_POINTER; 1136 if (This->state != READYSTATE_COMPLETE) return E_FAIL; 1137 1138 hr = GetHGlobalFromStream(This->bsc->stream, &hglobal); 1139 if (hr == S_OK) 1140 { 1141 xmlChar *ptr = GlobalLock(hglobal); 1142 DWORD size = GlobalSize(hglobal); 1143 xmlCharEncoding encoding = XML_CHAR_ENCODING_UTF8; 1144 1145 /* try to determine data encoding */ 1146 if (size >= 4) 1147 { 1148 encoding = xmlDetectCharEncoding(ptr, 4); 1149 TRACE("detected encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding))); 1150 if ( encoding != XML_CHAR_ENCODING_UTF8 && 1151 encoding != XML_CHAR_ENCODING_UTF16LE && 1152 encoding != XML_CHAR_ENCODING_NONE ) 1153 { 1154 FIXME("unsupported encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding))); 1155 GlobalUnlock(hglobal); 1156 return E_FAIL; 1157 } 1158 } 1159 1160 /* without BOM assume UTF-8 */ 1161 if (encoding == XML_CHAR_ENCODING_UTF8 || 1162 encoding == XML_CHAR_ENCODING_NONE ) 1163 { 1164 DWORD length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)ptr, size, NULL, 0); 1165 1166 *body = SysAllocStringLen(NULL, length); 1167 if (*body) 1168 MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)ptr, size, *body, length); 1169 } 1170 else 1171 *body = SysAllocStringByteLen((LPCSTR)ptr, size); 1172 1173 if (!*body) hr = E_OUTOFMEMORY; 1174 GlobalUnlock(hglobal); 1175 } 1176 1177 return hr; 1178 } 1179 1180 static HRESULT httprequest_get_responseXML(httprequest *This, IDispatch **body) 1181 { 1182 IXMLDOMDocument3 *doc; 1183 HRESULT hr; 1184 BSTR str; 1185 1186 if (!body) return E_INVALIDARG; 1187 if (This->state != READYSTATE_COMPLETE) return E_FAIL; 1188 1189 hr = DOMDocument_create(MSXML_DEFAULT, (void**)&doc); 1190 if (hr != S_OK) return hr; 1191 1192 hr = httprequest_get_responseText(This, &str); 1193 if (hr == S_OK) 1194 { 1195 VARIANT_BOOL ok; 1196 1197 hr = IXMLDOMDocument3_loadXML(doc, str, &ok); 1198 SysFreeString(str); 1199 } 1200 1201 IXMLDOMDocument3_QueryInterface(doc, &IID_IDispatch, (void**)body); 1202 IXMLDOMDocument3_Release(doc); 1203 1204 return hr; 1205 } 1206 1207 static HRESULT httprequest_get_responseBody(httprequest *This, VARIANT *body) 1208 { 1209 HGLOBAL hglobal; 1210 HRESULT hr; 1211 1212 if (!body) return E_INVALIDARG; 1213 V_VT(body) = VT_EMPTY; 1214 1215 if (This->state != READYSTATE_COMPLETE) return E_PENDING; 1216 1217 hr = GetHGlobalFromStream(This->bsc->stream, &hglobal); 1218 if (hr == S_OK) 1219 { 1220 void *ptr = GlobalLock(hglobal); 1221 DWORD size = GlobalSize(hglobal); 1222 1223 SAFEARRAYBOUND bound; 1224 SAFEARRAY *array; 1225 1226 bound.lLbound = 0; 1227 bound.cElements = size; 1228 array = SafeArrayCreate(VT_UI1, 1, &bound); 1229 1230 if (array) 1231 { 1232 void *dest; 1233 1234 V_VT(body) = VT_ARRAY | VT_UI1; 1235 V_ARRAY(body) = array; 1236 1237 hr = SafeArrayAccessData(array, &dest); 1238 if (hr == S_OK) 1239 { 1240 memcpy(dest, ptr, size); 1241 SafeArrayUnaccessData(array); 1242 } 1243 else 1244 { 1245 VariantClear(body); 1246 } 1247 } 1248 else 1249 hr = E_FAIL; 1250 1251 GlobalUnlock(hglobal); 1252 } 1253 1254 return hr; 1255 } 1256 1257 static HRESULT httprequest_get_responseStream(httprequest *This, VARIANT *body) 1258 { 1259 LARGE_INTEGER move; 1260 IStream *stream; 1261 HRESULT hr; 1262 1263 if (!body) return E_INVALIDARG; 1264 V_VT(body) = VT_EMPTY; 1265 1266 if (This->state != READYSTATE_COMPLETE) return E_PENDING; 1267 1268 hr = IStream_Clone(This->bsc->stream, &stream); 1269 1270 move.QuadPart = 0; 1271 IStream_Seek(stream, move, STREAM_SEEK_SET, NULL); 1272 1273 V_VT(body) = VT_UNKNOWN; 1274 V_UNKNOWN(body) = (IUnknown*)stream; 1275 1276 return hr; 1277 } 1278 1279 static HRESULT httprequest_get_readyState(httprequest *This, LONG *state) 1280 { 1281 if (!state) return E_POINTER; 1282 1283 *state = This->state; 1284 return S_OK; 1285 } 1286 1287 static HRESULT httprequest_put_onreadystatechange(httprequest *This, IDispatch *sink) 1288 { 1289 if (This->sink) IDispatch_Release(This->sink); 1290 if ((This->sink = sink)) IDispatch_AddRef(This->sink); 1291 1292 return S_OK; 1293 } 1294 1295 static void httprequest_release(httprequest *This) 1296 { 1297 if (This->site) 1298 IUnknown_Release( This->site ); 1299 if (This->uri) 1300 IUri_Release(This->uri); 1301 if (This->base_uri) 1302 IUri_Release(This->base_uri); 1303 1304 SysFreeString(This->custom); 1305 SysFreeString(This->user); 1306 SysFreeString(This->password); 1307 1308 /* cleanup headers lists */ 1309 free_request_headers(This); 1310 free_response_headers(This); 1311 SysFreeString(This->status_text); 1312 1313 /* detach callback object */ 1314 BindStatusCallback_Detach(This->bsc); 1315 1316 if (This->sink) IDispatch_Release(This->sink); 1317 } 1318 1319 static HRESULT WINAPI XMLHTTPRequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject) 1320 { 1321 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1322 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); 1323 1324 if ( IsEqualGUID( riid, &IID_IXMLHTTPRequest) || 1325 IsEqualGUID( riid, &IID_IDispatch) || 1326 IsEqualGUID( riid, &IID_IUnknown) ) 1327 { 1328 *ppvObject = iface; 1329 } 1330 else if (IsEqualGUID(&IID_IObjectWithSite, riid)) 1331 { 1332 *ppvObject = &This->IObjectWithSite_iface; 1333 } 1334 else if (IsEqualGUID(&IID_IObjectSafety, riid)) 1335 { 1336 *ppvObject = &This->IObjectSafety_iface; 1337 } 1338 else if (IsEqualGUID(&IID_ISupportErrorInfo, riid)) 1339 { 1340 *ppvObject = &This->ISupportErrorInfo_iface; 1341 } 1342 else 1343 { 1344 TRACE("Unsupported interface %s\n", debugstr_guid(riid)); 1345 *ppvObject = NULL; 1346 return E_NOINTERFACE; 1347 } 1348 1349 IUnknown_AddRef((IUnknown *)*ppvObject); 1350 1351 return S_OK; 1352 } 1353 1354 static ULONG WINAPI XMLHTTPRequest_AddRef(IXMLHTTPRequest *iface) 1355 { 1356 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1357 ULONG ref = InterlockedIncrement( &This->ref ); 1358 TRACE("(%p)->(%u)\n", This, ref ); 1359 return ref; 1360 } 1361 1362 static ULONG WINAPI XMLHTTPRequest_Release(IXMLHTTPRequest *iface) 1363 { 1364 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1365 ULONG ref = InterlockedDecrement( &This->ref ); 1366 1367 TRACE("(%p)->(%u)\n", This, ref ); 1368 1369 if ( ref == 0 ) 1370 { 1371 httprequest_release( This ); 1372 heap_free( This ); 1373 } 1374 1375 return ref; 1376 } 1377 1378 static HRESULT WINAPI XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest *iface, UINT *pctinfo) 1379 { 1380 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1381 1382 TRACE("(%p)->(%p)\n", This, pctinfo); 1383 1384 *pctinfo = 1; 1385 1386 return S_OK; 1387 } 1388 1389 static HRESULT WINAPI XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest *iface, UINT iTInfo, 1390 LCID lcid, ITypeInfo **ppTInfo) 1391 { 1392 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1393 1394 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 1395 1396 return get_typeinfo(IXMLHTTPRequest_tid, ppTInfo); 1397 } 1398 1399 static HRESULT WINAPI XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest *iface, REFIID riid, 1400 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) 1401 { 1402 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1403 ITypeInfo *typeinfo; 1404 HRESULT hr; 1405 1406 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 1407 lcid, rgDispId); 1408 1409 if(!rgszNames || cNames == 0 || !rgDispId) 1410 return E_INVALIDARG; 1411 1412 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo); 1413 if(SUCCEEDED(hr)) 1414 { 1415 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); 1416 ITypeInfo_Release(typeinfo); 1417 } 1418 1419 return hr; 1420 } 1421 1422 static HRESULT WINAPI XMLHTTPRequest_Invoke(IXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid, 1423 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 1424 EXCEPINFO *pExcepInfo, UINT *puArgErr) 1425 { 1426 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1427 ITypeInfo *typeinfo; 1428 HRESULT hr; 1429 1430 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 1431 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 1432 1433 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo); 1434 if(SUCCEEDED(hr)) 1435 { 1436 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLHTTPRequest_iface, dispIdMember, wFlags, 1437 pDispParams, pVarResult, pExcepInfo, puArgErr); 1438 ITypeInfo_Release(typeinfo); 1439 } 1440 1441 return hr; 1442 } 1443 1444 static HRESULT WINAPI XMLHTTPRequest_open(IXMLHTTPRequest *iface, BSTR method, BSTR url, 1445 VARIANT async, VARIANT user, VARIANT password) 1446 { 1447 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1448 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(method), debugstr_w(url), 1449 debugstr_variant(&async)); 1450 return httprequest_open(This, method, url, async, user, password); 1451 } 1452 1453 static HRESULT WINAPI XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR header, BSTR value) 1454 { 1455 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1456 TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value)); 1457 return httprequest_setRequestHeader(This, header, value); 1458 } 1459 1460 static HRESULT WINAPI XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR header, BSTR *value) 1461 { 1462 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1463 TRACE("(%p)->(%s %p)\n", This, debugstr_w(header), value); 1464 return httprequest_getResponseHeader(This, header, value); 1465 } 1466 1467 static HRESULT WINAPI XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *respheaders) 1468 { 1469 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1470 TRACE("(%p)->(%p)\n", This, respheaders); 1471 return httprequest_getAllResponseHeaders(This, respheaders); 1472 } 1473 1474 static HRESULT WINAPI XMLHTTPRequest_send(IXMLHTTPRequest *iface, VARIANT body) 1475 { 1476 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1477 TRACE("(%p)->(%s)\n", This, debugstr_variant(&body)); 1478 return httprequest_send(This, body); 1479 } 1480 1481 static HRESULT WINAPI XMLHTTPRequest_abort(IXMLHTTPRequest *iface) 1482 { 1483 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1484 TRACE("(%p)\n", This); 1485 return httprequest_abort(This); 1486 } 1487 1488 static HRESULT WINAPI XMLHTTPRequest_get_status(IXMLHTTPRequest *iface, LONG *status) 1489 { 1490 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1491 TRACE("(%p)->(%p)\n", This, status); 1492 return httprequest_get_status(This, status); 1493 } 1494 1495 static HRESULT WINAPI XMLHTTPRequest_get_statusText(IXMLHTTPRequest *iface, BSTR *status) 1496 { 1497 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1498 TRACE("(%p)->(%p)\n", This, status); 1499 return httprequest_get_statusText(This, status); 1500 } 1501 1502 static HRESULT WINAPI XMLHTTPRequest_get_responseXML(IXMLHTTPRequest *iface, IDispatch **body) 1503 { 1504 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1505 TRACE("(%p)->(%p)\n", This, body); 1506 return httprequest_get_responseXML(This, body); 1507 } 1508 1509 static HRESULT WINAPI XMLHTTPRequest_get_responseText(IXMLHTTPRequest *iface, BSTR *body) 1510 { 1511 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1512 TRACE("(%p)->(%p)\n", This, body); 1513 return httprequest_get_responseText(This, body); 1514 } 1515 1516 static HRESULT WINAPI XMLHTTPRequest_get_responseBody(IXMLHTTPRequest *iface, VARIANT *body) 1517 { 1518 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1519 TRACE("(%p)->(%p)\n", This, body); 1520 return httprequest_get_responseBody(This, body); 1521 } 1522 1523 static HRESULT WINAPI XMLHTTPRequest_get_responseStream(IXMLHTTPRequest *iface, VARIANT *body) 1524 { 1525 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1526 TRACE("(%p)->(%p)\n", This, body); 1527 return httprequest_get_responseStream(This, body); 1528 } 1529 1530 static HRESULT WINAPI XMLHTTPRequest_get_readyState(IXMLHTTPRequest *iface, LONG *state) 1531 { 1532 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1533 TRACE("(%p)->(%p)\n", This, state); 1534 return httprequest_get_readyState(This, state); 1535 } 1536 1537 static HRESULT WINAPI XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *sink) 1538 { 1539 httprequest *This = impl_from_IXMLHTTPRequest( iface ); 1540 TRACE("(%p)->(%p)\n", This, sink); 1541 return httprequest_put_onreadystatechange(This, sink); 1542 } 1543 1544 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl = 1545 { 1546 XMLHTTPRequest_QueryInterface, 1547 XMLHTTPRequest_AddRef, 1548 XMLHTTPRequest_Release, 1549 XMLHTTPRequest_GetTypeInfoCount, 1550 XMLHTTPRequest_GetTypeInfo, 1551 XMLHTTPRequest_GetIDsOfNames, 1552 XMLHTTPRequest_Invoke, 1553 XMLHTTPRequest_open, 1554 XMLHTTPRequest_setRequestHeader, 1555 XMLHTTPRequest_getResponseHeader, 1556 XMLHTTPRequest_getAllResponseHeaders, 1557 XMLHTTPRequest_send, 1558 XMLHTTPRequest_abort, 1559 XMLHTTPRequest_get_status, 1560 XMLHTTPRequest_get_statusText, 1561 XMLHTTPRequest_get_responseXML, 1562 XMLHTTPRequest_get_responseText, 1563 XMLHTTPRequest_get_responseBody, 1564 XMLHTTPRequest_get_responseStream, 1565 XMLHTTPRequest_get_readyState, 1566 XMLHTTPRequest_put_onreadystatechange 1567 }; 1568 1569 /* IObjectWithSite */ 1570 static HRESULT WINAPI 1571 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject ) 1572 { 1573 httprequest *This = impl_from_IObjectWithSite(iface); 1574 return IXMLHTTPRequest_QueryInterface(&This->IXMLHTTPRequest_iface, riid, ppvObject); 1575 } 1576 1577 static ULONG WINAPI httprequest_ObjectWithSite_AddRef( IObjectWithSite* iface ) 1578 { 1579 httprequest *This = impl_from_IObjectWithSite(iface); 1580 return IXMLHTTPRequest_AddRef(&This->IXMLHTTPRequest_iface); 1581 } 1582 1583 static ULONG WINAPI httprequest_ObjectWithSite_Release( IObjectWithSite* iface ) 1584 { 1585 httprequest *This = impl_from_IObjectWithSite(iface); 1586 return IXMLHTTPRequest_Release(&This->IXMLHTTPRequest_iface); 1587 } 1588 1589 static HRESULT WINAPI httprequest_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite ) 1590 { 1591 httprequest *This = impl_from_IObjectWithSite(iface); 1592 1593 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite ); 1594 1595 if ( !This->site ) 1596 return E_FAIL; 1597 1598 return IUnknown_QueryInterface( This->site, iid, ppvSite ); 1599 } 1600 1601 static void get_base_uri(httprequest *This) 1602 { 1603 IServiceProvider *provider; 1604 IHTMLDocument2 *doc; 1605 IUri *uri; 1606 BSTR url; 1607 HRESULT hr; 1608 1609 hr = IUnknown_QueryInterface(This->site, &IID_IServiceProvider, (void**)&provider); 1610 if(FAILED(hr)) 1611 return; 1612 1613 hr = IServiceProvider_QueryService(provider, &SID_SContainerDispatch, &IID_IHTMLDocument2, (void**)&doc); 1614 if(FAILED(hr)) 1615 hr = IServiceProvider_QueryService(provider, &SID_SInternetHostSecurityManager, &IID_IHTMLDocument2, (void**)&doc); 1616 IServiceProvider_Release(provider); 1617 if(FAILED(hr)) 1618 return; 1619 1620 hr = IHTMLDocument2_get_URL(doc, &url); 1621 IHTMLDocument2_Release(doc); 1622 if(FAILED(hr) || !url || !*url) 1623 return; 1624 1625 TRACE("host url %s\n", debugstr_w(url)); 1626 1627 hr = CreateUri(url, 0, 0, &uri); 1628 SysFreeString(url); 1629 if(FAILED(hr)) 1630 return; 1631 1632 This->base_uri = uri; 1633 } 1634 1635 static HRESULT WINAPI httprequest_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk ) 1636 { 1637 httprequest *This = impl_from_IObjectWithSite(iface); 1638 1639 TRACE("(%p)->(%p)\n", This, punk); 1640 1641 if(This->site) 1642 IUnknown_Release( This->site ); 1643 if(This->base_uri) 1644 IUri_Release(This->base_uri); 1645 1646 This->site = punk; 1647 1648 if (punk) 1649 { 1650 IUnknown_AddRef( punk ); 1651 get_base_uri(This); 1652 } 1653 1654 return S_OK; 1655 } 1656 1657 static const IObjectWithSiteVtbl ObjectWithSiteVtbl = 1658 { 1659 httprequest_ObjectWithSite_QueryInterface, 1660 httprequest_ObjectWithSite_AddRef, 1661 httprequest_ObjectWithSite_Release, 1662 httprequest_ObjectWithSite_SetSite, 1663 httprequest_ObjectWithSite_GetSite 1664 }; 1665 1666 /* IObjectSafety */ 1667 static HRESULT WINAPI httprequest_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv) 1668 { 1669 httprequest *This = impl_from_IObjectSafety(iface); 1670 return IXMLHTTPRequest_QueryInterface(&This->IXMLHTTPRequest_iface, riid, ppv); 1671 } 1672 1673 static ULONG WINAPI httprequest_Safety_AddRef(IObjectSafety *iface) 1674 { 1675 httprequest *This = impl_from_IObjectSafety(iface); 1676 return IXMLHTTPRequest_AddRef(&This->IXMLHTTPRequest_iface); 1677 } 1678 1679 static ULONG WINAPI httprequest_Safety_Release(IObjectSafety *iface) 1680 { 1681 httprequest *This = impl_from_IObjectSafety(iface); 1682 return IXMLHTTPRequest_Release(&This->IXMLHTTPRequest_iface); 1683 } 1684 1685 static HRESULT WINAPI httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, 1686 DWORD *supported, DWORD *enabled) 1687 { 1688 httprequest *This = impl_from_IObjectSafety(iface); 1689 1690 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled); 1691 1692 if(!supported || !enabled) return E_POINTER; 1693 1694 *supported = safety_supported_options; 1695 *enabled = This->safeopt; 1696 1697 return S_OK; 1698 } 1699 1700 static HRESULT WINAPI httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid, 1701 DWORD mask, DWORD enabled) 1702 { 1703 httprequest *This = impl_from_IObjectSafety(iface); 1704 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled); 1705 1706 if ((mask & ~safety_supported_options)) 1707 return E_FAIL; 1708 1709 This->safeopt = (This->safeopt & ~mask) | (mask & enabled); 1710 1711 return S_OK; 1712 } 1713 1714 static const IObjectSafetyVtbl ObjectSafetyVtbl = { 1715 httprequest_Safety_QueryInterface, 1716 httprequest_Safety_AddRef, 1717 httprequest_Safety_Release, 1718 httprequest_Safety_GetInterfaceSafetyOptions, 1719 httprequest_Safety_SetInterfaceSafetyOptions 1720 }; 1721 1722 static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **obj) 1723 { 1724 httprequest *This = impl_from_ISupportErrorInfo(iface); 1725 return IXMLHTTPRequest_QueryInterface(&This->IXMLHTTPRequest_iface, riid, obj); 1726 } 1727 1728 static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface) 1729 { 1730 httprequest *This = impl_from_ISupportErrorInfo(iface); 1731 return IXMLHTTPRequest_AddRef(&This->IXMLHTTPRequest_iface); 1732 } 1733 1734 static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface) 1735 { 1736 httprequest *This = impl_from_ISupportErrorInfo(iface); 1737 return IXMLHTTPRequest_Release(&This->IXMLHTTPRequest_iface); 1738 } 1739 1740 static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid) 1741 { 1742 httprequest *This = impl_from_ISupportErrorInfo(iface); 1743 1744 FIXME("(%p)->(%s)\n", This, debugstr_guid(riid)); 1745 1746 return E_NOTIMPL; 1747 } 1748 1749 static const ISupportErrorInfoVtbl SupportErrorInfoVtbl = 1750 { 1751 SupportErrorInfo_QueryInterface, 1752 SupportErrorInfo_AddRef, 1753 SupportErrorInfo_Release, 1754 SupportErrorInfo_InterfaceSupportsErrorInfo, 1755 }; 1756 1757 /* IServerXMLHTTPRequest */ 1758 static HRESULT WINAPI ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest *iface, REFIID riid, void **obj) 1759 { 1760 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1761 1762 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); 1763 1764 if ( IsEqualGUID( riid, &IID_IServerXMLHTTPRequest) || 1765 IsEqualGUID( riid, &IID_IXMLHTTPRequest) || 1766 IsEqualGUID( riid, &IID_IDispatch) || 1767 IsEqualGUID( riid, &IID_IUnknown) ) 1768 { 1769 *obj = iface; 1770 } 1771 else if ( IsEqualGUID( riid, &IID_ISupportErrorInfo )) 1772 { 1773 *obj = &This->req.ISupportErrorInfo_iface; 1774 } 1775 else 1776 { 1777 TRACE("Unsupported interface %s\n", debugstr_guid(riid)); 1778 *obj = NULL; 1779 return E_NOINTERFACE; 1780 } 1781 1782 IUnknown_AddRef( (IUnknown *)*obj ); 1783 1784 return S_OK; 1785 } 1786 1787 static ULONG WINAPI ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest *iface) 1788 { 1789 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1790 ULONG ref = InterlockedIncrement( &This->req.ref ); 1791 TRACE("(%p)->(%u)\n", This, ref ); 1792 return ref; 1793 } 1794 1795 static ULONG WINAPI ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest *iface) 1796 { 1797 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1798 ULONG ref = InterlockedDecrement( &This->req.ref ); 1799 1800 TRACE("(%p)->(%u)\n", This, ref ); 1801 1802 if ( ref == 0 ) 1803 { 1804 httprequest_release( &This->req ); 1805 heap_free( This ); 1806 } 1807 1808 return ref; 1809 } 1810 1811 static HRESULT WINAPI ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest *iface, UINT *pctinfo) 1812 { 1813 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1814 1815 TRACE("(%p)->(%p)\n", This, pctinfo); 1816 *pctinfo = 1; 1817 1818 return S_OK; 1819 } 1820 1821 static HRESULT WINAPI ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest *iface, UINT iTInfo, 1822 LCID lcid, ITypeInfo **ppTInfo) 1823 { 1824 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1825 1826 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 1827 1828 return get_typeinfo(IServerXMLHTTPRequest_tid, ppTInfo); 1829 } 1830 1831 static HRESULT WINAPI ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest *iface, REFIID riid, 1832 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) 1833 { 1834 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1835 ITypeInfo *typeinfo; 1836 HRESULT hr; 1837 1838 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 1839 lcid, rgDispId); 1840 1841 if(!rgszNames || cNames == 0 || !rgDispId) 1842 return E_INVALIDARG; 1843 1844 hr = get_typeinfo(IServerXMLHTTPRequest_tid, &typeinfo); 1845 if(SUCCEEDED(hr)) 1846 { 1847 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); 1848 ITypeInfo_Release(typeinfo); 1849 } 1850 1851 return hr; 1852 } 1853 1854 static HRESULT WINAPI ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid, 1855 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 1856 EXCEPINFO *pExcepInfo, UINT *puArgErr) 1857 { 1858 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1859 ITypeInfo *typeinfo; 1860 HRESULT hr; 1861 1862 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 1863 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 1864 1865 hr = get_typeinfo(IServerXMLHTTPRequest_tid, &typeinfo); 1866 if(SUCCEEDED(hr)) 1867 { 1868 hr = ITypeInfo_Invoke(typeinfo, &This->IServerXMLHTTPRequest_iface, dispIdMember, wFlags, 1869 pDispParams, pVarResult, pExcepInfo, puArgErr); 1870 ITypeInfo_Release(typeinfo); 1871 } 1872 1873 return hr; 1874 } 1875 1876 static HRESULT WINAPI ServerXMLHTTPRequest_open(IServerXMLHTTPRequest *iface, BSTR method, BSTR url, 1877 VARIANT async, VARIANT user, VARIANT password) 1878 { 1879 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1880 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(method), debugstr_w(url), 1881 debugstr_variant(&async)); 1882 return httprequest_open(&This->req, method, url, async, user, password); 1883 } 1884 1885 static HRESULT WINAPI ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest *iface, BSTR header, BSTR value) 1886 { 1887 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1888 TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value)); 1889 return httprequest_setRequestHeader(&This->req, header, value); 1890 } 1891 1892 static HRESULT WINAPI ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest *iface, BSTR header, BSTR *value) 1893 { 1894 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1895 TRACE("(%p)->(%s %p)\n", This, debugstr_w(header), value); 1896 return httprequest_getResponseHeader(&This->req, header, value); 1897 } 1898 1899 static HRESULT WINAPI ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest *iface, BSTR *respheaders) 1900 { 1901 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1902 TRACE("(%p)->(%p)\n", This, respheaders); 1903 return httprequest_getAllResponseHeaders(&This->req, respheaders); 1904 } 1905 1906 static HRESULT WINAPI ServerXMLHTTPRequest_send(IServerXMLHTTPRequest *iface, VARIANT body) 1907 { 1908 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1909 TRACE("(%p)->(%s)\n", This, debugstr_variant(&body)); 1910 return httprequest_send(&This->req, body); 1911 } 1912 1913 static HRESULT WINAPI ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest *iface) 1914 { 1915 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1916 TRACE("(%p)\n", This); 1917 return httprequest_abort(&This->req); 1918 } 1919 1920 static HRESULT WINAPI ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest *iface, LONG *status) 1921 { 1922 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1923 TRACE("(%p)->(%p)\n", This, status); 1924 return httprequest_get_status(&This->req, status); 1925 } 1926 1927 static HRESULT WINAPI ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest *iface, BSTR *status) 1928 { 1929 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1930 TRACE("(%p)->(%p)\n", This, status); 1931 return httprequest_get_statusText(&This->req, status); 1932 } 1933 1934 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest *iface, IDispatch **body) 1935 { 1936 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1937 TRACE("(%p)->(%p)\n", This, body); 1938 return httprequest_get_responseXML(&This->req, body); 1939 } 1940 1941 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest *iface, BSTR *body) 1942 { 1943 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1944 TRACE("(%p)->(%p)\n", This, body); 1945 return httprequest_get_responseText(&This->req, body); 1946 } 1947 1948 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest *iface, VARIANT *body) 1949 { 1950 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1951 TRACE("(%p)->(%p)\n", This, body); 1952 return httprequest_get_responseBody(&This->req, body); 1953 } 1954 1955 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest *iface, VARIANT *body) 1956 { 1957 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1958 TRACE("(%p)->(%p)\n", This, body); 1959 return httprequest_get_responseStream(&This->req, body); 1960 } 1961 1962 static HRESULT WINAPI ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest *iface, LONG *state) 1963 { 1964 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1965 TRACE("(%p)->(%p)\n", This, state); 1966 return httprequest_get_readyState(&This->req, state); 1967 } 1968 1969 static HRESULT WINAPI ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest *iface, IDispatch *sink) 1970 { 1971 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1972 TRACE("(%p)->(%p)\n", This, sink); 1973 return httprequest_put_onreadystatechange(&This->req, sink); 1974 } 1975 1976 static HRESULT WINAPI ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest *iface, LONG resolveTimeout, LONG connectTimeout, 1977 LONG sendTimeout, LONG receiveTimeout) 1978 { 1979 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1980 FIXME("(%p)->(%d %d %d %d): stub\n", This, resolveTimeout, connectTimeout, sendTimeout, receiveTimeout); 1981 return S_OK; 1982 } 1983 1984 static HRESULT WINAPI ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest *iface, VARIANT timeout, VARIANT_BOOL *isSuccessful) 1985 { 1986 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1987 FIXME("(%p)->(%s %p): stub\n", This, debugstr_variant(&timeout), isSuccessful); 1988 return E_NOTIMPL; 1989 } 1990 1991 static HRESULT WINAPI ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest *iface, SERVERXMLHTTP_OPTION option, VARIANT *value) 1992 { 1993 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 1994 FIXME("(%p)->(%d %p): stub\n", This, option, value); 1995 return E_NOTIMPL; 1996 } 1997 1998 static HRESULT WINAPI ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest *iface, SERVERXMLHTTP_OPTION option, VARIANT value) 1999 { 2000 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface ); 2001 FIXME("(%p)->(%d %s): stub\n", This, option, debugstr_variant(&value)); 2002 return E_NOTIMPL; 2003 } 2004 2005 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl = 2006 { 2007 ServerXMLHTTPRequest_QueryInterface, 2008 ServerXMLHTTPRequest_AddRef, 2009 ServerXMLHTTPRequest_Release, 2010 ServerXMLHTTPRequest_GetTypeInfoCount, 2011 ServerXMLHTTPRequest_GetTypeInfo, 2012 ServerXMLHTTPRequest_GetIDsOfNames, 2013 ServerXMLHTTPRequest_Invoke, 2014 ServerXMLHTTPRequest_open, 2015 ServerXMLHTTPRequest_setRequestHeader, 2016 ServerXMLHTTPRequest_getResponseHeader, 2017 ServerXMLHTTPRequest_getAllResponseHeaders, 2018 ServerXMLHTTPRequest_send, 2019 ServerXMLHTTPRequest_abort, 2020 ServerXMLHTTPRequest_get_status, 2021 ServerXMLHTTPRequest_get_statusText, 2022 ServerXMLHTTPRequest_get_responseXML, 2023 ServerXMLHTTPRequest_get_responseText, 2024 ServerXMLHTTPRequest_get_responseBody, 2025 ServerXMLHTTPRequest_get_responseStream, 2026 ServerXMLHTTPRequest_get_readyState, 2027 ServerXMLHTTPRequest_put_onreadystatechange, 2028 ServerXMLHTTPRequest_setTimeouts, 2029 ServerXMLHTTPRequest_waitForResponse, 2030 ServerXMLHTTPRequest_getOption, 2031 ServerXMLHTTPRequest_setOption 2032 }; 2033 2034 static void init_httprequest(httprequest *req) 2035 { 2036 req->IXMLHTTPRequest_iface.lpVtbl = &XMLHTTPRequestVtbl; 2037 req->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl; 2038 req->IObjectSafety_iface.lpVtbl = &ObjectSafetyVtbl; 2039 req->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl; 2040 req->ref = 1; 2041 2042 req->async = FALSE; 2043 req->verb = -1; 2044 req->custom = NULL; 2045 req->uri = req->base_uri = NULL; 2046 req->user = req->password = NULL; 2047 2048 req->state = READYSTATE_UNINITIALIZED; 2049 req->sink = NULL; 2050 2051 req->bsc = NULL; 2052 req->status = 0; 2053 req->status_text = NULL; 2054 req->reqheader_size = 0; 2055 req->raw_respheaders = NULL; 2056 req->use_utf8_content = FALSE; 2057 2058 list_init(&req->reqheaders); 2059 list_init(&req->respheaders); 2060 2061 req->site = NULL; 2062 req->safeopt = 0; 2063 } 2064 2065 HRESULT XMLHTTPRequest_create(void **obj) 2066 { 2067 httprequest *req; 2068 2069 TRACE("(%p)\n", obj); 2070 2071 req = heap_alloc( sizeof (*req) ); 2072 if( !req ) 2073 return E_OUTOFMEMORY; 2074 2075 init_httprequest(req); 2076 *obj = &req->IXMLHTTPRequest_iface; 2077 2078 TRACE("returning iface %p\n", *obj); 2079 2080 return S_OK; 2081 } 2082 2083 HRESULT ServerXMLHTTP_create(void **obj) 2084 { 2085 serverhttp *req; 2086 2087 TRACE("(%p)\n", obj); 2088 2089 req = heap_alloc( sizeof (*req) ); 2090 if( !req ) 2091 return E_OUTOFMEMORY; 2092 2093 init_httprequest(&req->req); 2094 req->IServerXMLHTTPRequest_iface.lpVtbl = &ServerXMLHTTPRequestVtbl; 2095 2096 *obj = &req->IServerXMLHTTPRequest_iface; 2097 2098 TRACE("returning iface %p\n", *obj); 2099 2100 return S_OK; 2101 } 2102 2103 #else 2104 2105 HRESULT XMLHTTPRequest_create(void **ppObj) 2106 { 2107 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n" 2108 "libxml2 support was not present at compile time.\n"); 2109 return E_NOTIMPL; 2110 } 2111 2112 HRESULT ServerXMLHTTP_create(void **obj) 2113 { 2114 MESSAGE("This program tried to use a ServerXMLHTTP object, but\n" 2115 "libxml2 support was not present at compile time.\n"); 2116 return E_NOTIMPL; 2117 } 2118 2119 #endif 2120