* Sync up to trunk head (r65120).
[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 static const WCHAR refererW[] = {'R','e','f','e','r','e','r',':',' ',0};
437
438 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
439 const struct httpheader *entry;
440 BSTR base_uri = NULL;
441 WCHAR *buff, *ptr;
442 int size = 0;
443
444 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(url), debugstr_w(headers), reserved, add_headers);
445
446 *add_headers = NULL;
447
448 if (This->request->use_utf8_content)
449 size = sizeof(content_type_utf8W);
450
451 if (!list_empty(&This->request->reqheaders))
452 size += This->request->reqheader_size*sizeof(WCHAR);
453
454 if (This->request->base_uri)
455 {
456 IUri_GetRawUri(This->request->base_uri, &base_uri);
457 size += SysStringLen(base_uri)*sizeof(WCHAR) + sizeof(refererW) + sizeof(crlfW);
458 }
459
460 if (!size)
461 {
462 SysFreeString(base_uri);
463 return S_OK;
464 }
465
466 buff = CoTaskMemAlloc(size);
467 if (!buff)
468 {
469 SysFreeString(base_uri);
470 return E_OUTOFMEMORY;
471 }
472
473 ptr = buff;
474 if (This->request->use_utf8_content)
475 {
476 lstrcpyW(ptr, content_type_utf8W);
477 ptr += sizeof(content_type_utf8W)/sizeof(WCHAR)-1;
478 }
479
480 if (base_uri)
481 {
482 strcpyW(ptr, refererW);
483 strcatW(ptr, base_uri);
484 strcatW(ptr, crlfW);
485 ptr += strlenW(refererW) + SysStringLen(base_uri) + strlenW(crlfW);
486 SysFreeString(base_uri);
487 }
488
489 /* user headers */
490 LIST_FOR_EACH_ENTRY(entry, &This->request->reqheaders, struct httpheader, entry)
491 {
492 lstrcpyW(ptr, entry->header);
493 ptr += SysStringLen(entry->header);
494
495 lstrcpyW(ptr, colspaceW);
496 ptr += sizeof(colspaceW)/sizeof(WCHAR)-1;
497
498 lstrcpyW(ptr, entry->value);
499 ptr += SysStringLen(entry->value);
500
501 lstrcpyW(ptr, crlfW);
502 ptr += sizeof(crlfW)/sizeof(WCHAR)-1;
503 }
504
505 *add_headers = buff;
506
507 return S_OK;
508 }
509
510 static void add_response_header(httprequest *This, const WCHAR *data, int len)
511 {
512 struct httpheader *entry;
513 const WCHAR *ptr = data;
514 BSTR header, value;
515
516 while (*ptr)
517 {
518 if (*ptr == ':')
519 {
520 header = SysAllocStringLen(data, ptr-data);
521 /* skip leading spaces for a value */
522 while (*++ptr == ' ')
523 ;
524 value = SysAllocStringLen(ptr, len-(ptr-data));
525 break;
526 }
527 ptr++;
528 }
529
530 if (!*ptr) return;
531
532 /* new header */
533 TRACE("got header %s:%s\n", debugstr_w(header), debugstr_w(value));
534
535 entry = heap_alloc(sizeof(*entry));
536 entry->header = header;
537 entry->value = value;
538 list_add_head(&This->respheaders, &entry->entry);
539 }
540
541 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD code,
542 LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders)
543 {
544 BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
545
546 TRACE("(%p)->(%d %s %s %p)\n", This, code, debugstr_w(resp_headers),
547 debugstr_w(req_headers), add_reqheaders);
548
549 This->request->status = code;
550 /* store headers and status text */
551 free_response_headers(This->request);
552 SysFreeString(This->request->status_text);
553 This->request->status_text = NULL;
554 if (resp_headers)
555 {
556 const WCHAR *ptr, *line, *status_text;
557
558 ptr = line = resp_headers;
559
560 /* skip HTTP-Version */
561 ptr = strchrW(ptr, ' ');
562 if (ptr)
563 {
564 /* skip Status-Code */
565 ptr = strchrW(++ptr, ' ');
566 if (ptr)
567 {
568 status_text = ++ptr;
569 /* now it supposed to end with CRLF */
570 while (*ptr)
571 {
572 if (*ptr == '\r' && *(ptr+1) == '\n')
573 {
574 line = ptr + 2;
575 This->request->status_text = SysAllocStringLen(status_text, ptr-status_text);
576 TRACE("status text %s\n", debugstr_w(This->request->status_text));
577 break;
578 }
579 ptr++;
580 }
581 }
582 }
583
584 /* store as unparsed string for now */
585 This->request->raw_respheaders = SysAllocString(line);
586 }
587
588 return S_OK;
589 }
590
591 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl = {
592 BSCHttpNegotiate_QueryInterface,
593 BSCHttpNegotiate_AddRef,
594 BSCHttpNegotiate_Release,
595 BSCHttpNegotiate_BeginningTransaction,
596 BSCHttpNegotiate_OnResponse
597 };
598
599 static HRESULT WINAPI Authenticate_QueryInterface(IAuthenticate *iface,
600 REFIID riid, void **ppv)
601 {
602 BindStatusCallback *This = impl_from_IAuthenticate(iface);
603 return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
604 }
605
606 static ULONG WINAPI Authenticate_AddRef(IAuthenticate *iface)
607 {
608 BindStatusCallback *This = impl_from_IAuthenticate(iface);
609 return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
610 }
611
612 static ULONG WINAPI Authenticate_Release(IAuthenticate *iface)
613 {
614 BindStatusCallback *This = impl_from_IAuthenticate(iface);
615 return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
616 }
617
618 static HRESULT WINAPI Authenticate_Authenticate(IAuthenticate *iface,
619 HWND *hwnd, LPWSTR *username, LPWSTR *password)
620 {
621 BindStatusCallback *This = impl_from_IAuthenticate(iface);
622 httprequest *request = This->request;
623
624 TRACE("(%p)->(%p %p %p)\n", This, hwnd, username, password);
625
626 if (request->user && *request->user)
627 {
628 if (hwnd) *hwnd = NULL;
629 *username = CoTaskMemAlloc(SysStringByteLen(request->user)+sizeof(WCHAR));
630 *password = CoTaskMemAlloc(SysStringByteLen(request->password)+sizeof(WCHAR));
631 if (!*username || !*password)
632 {
633 CoTaskMemFree(*username);
634 CoTaskMemFree(*password);
635 return E_OUTOFMEMORY;
636 }
637
638 memcpy(*username, request->user, SysStringByteLen(request->user)+sizeof(WCHAR));
639 memcpy(*password, request->password, SysStringByteLen(request->password)+sizeof(WCHAR));
640 }
641
642 return S_OK;
643 }
644
645 static const IAuthenticateVtbl AuthenticateVtbl = {
646 Authenticate_QueryInterface,
647 Authenticate_AddRef,
648 Authenticate_Release,
649 Authenticate_Authenticate
650 };
651
652 static HRESULT BindStatusCallback_create(httprequest* This, BindStatusCallback **obj, const VARIANT *body)
653 {
654 BindStatusCallback *bsc;
655 IBindCtx *pbc;
656 HRESULT hr;
657 int size;
658
659 hr = CreateBindCtx(0, &pbc);
660 if (hr != S_OK) return hr;
661
662 bsc = heap_alloc(sizeof(*bsc));
663 if (!bsc)
664 {
665 IBindCtx_Release(pbc);
666 return E_OUTOFMEMORY;
667 }
668
669 bsc->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
670 bsc->IHttpNegotiate_iface.lpVtbl = &BSCHttpNegotiateVtbl;
671 bsc->IAuthenticate_iface.lpVtbl = &AuthenticateVtbl;
672 bsc->ref = 1;
673 bsc->request = This;
674 bsc->binding = NULL;
675 bsc->stream = NULL;
676 bsc->body = NULL;
677
678 TRACE("(%p)->(%p)\n", This, bsc);
679
680 This->use_utf8_content = FALSE;
681
682 if (This->verb != BINDVERB_GET)
683 {
684 void *send_data, *ptr;
685 SAFEARRAY *sa = NULL;
686
687 if (V_VT(body) == (VT_VARIANT|VT_BYREF))
688 body = V_VARIANTREF(body);
689
690 switch (V_VT(body))
691 {
692 case VT_BSTR:
693 {
694 int len = SysStringLen(V_BSTR(body));
695 const WCHAR *str = V_BSTR(body);
696 UINT i, cp = CP_ACP;
697
698 for (i = 0; i < len; i++)
699 {
700 if (str[i] > 127)
701 {
702 cp = CP_UTF8;
703 break;
704 }
705 }
706
707 size = WideCharToMultiByte(cp, 0, str, len, NULL, 0, NULL, NULL);
708 if (!(ptr = heap_alloc(size)))
709 {
710 heap_free(bsc);
711 return E_OUTOFMEMORY;
712 }
713 WideCharToMultiByte(cp, 0, str, len, ptr, size, NULL, NULL);
714 if (cp == CP_UTF8) This->use_utf8_content = TRUE;
715 break;
716 }
717 case VT_ARRAY|VT_UI1:
718 {
719 sa = V_ARRAY(body);
720 if ((hr = SafeArrayAccessData(sa, (void **)&ptr)) != S_OK)
721 {
722 heap_free(bsc);
723 return hr;
724 }
725 if ((hr = SafeArrayGetUBound(sa, 1, &size)) != S_OK)
726 {
727 SafeArrayUnaccessData(sa);
728 heap_free(bsc);
729 return hr;
730 }
731 size++;
732 break;
733 }
734 default:
735 FIXME("unsupported body data type %d\n", V_VT(body));
736 /* fall through */
737 case VT_EMPTY:
738 case VT_ERROR:
739 case VT_NULL:
740 ptr = NULL;
741 size = 0;
742 break;
743 }
744
745 if (size)
746 {
747 bsc->body = GlobalAlloc(GMEM_FIXED, size);
748 if (!bsc->body)
749 {
750 if (V_VT(body) == VT_BSTR)
751 heap_free(ptr);
752 else if (V_VT(body) == (VT_ARRAY|VT_UI1))
753 SafeArrayUnaccessData(sa);
754
755 heap_free(bsc);
756 return E_OUTOFMEMORY;
757 }
758
759 send_data = GlobalLock(bsc->body);
760 memcpy(send_data, ptr, size);
761 GlobalUnlock(bsc->body);
762 }
763
764 if (V_VT(body) == VT_BSTR)
765 heap_free(ptr);
766 else if (V_VT(body) == (VT_ARRAY|VT_UI1))
767 SafeArrayUnaccessData(sa);
768 }
769
770 hr = RegisterBindStatusCallback(pbc, &bsc->IBindStatusCallback_iface, NULL, 0);
771 if (hr == S_OK)
772 {
773 IMoniker *moniker;
774
775 hr = CreateURLMonikerEx2(NULL, This->uri, &moniker, URL_MK_UNIFORM);
776 if (hr == S_OK)
777 {
778 IStream *stream;
779
780 hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (void**)&stream);
781 IMoniker_Release(moniker);
782 if (stream) IStream_Release(stream);
783 }
784 IBindCtx_Release(pbc);
785 }
786
787 if (FAILED(hr))
788 {
789 IBindStatusCallback_Release(&bsc->IBindStatusCallback_iface);
790 bsc = NULL;
791 }
792
793 *obj = bsc;
794 return hr;
795 }
796
797 static HRESULT verify_uri(httprequest *This, IUri *uri)
798 {
799 DWORD scheme, base_scheme;
800 BSTR host, base_host;
801 HRESULT hr;
802
803 if(!(This->safeopt & INTERFACESAFE_FOR_UNTRUSTED_DATA))
804 return S_OK;
805
806 if(!This->base_uri)
807 return E_ACCESSDENIED;
808
809 hr = IUri_GetScheme(uri, &scheme);
810 if(FAILED(hr))
811 return hr;
812
813 hr = IUri_GetScheme(This->base_uri, &base_scheme);
814 if(FAILED(hr))
815 return hr;
816
817 if(scheme != base_scheme) {
818 WARN("Schemes don't match\n");
819 return E_ACCESSDENIED;
820 }
821
822 if(scheme == INTERNET_SCHEME_UNKNOWN) {
823 FIXME("Unknown scheme\n");
824 return E_ACCESSDENIED;
825 }
826
827 hr = IUri_GetHost(uri, &host);
828 if(FAILED(hr))
829 return hr;
830
831 hr = IUri_GetHost(This->base_uri, &base_host);
832 if(SUCCEEDED(hr)) {
833 if(strcmpiW(host, base_host)) {
834 WARN("Hosts don't match\n");
835 hr = E_ACCESSDENIED;
836 }
837 SysFreeString(base_host);
838 }
839
840 SysFreeString(host);
841 return hr;
842 }
843
844 static HRESULT httprequest_open(httprequest *This, BSTR method, BSTR url,
845 VARIANT async, VARIANT user, VARIANT password)
846 {
847 static const WCHAR MethodGetW[] = {'G','E','T',0};
848 static const WCHAR MethodPutW[] = {'P','U','T',0};
849 static const WCHAR MethodPostW[] = {'P','O','S','T',0};
850 static const WCHAR MethodDeleteW[] = {'D','E','L','E','T','E',0};
851 static const WCHAR MethodPropFindW[] = {'P','R','O','P','F','I','N','D',0};
852 VARIANT str, is_async;
853 IUri *uri;
854 HRESULT hr;
855
856 if (!method || !url) return E_INVALIDARG;
857
858 /* free previously set data */
859 if(This->uri) {
860 IUri_Release(This->uri);
861 This->uri = NULL;
862 }
863
864 SysFreeString(This->user);
865 SysFreeString(This->password);
866 This->user = This->password = NULL;
867
868 if (!strcmpiW(method, MethodGetW))
869 {
870 This->verb = BINDVERB_GET;
871 }
872 else if (!strcmpiW(method, MethodPutW))
873 {
874 This->verb = BINDVERB_PUT;
875 }
876 else if (!strcmpiW(method, MethodPostW))
877 {
878 This->verb = BINDVERB_POST;
879 }
880 else if (!strcmpiW(method, MethodDeleteW) ||
881 !strcmpiW(method, MethodPropFindW))
882 {
883 This->verb = BINDVERB_CUSTOM;
884 SysReAllocString(&This->custom, method);
885 }
886 else
887 {
888 FIXME("unsupported request type %s\n", debugstr_w(method));
889 This->verb = -1;
890 return E_FAIL;
891 }
892
893 if(This->base_uri)
894 hr = CoInternetCombineUrlEx(This->base_uri, url, 0, &uri, 0);
895 else
896 hr = CreateUri(url, 0, 0, &uri);
897 if(FAILED(hr)) {
898 WARN("Could not create IUri object: %08x\n", hr);
899 return hr;
900 }
901
902 hr = verify_uri(This, uri);
903 if(FAILED(hr)) {
904 IUri_Release(uri);
905 return hr;
906 }
907
908 VariantInit(&str);
909 hr = VariantChangeType(&str, &user, 0, VT_BSTR);
910 if (hr == S_OK)
911 This->user = V_BSTR(&str);
912
913 VariantInit(&str);
914 hr = VariantChangeType(&str, &password, 0, VT_BSTR);
915 if (hr == S_OK)
916 This->password = V_BSTR(&str);
917
918 /* add authentication info */
919 if (This->user && *This->user)
920 {
921 IUriBuilder *builder;
922
923 hr = CreateIUriBuilder(uri, 0, 0, &builder);
924 if (hr == S_OK)
925 {
926 IUri *full_uri;
927
928 IUriBuilder_SetUserName(builder, This->user);
929 IUriBuilder_SetPassword(builder, This->password);
930 hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &full_uri);
931 if (hr == S_OK)
932 {
933 IUri_Release(uri);
934 uri = full_uri;
935 }
936 else
937 WARN("failed to create modified uri, 0x%08x\n", hr);
938 IUriBuilder_Release(builder);
939 }
940 else
941 WARN("IUriBuilder creation failed, 0x%08x\n", hr);
942 }
943
944 This->uri = uri;
945
946 VariantInit(&is_async);
947 hr = VariantChangeType(&is_async, &async, 0, VT_BOOL);
948 This->async = hr == S_OK && V_BOOL(&is_async);
949
950 httprequest_setreadystate(This, READYSTATE_LOADING);
951
952 return S_OK;
953 }
954
955 static HRESULT httprequest_setRequestHeader(httprequest *This, BSTR header, BSTR value)
956 {
957 struct httpheader *entry;
958
959 if (!header || !*header) return E_INVALIDARG;
960 if (This->state != READYSTATE_LOADING) return E_FAIL;
961 if (!value) return E_INVALIDARG;
962
963 /* replace existing header value if already added */
964 LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct httpheader, entry)
965 {
966 if (lstrcmpW(entry->header, header) == 0)
967 {
968 LONG length = SysStringLen(entry->value);
969 HRESULT hr;
970
971 hr = SysReAllocString(&entry->value, value) ? S_OK : E_OUTOFMEMORY;
972
973 if (hr == S_OK)
974 This->reqheader_size += (SysStringLen(entry->value) - length);
975
976 return hr;
977 }
978 }
979
980 entry = heap_alloc(sizeof(*entry));
981 if (!entry) return E_OUTOFMEMORY;
982
983 /* new header */
984 entry->header = SysAllocString(header);
985 entry->value = SysAllocString(value);
986
987 /* header length including null terminator */
988 This->reqheader_size += SysStringLen(entry->header) + sizeof(colspaceW)/sizeof(WCHAR) +
989 SysStringLen(entry->value) + sizeof(crlfW)/sizeof(WCHAR) - 1;
990
991 list_add_head(&This->reqheaders, &entry->entry);
992
993 return S_OK;
994 }
995
996 static HRESULT httprequest_getResponseHeader(httprequest *This, BSTR header, BSTR *value)
997 {
998 struct httpheader *entry;
999
1000 if (!header) return E_INVALIDARG;
1001 if (!value) return E_POINTER;
1002
1003 if (This->raw_respheaders && list_empty(&This->respheaders))
1004 {
1005 WCHAR *ptr, *line;
1006
1007 ptr = line = This->raw_respheaders;
1008 while (*ptr)
1009 {
1010 if (*ptr == '\r' && *(ptr+1) == '\n')
1011 {
1012 add_response_header(This, line, ptr-line);
1013 ptr++; line = ++ptr;
1014 continue;
1015 }
1016 ptr++;
1017 }
1018 }
1019
1020 LIST_FOR_EACH_ENTRY(entry, &This->respheaders, struct httpheader, entry)
1021 {
1022 if (!strcmpiW(entry->header, header))
1023 {
1024 *value = SysAllocString(entry->value);
1025 TRACE("header value %s\n", debugstr_w(*value));
1026 return S_OK;
1027 }
1028 }
1029
1030 return S_FALSE;
1031 }
1032
1033 static HRESULT httprequest_getAllResponseHeaders(httprequest *This, BSTR *respheaders)
1034 {
1035 if (!respheaders) return E_POINTER;
1036
1037 *respheaders = SysAllocString(This->raw_respheaders);
1038
1039 return S_OK;
1040 }
1041
1042 static HRESULT httprequest_send(httprequest *This, VARIANT body)
1043 {
1044 BindStatusCallback *bsc = NULL;
1045 HRESULT hr;
1046
1047 if (This->state != READYSTATE_LOADING) return E_FAIL;
1048
1049 hr = BindStatusCallback_create(This, &bsc, &body);
1050 if (FAILED(hr))
1051 /* success path to detach it is OnStopBinding call */
1052 BindStatusCallback_Detach(bsc);
1053
1054 return hr;
1055 }
1056
1057 static HRESULT httprequest_abort(httprequest *This)
1058 {
1059 BindStatusCallback_Detach(This->bsc);
1060
1061 httprequest_setreadystate(This, READYSTATE_UNINITIALIZED);
1062
1063 return S_OK;
1064 }
1065
1066 static HRESULT httprequest_get_status(httprequest *This, LONG *status)
1067 {
1068 if (!status) return E_POINTER;
1069
1070 *status = This->status;
1071
1072 return This->state == READYSTATE_COMPLETE ? S_OK : E_FAIL;
1073 }
1074
1075 static HRESULT httprequest_get_statusText(httprequest *This, BSTR *status)
1076 {
1077 if (!status) return E_POINTER;
1078 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
1079
1080 *status = SysAllocString(This->status_text);
1081
1082 return S_OK;
1083 }
1084
1085 static HRESULT httprequest_get_responseText(httprequest *This, BSTR *body)
1086 {
1087 HGLOBAL hglobal;
1088 HRESULT hr;
1089
1090 if (!body) return E_POINTER;
1091 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
1092
1093 hr = GetHGlobalFromStream(This->bsc->stream, &hglobal);
1094 if (hr == S_OK)
1095 {
1096 xmlChar *ptr = GlobalLock(hglobal);
1097 DWORD size = GlobalSize(hglobal);
1098 xmlCharEncoding encoding = XML_CHAR_ENCODING_UTF8;
1099
1100 /* try to determine data encoding */
1101 if (size >= 4)
1102 {
1103 encoding = xmlDetectCharEncoding(ptr, 4);
1104 TRACE("detected encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding)));
1105 if ( encoding != XML_CHAR_ENCODING_UTF8 &&
1106 encoding != XML_CHAR_ENCODING_UTF16LE &&
1107 encoding != XML_CHAR_ENCODING_NONE )
1108 {
1109 FIXME("unsupported encoding: %s\n", debugstr_a(xmlGetCharEncodingName(encoding)));
1110 GlobalUnlock(hglobal);
1111 return E_FAIL;
1112 }
1113 }
1114
1115 /* without BOM assume UTF-8 */
1116 if (encoding == XML_CHAR_ENCODING_UTF8 ||
1117 encoding == XML_CHAR_ENCODING_NONE )
1118 {
1119 DWORD length = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)ptr, size, NULL, 0);
1120
1121 *body = SysAllocStringLen(NULL, length);
1122 if (*body)
1123 MultiByteToWideChar( CP_UTF8, 0, (LPCSTR)ptr, size, *body, length);
1124 }
1125 else
1126 *body = SysAllocStringByteLen((LPCSTR)ptr, size);
1127
1128 if (!*body) hr = E_OUTOFMEMORY;
1129 GlobalUnlock(hglobal);
1130 }
1131
1132 return hr;
1133 }
1134
1135 static HRESULT httprequest_get_responseXML(httprequest *This, IDispatch **body)
1136 {
1137 IXMLDOMDocument3 *doc;
1138 HRESULT hr;
1139 BSTR str;
1140
1141 if (!body) return E_INVALIDARG;
1142 if (This->state != READYSTATE_COMPLETE) return E_FAIL;
1143
1144 hr = DOMDocument_create(MSXML_DEFAULT, (void**)&doc);
1145 if (hr != S_OK) return hr;
1146
1147 hr = httprequest_get_responseText(This, &str);
1148 if (hr == S_OK)
1149 {
1150 VARIANT_BOOL ok;
1151
1152 hr = IXMLDOMDocument3_loadXML(doc, str, &ok);
1153 SysFreeString(str);
1154 }
1155
1156 IXMLDOMDocument3_QueryInterface(doc, &IID_IDispatch, (void**)body);
1157 IXMLDOMDocument3_Release(doc);
1158
1159 return hr;
1160 }
1161
1162 static HRESULT httprequest_get_responseBody(httprequest *This, VARIANT *body)
1163 {
1164 HGLOBAL hglobal;
1165 HRESULT hr;
1166
1167 if (!body) return E_INVALIDARG;
1168 V_VT(body) = VT_EMPTY;
1169
1170 if (This->state != READYSTATE_COMPLETE) return E_PENDING;
1171
1172 hr = GetHGlobalFromStream(This->bsc->stream, &hglobal);
1173 if (hr == S_OK)
1174 {
1175 void *ptr = GlobalLock(hglobal);
1176 DWORD size = GlobalSize(hglobal);
1177
1178 SAFEARRAYBOUND bound;
1179 SAFEARRAY *array;
1180
1181 bound.lLbound = 0;
1182 bound.cElements = size;
1183 array = SafeArrayCreate(VT_UI1, 1, &bound);
1184
1185 if (array)
1186 {
1187 void *dest;
1188
1189 V_VT(body) = VT_ARRAY | VT_UI1;
1190 V_ARRAY(body) = array;
1191
1192 hr = SafeArrayAccessData(array, &dest);
1193 if (hr == S_OK)
1194 {
1195 memcpy(dest, ptr, size);
1196 SafeArrayUnaccessData(array);
1197 }
1198 else
1199 {
1200 VariantClear(body);
1201 }
1202 }
1203 else
1204 hr = E_FAIL;
1205
1206 GlobalUnlock(hglobal);
1207 }
1208
1209 return hr;
1210 }
1211
1212 static HRESULT httprequest_get_responseStream(httprequest *This, VARIANT *body)
1213 {
1214 LARGE_INTEGER move;
1215 IStream *stream;
1216 HRESULT hr;
1217
1218 if (!body) return E_INVALIDARG;
1219 V_VT(body) = VT_EMPTY;
1220
1221 if (This->state != READYSTATE_COMPLETE) return E_PENDING;
1222
1223 hr = IStream_Clone(This->bsc->stream, &stream);
1224
1225 move.QuadPart = 0;
1226 IStream_Seek(stream, move, STREAM_SEEK_SET, NULL);
1227
1228 V_VT(body) = VT_UNKNOWN;
1229 V_UNKNOWN(body) = (IUnknown*)stream;
1230
1231 return hr;
1232 }
1233
1234 static HRESULT httprequest_get_readyState(httprequest *This, LONG *state)
1235 {
1236 if (!state) return E_POINTER;
1237
1238 *state = This->state;
1239 return S_OK;
1240 }
1241
1242 static HRESULT httprequest_put_onreadystatechange(httprequest *This, IDispatch *sink)
1243 {
1244 if (This->sink) IDispatch_Release(This->sink);
1245 if ((This->sink = sink)) IDispatch_AddRef(This->sink);
1246
1247 return S_OK;
1248 }
1249
1250 static void httprequest_release(httprequest *This)
1251 {
1252 struct httpheader *header, *header2;
1253
1254 if (This->site)
1255 IUnknown_Release( This->site );
1256 if (This->uri)
1257 IUri_Release(This->uri);
1258 if (This->base_uri)
1259 IUri_Release(This->base_uri);
1260
1261 SysFreeString(This->custom);
1262 SysFreeString(This->user);
1263 SysFreeString(This->password);
1264
1265 /* request headers */
1266 LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry)
1267 {
1268 list_remove(&header->entry);
1269 SysFreeString(header->header);
1270 SysFreeString(header->value);
1271 heap_free(header);
1272 }
1273 /* response headers */
1274 free_response_headers(This);
1275 SysFreeString(This->status_text);
1276
1277 /* detach callback object */
1278 BindStatusCallback_Detach(This->bsc);
1279
1280 if (This->sink) IDispatch_Release(This->sink);
1281 }
1282
1283 static HRESULT WINAPI XMLHTTPRequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject)
1284 {
1285 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1286 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
1287
1288 if ( IsEqualGUID( riid, &IID_IXMLHTTPRequest) ||
1289 IsEqualGUID( riid, &IID_IDispatch) ||
1290 IsEqualGUID( riid, &IID_IUnknown) )
1291 {
1292 *ppvObject = iface;
1293 }
1294 else if (IsEqualGUID(&IID_IObjectWithSite, riid))
1295 {
1296 *ppvObject = &This->IObjectWithSite_iface;
1297 }
1298 else if (IsEqualGUID(&IID_IObjectSafety, riid))
1299 {
1300 *ppvObject = &This->IObjectSafety_iface;
1301 }
1302 else
1303 {
1304 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
1305 *ppvObject = NULL;
1306 return E_NOINTERFACE;
1307 }
1308
1309 IXMLHTTPRequest_AddRef( iface );
1310
1311 return S_OK;
1312 }
1313
1314 static ULONG WINAPI XMLHTTPRequest_AddRef(IXMLHTTPRequest *iface)
1315 {
1316 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1317 ULONG ref = InterlockedIncrement( &This->ref );
1318 TRACE("(%p)->(%u)\n", This, ref );
1319 return ref;
1320 }
1321
1322 static ULONG WINAPI XMLHTTPRequest_Release(IXMLHTTPRequest *iface)
1323 {
1324 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1325 ULONG ref = InterlockedDecrement( &This->ref );
1326
1327 TRACE("(%p)->(%u)\n", This, ref );
1328
1329 if ( ref == 0 )
1330 {
1331 httprequest_release( This );
1332 heap_free( This );
1333 }
1334
1335 return ref;
1336 }
1337
1338 static HRESULT WINAPI XMLHTTPRequest_GetTypeInfoCount(IXMLHTTPRequest *iface, UINT *pctinfo)
1339 {
1340 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1341
1342 TRACE("(%p)->(%p)\n", This, pctinfo);
1343
1344 *pctinfo = 1;
1345
1346 return S_OK;
1347 }
1348
1349 static HRESULT WINAPI XMLHTTPRequest_GetTypeInfo(IXMLHTTPRequest *iface, UINT iTInfo,
1350 LCID lcid, ITypeInfo **ppTInfo)
1351 {
1352 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1353
1354 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1355
1356 return get_typeinfo(IXMLHTTPRequest_tid, ppTInfo);
1357 }
1358
1359 static HRESULT WINAPI XMLHTTPRequest_GetIDsOfNames(IXMLHTTPRequest *iface, REFIID riid,
1360 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1361 {
1362 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1363 ITypeInfo *typeinfo;
1364 HRESULT hr;
1365
1366 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1367 lcid, rgDispId);
1368
1369 if(!rgszNames || cNames == 0 || !rgDispId)
1370 return E_INVALIDARG;
1371
1372 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
1373 if(SUCCEEDED(hr))
1374 {
1375 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1376 ITypeInfo_Release(typeinfo);
1377 }
1378
1379 return hr;
1380 }
1381
1382 static HRESULT WINAPI XMLHTTPRequest_Invoke(IXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid,
1383 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1384 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1385 {
1386 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1387 ITypeInfo *typeinfo;
1388 HRESULT hr;
1389
1390 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1391 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1392
1393 hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
1394 if(SUCCEEDED(hr))
1395 {
1396 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLHTTPRequest_iface, dispIdMember, wFlags,
1397 pDispParams, pVarResult, pExcepInfo, puArgErr);
1398 ITypeInfo_Release(typeinfo);
1399 }
1400
1401 return hr;
1402 }
1403
1404 static HRESULT WINAPI XMLHTTPRequest_open(IXMLHTTPRequest *iface, BSTR method, BSTR url,
1405 VARIANT async, VARIANT user, VARIANT password)
1406 {
1407 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1408 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(method), debugstr_w(url),
1409 debugstr_variant(&async));
1410 return httprequest_open(This, method, url, async, user, password);
1411 }
1412
1413 static HRESULT WINAPI XMLHTTPRequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR header, BSTR value)
1414 {
1415 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1416 TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
1417 return httprequest_setRequestHeader(This, header, value);
1418 }
1419
1420 static HRESULT WINAPI XMLHTTPRequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR header, BSTR *value)
1421 {
1422 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1423 TRACE("(%p)->(%s %p)\n", This, debugstr_w(header), value);
1424 return httprequest_getResponseHeader(This, header, value);
1425 }
1426
1427 static HRESULT WINAPI XMLHTTPRequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *respheaders)
1428 {
1429 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1430 TRACE("(%p)->(%p)\n", This, respheaders);
1431 return httprequest_getAllResponseHeaders(This, respheaders);
1432 }
1433
1434 static HRESULT WINAPI XMLHTTPRequest_send(IXMLHTTPRequest *iface, VARIANT body)
1435 {
1436 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1437 TRACE("(%p)->(%s)\n", This, debugstr_variant(&body));
1438 return httprequest_send(This, body);
1439 }
1440
1441 static HRESULT WINAPI XMLHTTPRequest_abort(IXMLHTTPRequest *iface)
1442 {
1443 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1444 TRACE("(%p)\n", This);
1445 return httprequest_abort(This);
1446 }
1447
1448 static HRESULT WINAPI XMLHTTPRequest_get_status(IXMLHTTPRequest *iface, LONG *status)
1449 {
1450 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1451 TRACE("(%p)->(%p)\n", This, status);
1452 return httprequest_get_status(This, status);
1453 }
1454
1455 static HRESULT WINAPI XMLHTTPRequest_get_statusText(IXMLHTTPRequest *iface, BSTR *status)
1456 {
1457 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1458 TRACE("(%p)->(%p)\n", This, status);
1459 return httprequest_get_statusText(This, status);
1460 }
1461
1462 static HRESULT WINAPI XMLHTTPRequest_get_responseXML(IXMLHTTPRequest *iface, IDispatch **body)
1463 {
1464 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1465 TRACE("(%p)->(%p)\n", This, body);
1466 return httprequest_get_responseXML(This, body);
1467 }
1468
1469 static HRESULT WINAPI XMLHTTPRequest_get_responseText(IXMLHTTPRequest *iface, BSTR *body)
1470 {
1471 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1472 TRACE("(%p)->(%p)\n", This, body);
1473 return httprequest_get_responseText(This, body);
1474 }
1475
1476 static HRESULT WINAPI XMLHTTPRequest_get_responseBody(IXMLHTTPRequest *iface, VARIANT *body)
1477 {
1478 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1479 TRACE("(%p)->(%p)\n", This, body);
1480 return httprequest_get_responseBody(This, body);
1481 }
1482
1483 static HRESULT WINAPI XMLHTTPRequest_get_responseStream(IXMLHTTPRequest *iface, VARIANT *body)
1484 {
1485 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1486 TRACE("(%p)->(%p)\n", This, body);
1487 return httprequest_get_responseStream(This, body);
1488 }
1489
1490 static HRESULT WINAPI XMLHTTPRequest_get_readyState(IXMLHTTPRequest *iface, LONG *state)
1491 {
1492 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1493 TRACE("(%p)->(%p)\n", This, state);
1494 return httprequest_get_readyState(This, state);
1495 }
1496
1497 static HRESULT WINAPI XMLHTTPRequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *sink)
1498 {
1499 httprequest *This = impl_from_IXMLHTTPRequest( iface );
1500 TRACE("(%p)->(%p)\n", This, sink);
1501 return httprequest_put_onreadystatechange(This, sink);
1502 }
1503
1504 static const struct IXMLHTTPRequestVtbl XMLHTTPRequestVtbl =
1505 {
1506 XMLHTTPRequest_QueryInterface,
1507 XMLHTTPRequest_AddRef,
1508 XMLHTTPRequest_Release,
1509 XMLHTTPRequest_GetTypeInfoCount,
1510 XMLHTTPRequest_GetTypeInfo,
1511 XMLHTTPRequest_GetIDsOfNames,
1512 XMLHTTPRequest_Invoke,
1513 XMLHTTPRequest_open,
1514 XMLHTTPRequest_setRequestHeader,
1515 XMLHTTPRequest_getResponseHeader,
1516 XMLHTTPRequest_getAllResponseHeaders,
1517 XMLHTTPRequest_send,
1518 XMLHTTPRequest_abort,
1519 XMLHTTPRequest_get_status,
1520 XMLHTTPRequest_get_statusText,
1521 XMLHTTPRequest_get_responseXML,
1522 XMLHTTPRequest_get_responseText,
1523 XMLHTTPRequest_get_responseBody,
1524 XMLHTTPRequest_get_responseStream,
1525 XMLHTTPRequest_get_readyState,
1526 XMLHTTPRequest_put_onreadystatechange
1527 };
1528
1529 /* IObjectWithSite */
1530 static HRESULT WINAPI
1531 httprequest_ObjectWithSite_QueryInterface( IObjectWithSite* iface, REFIID riid, void** ppvObject )
1532 {
1533 httprequest *This = impl_from_IObjectWithSite(iface);
1534 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest *)This, riid, ppvObject );
1535 }
1536
1537 static ULONG WINAPI httprequest_ObjectWithSite_AddRef( IObjectWithSite* iface )
1538 {
1539 httprequest *This = impl_from_IObjectWithSite(iface);
1540 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest *)This);
1541 }
1542
1543 static ULONG WINAPI httprequest_ObjectWithSite_Release( IObjectWithSite* iface )
1544 {
1545 httprequest *This = impl_from_IObjectWithSite(iface);
1546 return IXMLHTTPRequest_Release((IXMLHTTPRequest *)This);
1547 }
1548
1549 static HRESULT WINAPI httprequest_ObjectWithSite_GetSite( IObjectWithSite *iface, REFIID iid, void **ppvSite )
1550 {
1551 httprequest *This = impl_from_IObjectWithSite(iface);
1552
1553 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( iid ), ppvSite );
1554
1555 if ( !This->site )
1556 return E_FAIL;
1557
1558 return IUnknown_QueryInterface( This->site, iid, ppvSite );
1559 }
1560
1561 static void get_base_uri(httprequest *This)
1562 {
1563 IServiceProvider *provider;
1564 IHTMLDocument2 *doc;
1565 IUri *uri;
1566 BSTR url;
1567 HRESULT hr;
1568
1569 hr = IUnknown_QueryInterface(This->site, &IID_IServiceProvider, (void**)&provider);
1570 if(FAILED(hr))
1571 return;
1572
1573 hr = IServiceProvider_QueryService(provider, &SID_SContainerDispatch, &IID_IHTMLDocument2, (void**)&doc);
1574 if(FAILED(hr))
1575 hr = IServiceProvider_QueryService(provider, &SID_SInternetHostSecurityManager, &IID_IHTMLDocument2, (void**)&doc);
1576 IServiceProvider_Release(provider);
1577 if(FAILED(hr))
1578 return;
1579
1580 hr = IHTMLDocument2_get_URL(doc, &url);
1581 IHTMLDocument2_Release(doc);
1582 if(FAILED(hr) || !url || !*url)
1583 return;
1584
1585 TRACE("host url %s\n", debugstr_w(url));
1586
1587 hr = CreateUri(url, 0, 0, &uri);
1588 SysFreeString(url);
1589 if(FAILED(hr))
1590 return;
1591
1592 This->base_uri = uri;
1593 }
1594
1595 static HRESULT WINAPI httprequest_ObjectWithSite_SetSite( IObjectWithSite *iface, IUnknown *punk )
1596 {
1597 httprequest *This = impl_from_IObjectWithSite(iface);
1598
1599 TRACE("(%p)->(%p)\n", This, punk);
1600
1601 if(This->site)
1602 IUnknown_Release( This->site );
1603 if(This->base_uri)
1604 IUri_Release(This->base_uri);
1605
1606 This->site = punk;
1607
1608 if (punk)
1609 {
1610 IUnknown_AddRef( punk );
1611 get_base_uri(This);
1612 }
1613
1614 return S_OK;
1615 }
1616
1617 static const IObjectWithSiteVtbl ObjectWithSiteVtbl =
1618 {
1619 httprequest_ObjectWithSite_QueryInterface,
1620 httprequest_ObjectWithSite_AddRef,
1621 httprequest_ObjectWithSite_Release,
1622 httprequest_ObjectWithSite_SetSite,
1623 httprequest_ObjectWithSite_GetSite
1624 };
1625
1626 /* IObjectSafety */
1627 static HRESULT WINAPI httprequest_Safety_QueryInterface(IObjectSafety *iface, REFIID riid, void **ppv)
1628 {
1629 httprequest *This = impl_from_IObjectSafety(iface);
1630 return IXMLHTTPRequest_QueryInterface( (IXMLHTTPRequest *)This, riid, ppv );
1631 }
1632
1633 static ULONG WINAPI httprequest_Safety_AddRef(IObjectSafety *iface)
1634 {
1635 httprequest *This = impl_from_IObjectSafety(iface);
1636 return IXMLHTTPRequest_AddRef((IXMLHTTPRequest *)This);
1637 }
1638
1639 static ULONG WINAPI httprequest_Safety_Release(IObjectSafety *iface)
1640 {
1641 httprequest *This = impl_from_IObjectSafety(iface);
1642 return IXMLHTTPRequest_Release((IXMLHTTPRequest *)This);
1643 }
1644
1645 static HRESULT WINAPI httprequest_Safety_GetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1646 DWORD *supported, DWORD *enabled)
1647 {
1648 httprequest *This = impl_from_IObjectSafety(iface);
1649
1650 TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(riid), supported, enabled);
1651
1652 if(!supported || !enabled) return E_POINTER;
1653
1654 *supported = safety_supported_options;
1655 *enabled = This->safeopt;
1656
1657 return S_OK;
1658 }
1659
1660 static HRESULT WINAPI httprequest_Safety_SetInterfaceSafetyOptions(IObjectSafety *iface, REFIID riid,
1661 DWORD mask, DWORD enabled)
1662 {
1663 httprequest *This = impl_from_IObjectSafety(iface);
1664 TRACE("(%p)->(%s %x %x)\n", This, debugstr_guid(riid), mask, enabled);
1665
1666 if ((mask & ~safety_supported_options))
1667 return E_FAIL;
1668
1669 This->safeopt = (This->safeopt & ~mask) | (mask & enabled);
1670
1671 return S_OK;
1672 }
1673
1674 static const IObjectSafetyVtbl ObjectSafetyVtbl = {
1675 httprequest_Safety_QueryInterface,
1676 httprequest_Safety_AddRef,
1677 httprequest_Safety_Release,
1678 httprequest_Safety_GetInterfaceSafetyOptions,
1679 httprequest_Safety_SetInterfaceSafetyOptions
1680 };
1681
1682 /* IServerXMLHTTPRequest */
1683 static HRESULT WINAPI ServerXMLHTTPRequest_QueryInterface(IServerXMLHTTPRequest *iface, REFIID riid, void **obj)
1684 {
1685 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1686
1687 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
1688
1689 if ( IsEqualGUID( riid, &IID_IServerXMLHTTPRequest) ||
1690 IsEqualGUID( riid, &IID_IXMLHTTPRequest) ||
1691 IsEqualGUID( riid, &IID_IDispatch) ||
1692 IsEqualGUID( riid, &IID_IUnknown) )
1693 {
1694 *obj = iface;
1695 }
1696 else
1697 {
1698 TRACE("Unsupported interface %s\n", debugstr_guid(riid));
1699 *obj = NULL;
1700 return E_NOINTERFACE;
1701 }
1702
1703 IServerXMLHTTPRequest_AddRef( iface );
1704
1705 return S_OK;
1706 }
1707
1708 static ULONG WINAPI ServerXMLHTTPRequest_AddRef(IServerXMLHTTPRequest *iface)
1709 {
1710 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1711 ULONG ref = InterlockedIncrement( &This->ref );
1712 TRACE("(%p)->(%u)\n", This, ref );
1713 return ref;
1714 }
1715
1716 static ULONG WINAPI ServerXMLHTTPRequest_Release(IServerXMLHTTPRequest *iface)
1717 {
1718 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1719 ULONG ref = InterlockedDecrement( &This->ref );
1720
1721 TRACE("(%p)->(%u)\n", This, ref );
1722
1723 if ( ref == 0 )
1724 {
1725 httprequest_release( &This->req );
1726 heap_free( This );
1727 }
1728
1729 return ref;
1730 }
1731
1732 static HRESULT WINAPI ServerXMLHTTPRequest_GetTypeInfoCount(IServerXMLHTTPRequest *iface, UINT *pctinfo)
1733 {
1734 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1735
1736 TRACE("(%p)->(%p)\n", This, pctinfo);
1737 *pctinfo = 1;
1738
1739 return S_OK;
1740 }
1741
1742 static HRESULT WINAPI ServerXMLHTTPRequest_GetTypeInfo(IServerXMLHTTPRequest *iface, UINT iTInfo,
1743 LCID lcid, ITypeInfo **ppTInfo)
1744 {
1745 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1746
1747 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1748
1749 return get_typeinfo(IServerXMLHTTPRequest_tid, ppTInfo);
1750 }
1751
1752 static HRESULT WINAPI ServerXMLHTTPRequest_GetIDsOfNames(IServerXMLHTTPRequest *iface, REFIID riid,
1753 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1754 {
1755 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1756 ITypeInfo *typeinfo;
1757 HRESULT hr;
1758
1759 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1760 lcid, rgDispId);
1761
1762 if(!rgszNames || cNames == 0 || !rgDispId)
1763 return E_INVALIDARG;
1764
1765 hr = get_typeinfo(IServerXMLHTTPRequest_tid, &typeinfo);
1766 if(SUCCEEDED(hr))
1767 {
1768 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
1769 ITypeInfo_Release(typeinfo);
1770 }
1771
1772 return hr;
1773 }
1774
1775 static HRESULT WINAPI ServerXMLHTTPRequest_Invoke(IServerXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid,
1776 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1777 EXCEPINFO *pExcepInfo, UINT *puArgErr)
1778 {
1779 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1780 ITypeInfo *typeinfo;
1781 HRESULT hr;
1782
1783 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1784 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1785
1786 hr = get_typeinfo(IServerXMLHTTPRequest_tid, &typeinfo);
1787 if(SUCCEEDED(hr))
1788 {
1789 hr = ITypeInfo_Invoke(typeinfo, &This->IServerXMLHTTPRequest_iface, dispIdMember, wFlags,
1790 pDispParams, pVarResult, pExcepInfo, puArgErr);
1791 ITypeInfo_Release(typeinfo);
1792 }
1793
1794 return hr;
1795 }
1796
1797 static HRESULT WINAPI ServerXMLHTTPRequest_open(IServerXMLHTTPRequest *iface, BSTR method, BSTR url,
1798 VARIANT async, VARIANT user, VARIANT password)
1799 {
1800 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1801 TRACE("(%p)->(%s %s %s)\n", This, debugstr_w(method), debugstr_w(url),
1802 debugstr_variant(&async));
1803 return httprequest_open(&This->req, method, url, async, user, password);
1804 }
1805
1806 static HRESULT WINAPI ServerXMLHTTPRequest_setRequestHeader(IServerXMLHTTPRequest *iface, BSTR header, BSTR value)
1807 {
1808 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1809 TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
1810 return httprequest_setRequestHeader(&This->req, header, value);
1811 }
1812
1813 static HRESULT WINAPI ServerXMLHTTPRequest_getResponseHeader(IServerXMLHTTPRequest *iface, BSTR header, BSTR *value)
1814 {
1815 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1816 TRACE("(%p)->(%s %p)\n", This, debugstr_w(header), value);
1817 return httprequest_getResponseHeader(&This->req, header, value);
1818 }
1819
1820 static HRESULT WINAPI ServerXMLHTTPRequest_getAllResponseHeaders(IServerXMLHTTPRequest *iface, BSTR *respheaders)
1821 {
1822 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1823 TRACE("(%p)->(%p)\n", This, respheaders);
1824 return httprequest_getAllResponseHeaders(&This->req, respheaders);
1825 }
1826
1827 static HRESULT WINAPI ServerXMLHTTPRequest_send(IServerXMLHTTPRequest *iface, VARIANT body)
1828 {
1829 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1830 TRACE("(%p)->(%s)\n", This, debugstr_variant(&body));
1831 return httprequest_send(&This->req, body);
1832 }
1833
1834 static HRESULT WINAPI ServerXMLHTTPRequest_abort(IServerXMLHTTPRequest *iface)
1835 {
1836 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1837 TRACE("(%p)\n", This);
1838 return httprequest_abort(&This->req);
1839 }
1840
1841 static HRESULT WINAPI ServerXMLHTTPRequest_get_status(IServerXMLHTTPRequest *iface, LONG *status)
1842 {
1843 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1844 TRACE("(%p)->(%p)\n", This, status);
1845 return httprequest_get_status(&This->req, status);
1846 }
1847
1848 static HRESULT WINAPI ServerXMLHTTPRequest_get_statusText(IServerXMLHTTPRequest *iface, BSTR *status)
1849 {
1850 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1851 TRACE("(%p)->(%p)\n", This, status);
1852 return httprequest_get_statusText(&This->req, status);
1853 }
1854
1855 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseXML(IServerXMLHTTPRequest *iface, IDispatch **body)
1856 {
1857 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1858 TRACE("(%p)->(%p)\n", This, body);
1859 return httprequest_get_responseXML(&This->req, body);
1860 }
1861
1862 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseText(IServerXMLHTTPRequest *iface, BSTR *body)
1863 {
1864 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1865 TRACE("(%p)->(%p)\n", This, body);
1866 return httprequest_get_responseText(&This->req, body);
1867 }
1868
1869 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseBody(IServerXMLHTTPRequest *iface, VARIANT *body)
1870 {
1871 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1872 TRACE("(%p)->(%p)\n", This, body);
1873 return httprequest_get_responseBody(&This->req, body);
1874 }
1875
1876 static HRESULT WINAPI ServerXMLHTTPRequest_get_responseStream(IServerXMLHTTPRequest *iface, VARIANT *body)
1877 {
1878 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1879 TRACE("(%p)->(%p)\n", This, body);
1880 return httprequest_get_responseStream(&This->req, body);
1881 }
1882
1883 static HRESULT WINAPI ServerXMLHTTPRequest_get_readyState(IServerXMLHTTPRequest *iface, LONG *state)
1884 {
1885 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1886 TRACE("(%p)->(%p)\n", This, state);
1887 return httprequest_get_readyState(&This->req, state);
1888 }
1889
1890 static HRESULT WINAPI ServerXMLHTTPRequest_put_onreadystatechange(IServerXMLHTTPRequest *iface, IDispatch *sink)
1891 {
1892 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1893 TRACE("(%p)->(%p)\n", This, sink);
1894 return httprequest_put_onreadystatechange(&This->req, sink);
1895 }
1896
1897 static HRESULT WINAPI ServerXMLHTTPRequest_setTimeouts(IServerXMLHTTPRequest *iface, LONG resolveTimeout, LONG connectTimeout,
1898 LONG sendTimeout, LONG receiveTimeout)
1899 {
1900 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1901 FIXME("(%p)->(%d %d %d %d): stub\n", This, resolveTimeout, connectTimeout, sendTimeout, receiveTimeout);
1902 return E_NOTIMPL;
1903 }
1904
1905 static HRESULT WINAPI ServerXMLHTTPRequest_waitForResponse(IServerXMLHTTPRequest *iface, VARIANT timeout, VARIANT_BOOL *isSuccessful)
1906 {
1907 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1908 FIXME("(%p)->(%s %p): stub\n", This, debugstr_variant(&timeout), isSuccessful);
1909 return E_NOTIMPL;
1910 }
1911
1912 static HRESULT WINAPI ServerXMLHTTPRequest_getOption(IServerXMLHTTPRequest *iface, SERVERXMLHTTP_OPTION option, VARIANT *value)
1913 {
1914 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1915 FIXME("(%p)->(%d %p): stub\n", This, option, value);
1916 return E_NOTIMPL;
1917 }
1918
1919 static HRESULT WINAPI ServerXMLHTTPRequest_setOption(IServerXMLHTTPRequest *iface, SERVERXMLHTTP_OPTION option, VARIANT value)
1920 {
1921 serverhttp *This = impl_from_IServerXMLHTTPRequest( iface );
1922 FIXME("(%p)->(%d %s): stub\n", This, option, debugstr_variant(&value));
1923 return E_NOTIMPL;
1924 }
1925
1926 static const struct IServerXMLHTTPRequestVtbl ServerXMLHTTPRequestVtbl =
1927 {
1928 ServerXMLHTTPRequest_QueryInterface,
1929 ServerXMLHTTPRequest_AddRef,
1930 ServerXMLHTTPRequest_Release,
1931 ServerXMLHTTPRequest_GetTypeInfoCount,
1932 ServerXMLHTTPRequest_GetTypeInfo,
1933 ServerXMLHTTPRequest_GetIDsOfNames,
1934 ServerXMLHTTPRequest_Invoke,
1935 ServerXMLHTTPRequest_open,
1936 ServerXMLHTTPRequest_setRequestHeader,
1937 ServerXMLHTTPRequest_getResponseHeader,
1938 ServerXMLHTTPRequest_getAllResponseHeaders,
1939 ServerXMLHTTPRequest_send,
1940 ServerXMLHTTPRequest_abort,
1941 ServerXMLHTTPRequest_get_status,
1942 ServerXMLHTTPRequest_get_statusText,
1943 ServerXMLHTTPRequest_get_responseXML,
1944 ServerXMLHTTPRequest_get_responseText,
1945 ServerXMLHTTPRequest_get_responseBody,
1946 ServerXMLHTTPRequest_get_responseStream,
1947 ServerXMLHTTPRequest_get_readyState,
1948 ServerXMLHTTPRequest_put_onreadystatechange,
1949 ServerXMLHTTPRequest_setTimeouts,
1950 ServerXMLHTTPRequest_waitForResponse,
1951 ServerXMLHTTPRequest_getOption,
1952 ServerXMLHTTPRequest_setOption
1953 };
1954
1955 static void init_httprequest(httprequest *req)
1956 {
1957 req->IXMLHTTPRequest_iface.lpVtbl = &XMLHTTPRequestVtbl;
1958 req->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl;
1959 req->IObjectSafety_iface.lpVtbl = &ObjectSafetyVtbl;
1960 req->ref = 1;
1961
1962 req->async = FALSE;
1963 req->verb = -1;
1964 req->custom = NULL;
1965 req->uri = req->base_uri = NULL;
1966 req->user = req->password = NULL;
1967
1968 req->state = READYSTATE_UNINITIALIZED;
1969 req->sink = NULL;
1970
1971 req->bsc = NULL;
1972 req->status = 0;
1973 req->status_text = NULL;
1974 req->reqheader_size = 0;
1975 req->raw_respheaders = NULL;
1976 req->use_utf8_content = FALSE;
1977
1978 list_init(&req->reqheaders);
1979 list_init(&req->respheaders);
1980
1981 req->site = NULL;
1982 req->safeopt = 0;
1983 }
1984
1985 HRESULT XMLHTTPRequest_create(void **obj)
1986 {
1987 httprequest *req;
1988
1989 TRACE("(%p)\n", obj);
1990
1991 req = heap_alloc( sizeof (*req) );
1992 if( !req )
1993 return E_OUTOFMEMORY;
1994
1995 init_httprequest(req);
1996 *obj = &req->IXMLHTTPRequest_iface;
1997
1998 TRACE("returning iface %p\n", *obj);
1999
2000 return S_OK;
2001 }
2002
2003 HRESULT ServerXMLHTTP_create(void **obj)
2004 {
2005 serverhttp *req;
2006
2007 TRACE("(%p)\n", obj);
2008
2009 req = heap_alloc( sizeof (*req) );
2010 if( !req )
2011 return E_OUTOFMEMORY;
2012
2013 init_httprequest(&req->req);
2014 req->IServerXMLHTTPRequest_iface.lpVtbl = &ServerXMLHTTPRequestVtbl;
2015 req->ref = 1;
2016
2017 *obj = &req->IServerXMLHTTPRequest_iface;
2018
2019 TRACE("returning iface %p\n", *obj);
2020
2021 return S_OK;
2022 }
2023
2024 #else
2025
2026 HRESULT XMLHTTPRequest_create(void **ppObj)
2027 {
2028 MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
2029 "libxml2 support was not present at compile time.\n");
2030 return E_NOTIMPL;
2031 }
2032
2033 HRESULT ServerXMLHTTP_create(void **obj)
2034 {
2035 MESSAGE("This program tried to use a ServerXMLHTTP object, but\n"
2036 "libxml2 support was not present at compile time.\n");
2037 return E_NOTIMPL;
2038 }
2039
2040 #endif