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