gdi.exe16: Constify a variable.
[wine] / dlls / msxml3 / httprequest.c
1 /*
2  *    IXMLHTTPRequest implementation
3  *
4  * Copyright 2008 Alistair Leslie-Hughes
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #define COBJMACROS
21
22 #include "config.h"
23
24 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "ole2.h"
29 #include "msxml6.h"
30
31 #include "msxml_private.h"
32
33 #include "wine/debug.h"
34 #include "wine/list.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
37
38 #ifdef HAVE_LIBXML2
39
40 static const WCHAR MethodGetW[] = {'G','E','T',0};
41 static const WCHAR MethodPutW[] = {'P','U','T',0};
42 static const WCHAR MethodPostW[] = {'P','O','S','T',0};
43
44 typedef struct BindStatusCallback BindStatusCallback;
45
46 struct reqheader
47 {
48     struct list entry;
49     BSTR header;
50     BSTR value;
51 };
52
53 typedef struct
54 {
55     const struct IXMLHTTPRequestVtbl *lpVtbl;
56     LONG ref;
57
58     READYSTATE state;
59
60     /* request */
61     BINDVERB verb;
62     BSTR url;
63     BOOL async;
64     struct list reqheaders;
65
66     /* credentials */
67     BSTR user;
68     BSTR password;
69
70     /* bind callback */
71     BindStatusCallback *bsc;
72 } httprequest;
73
74 static inline httprequest *impl_from_IXMLHTTPRequest( IXMLHTTPRequest *iface )
75 {
76     return (httprequest *)((char*)iface - FIELD_OFFSET(httprequest, lpVtbl));
77 }
78
79 struct BindStatusCallback
80 {
81     const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl;
82     const IHttpNegotiateVtbl      *lpHttpNegotiateVtbl;
83     LONG ref;
84
85     IBinding *binding;
86     const httprequest *request;
87 };
88
89 static inline BindStatusCallback *impl_from_IBindStatusCallback( IBindStatusCallback *iface )
90 {
91     return (BindStatusCallback *)((char*)iface - FIELD_OFFSET(BindStatusCallback, lpBindStatusCallbackVtbl));
92 }
93
94 static inline BindStatusCallback *impl_from_IHttpNegotiate( IHttpNegotiate *iface )
95 {
96     return (BindStatusCallback *)((char*)iface - FIELD_OFFSET(BindStatusCallback, lpHttpNegotiateVtbl));
97 }
98
99 void BindStatusCallback_Detach(BindStatusCallback *bsc)
100 {
101     if (bsc)
102     {
103         if (bsc->binding) IBinding_Abort(bsc->binding);
104         bsc->request = NULL;
105         IBindStatusCallback_Release((IBindStatusCallback*)bsc);
106     }
107 }
108
109 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface,
110         REFIID riid, void **ppv)
111 {
112     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
113
114     *ppv = NULL;
115
116     TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
117
118     if (IsEqualGUID(&IID_IUnknown, riid) ||
119         IsEqualGUID(&IID_IBindStatusCallback, riid))
120     {
121         *ppv = &This->lpBindStatusCallbackVtbl;
122     }
123     else if (IsEqualGUID(&IID_IServiceProvider, riid) ||
124              IsEqualGUID(&IID_IBindStatusCallbackEx, riid))
125     {
126         return E_NOINTERFACE;
127     }
128
129     if (*ppv)
130     {
131         IBindStatusCallback_AddRef(iface);
132         return S_OK;
133     }
134
135     FIXME("Unsupported riid = %s\n", debugstr_guid(riid));
136
137     return E_NOINTERFACE;
138 }
139
140 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
141 {
142     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
143     LONG ref = InterlockedIncrement(&This->ref);
144
145     TRACE("(%p) ref = %d\n", This, ref);
146
147     return ref;
148 }
149
150 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
151 {
152     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
153     LONG ref = InterlockedDecrement(&This->ref);
154
155     TRACE("(%p) ref = %d\n", This, ref);
156
157     if (!ref)
158     {
159         if (This->binding) IBinding_Release(This->binding);
160         heap_free(This);
161     }
162
163     return ref;
164 }
165
166 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface,
167         DWORD reserved, IBinding *pbind)
168 {
169     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
170
171     TRACE("(%p)->(%d %p)\n", This, reserved, pbind);
172
173     if (!pbind) return E_INVALIDARG;
174
175     This->binding = pbind;
176     IBinding_AddRef(pbind);
177
178     return S_OK;
179 }
180
181 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pPriority)
182 {
183     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
184
185     TRACE("(%p)->(%p)\n", This, pPriority);
186
187     return E_NOTIMPL;
188 }
189
190 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
191 {
192     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
193
194     TRACE("(%p)->(%d)\n", This, reserved);
195
196     return E_NOTIMPL;
197 }
198
199 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
200         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
201 {
202     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
203
204     TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
205             debugstr_w(szStatusText));
206
207     return S_OK;
208 }
209
210 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface,
211         HRESULT hr, LPCWSTR error)
212 {
213     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
214
215     TRACE("(%p)->(0x%08x %s)\n", This, hr, debugstr_w(error));
216
217     return S_OK;
218 }
219
220 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface,
221         DWORD *bind_flags, BINDINFO *pbindinfo)
222 {
223     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
224
225     TRACE("(%p)->(%p %p)\n", This, bind_flags, pbindinfo);
226
227     *bind_flags = 0;
228     if (This->request->async) *bind_flags |= BINDF_ASYNCHRONOUS;
229
230     if (This->request->verb != BINDVERB_GET)
231     {
232         FIXME("only GET verb supported. Got %d\n", This->request->verb);
233         return E_FAIL;
234     }
235
236     pbindinfo->dwBindVerb = This->request->verb;
237
238     return S_OK;
239 }
240
241 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface,
242         DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
243 {
244     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
245
246     FIXME("(%p)->(%08x %d %p %p): stub\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
247
248     return E_NOTIMPL;
249 }
250
251 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface,
252         REFIID riid, IUnknown *punk)
253 {
254     BindStatusCallback *This = impl_from_IBindStatusCallback(iface);
255
256     FIXME("(%p)->(%s %p): stub\n", This, debugstr_guid(riid), punk);
257
258     return E_NOTIMPL;
259 }
260
261 #undef STATUSCLB_THIS
262
263 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
264     BindStatusCallback_QueryInterface,
265     BindStatusCallback_AddRef,
266     BindStatusCallback_Release,
267     BindStatusCallback_OnStartBinding,
268     BindStatusCallback_GetPriority,
269     BindStatusCallback_OnLowResource,
270     BindStatusCallback_OnProgress,
271     BindStatusCallback_OnStopBinding,
272     BindStatusCallback_GetBindInfo,
273     BindStatusCallback_OnDataAvailable,
274     BindStatusCallback_OnObjectAvailable
275 };
276
277 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate *iface,
278         REFIID riid, void **ppv)
279 {
280     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
281     return IBindStatusCallback_QueryInterface((IBindStatusCallback*)This, riid, ppv);
282 }
283
284 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate *iface)
285 {
286     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
287     return IBindStatusCallback_AddRef((IBindStatusCallback*)This);
288 }
289
290 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate *iface)
291 {
292     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
293     return IBindStatusCallback_Release((IBindStatusCallback*)This);
294 }
295
296 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *iface,
297         LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR *add_headers)
298 {
299     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
300
301     FIXME("(%p)->(%s %s %d %p): stub\n", This, debugstr_w(url), debugstr_w(headers), reserved, add_headers);
302
303     *add_headers = NULL;
304
305     return E_NOTIMPL;
306 }
307
308 static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD code,
309         LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders)
310 {
311     BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
312
313     TRACE("(%p)->(%d %s %s %p)\n", This, code, debugstr_w(resp_headers),
314           debugstr_w(req_headers), add_reqheaders);
315
316     return S_OK;
317 }
318
319 #undef HTTPNEG2_THIS
320
321 static const IHttpNegotiateVtbl BSCHttpNegotiateVtbl = {
322     BSCHttpNegotiate_QueryInterface,
323     BSCHttpNegotiate_AddRef,
324     BSCHttpNegotiate_Release,
325     BSCHttpNegotiate_BeginningTransaction,
326     BSCHttpNegotiate_OnResponse
327 };
328
329 static HRESULT BindStatusCallback_create(const httprequest* This, BindStatusCallback **obj)
330 {
331     BindStatusCallback *bsc;
332     IBindCtx *pbc;
333     HRESULT hr;
334
335     hr = CreateBindCtx(0, &pbc);
336     if (hr != S_OK) return hr;
337
338     bsc = heap_alloc(sizeof(*bsc));
339     if (!bsc)
340     {
341         IBindCtx_Release(pbc);
342         return E_OUTOFMEMORY;
343     }
344
345     bsc->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
346     bsc->lpHttpNegotiateVtbl = &BSCHttpNegotiateVtbl;
347     bsc->ref = 1;
348     bsc->request = This;
349     bsc->binding = NULL;
350
351     hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)bsc, NULL, 0);
352     if (hr == S_OK)
353     {
354         IMoniker *moniker;
355
356         hr = CreateURLMoniker(NULL, This->url, &moniker);
357         if (hr == S_OK)
358         {
359             IStream *stream;
360
361             hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (void**)&stream);
362             IMoniker_Release(moniker);
363             if (stream) IStream_Release(stream);
364         }
365         IBindCtx_Release(pbc);
366     }
367
368     if (FAILED(hr))
369     {
370         IBindStatusCallback_Release((IBindStatusCallback*)bsc);
371         bsc = NULL;
372     }
373
374     *obj = bsc;
375     return hr;
376 }
377
378 /* TODO: process OnChange callback */
379 static void httprequest_setreadystate(httprequest *This, READYSTATE state)
380 {
381     This->state = state;
382 }
383
384 static HRESULT WINAPI httprequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject)
385 {
386     httprequest *This = impl_from_IXMLHTTPRequest( iface );
387     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
388
389     if ( IsEqualGUID( riid, &IID_IXMLHTTPRequest) ||
390          IsEqualGUID( riid, &IID_IDispatch) ||
391          IsEqualGUID( riid, &IID_IUnknown) )
392     {
393         *ppvObject = iface;
394     }
395     else
396     {
397         FIXME("Unsupported interface %s\n", debugstr_guid(riid));
398         return E_NOINTERFACE;
399     }
400
401     IXMLHTTPRequest_AddRef( iface );
402
403     return S_OK;
404 }
405
406 static ULONG WINAPI httprequest_AddRef(IXMLHTTPRequest *iface)
407 {
408     httprequest *This = impl_from_IXMLHTTPRequest( iface );
409     ULONG ref = InterlockedIncrement( &This->ref );
410     TRACE("(%p)->(%u)\n", This, ref );
411     return ref;
412 }
413
414 static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
415 {
416     httprequest *This = impl_from_IXMLHTTPRequest( iface );
417     ULONG ref = InterlockedDecrement( &This->ref );
418
419     TRACE("(%p)->(%u)\n", This, ref );
420
421     if ( ref == 0 )
422     {
423         struct reqheader *header, *header2;
424
425         SysFreeString(This->url);
426         SysFreeString(This->user);
427         SysFreeString(This->password);
428
429         /* request headers */
430         LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct reqheader, entry)
431         {
432             list_remove(&header->entry);
433             SysFreeString(header->header);
434             SysFreeString(header->value);
435         }
436
437         /* detach callback object */
438         BindStatusCallback_Detach(This->bsc);
439
440         heap_free( This );
441     }
442
443     return ref;
444 }
445
446 static HRESULT WINAPI httprequest_GetTypeInfoCount(IXMLHTTPRequest *iface, UINT *pctinfo)
447 {
448     httprequest *This = impl_from_IXMLHTTPRequest( iface );
449
450     TRACE("(%p)->(%p)\n", This, pctinfo);
451
452     *pctinfo = 1;
453
454     return S_OK;
455 }
456
457 static HRESULT WINAPI httprequest_GetTypeInfo(IXMLHTTPRequest *iface, UINT iTInfo,
458         LCID lcid, ITypeInfo **ppTInfo)
459 {
460     httprequest *This = impl_from_IXMLHTTPRequest( iface );
461     HRESULT hr;
462
463     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
464
465     hr = get_typeinfo(IXMLHTTPRequest_tid, ppTInfo);
466
467     return hr;
468 }
469
470 static HRESULT WINAPI httprequest_GetIDsOfNames(IXMLHTTPRequest *iface, REFIID riid,
471         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
472 {
473     httprequest *This = impl_from_IXMLHTTPRequest( iface );
474     ITypeInfo *typeinfo;
475     HRESULT hr;
476
477     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
478           lcid, rgDispId);
479
480     if(!rgszNames || cNames == 0 || !rgDispId)
481         return E_INVALIDARG;
482
483     hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
484     if(SUCCEEDED(hr))
485     {
486         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
487         ITypeInfo_Release(typeinfo);
488     }
489
490     return hr;
491 }
492
493 static HRESULT WINAPI httprequest_Invoke(IXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid,
494         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
495         EXCEPINFO *pExcepInfo, UINT *puArgErr)
496 {
497     httprequest *This = impl_from_IXMLHTTPRequest( iface );
498     ITypeInfo *typeinfo;
499     HRESULT hr;
500
501     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
502           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
503
504     hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo);
505     if(SUCCEEDED(hr))
506     {
507         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
508                 pVarResult, pExcepInfo, puArgErr);
509         ITypeInfo_Release(typeinfo);
510     }
511
512     return hr;
513 }
514
515 static HRESULT WINAPI httprequest_open(IXMLHTTPRequest *iface, BSTR method, BSTR url,
516         VARIANT async, VARIANT user, VARIANT password)
517 {
518     httprequest *This = impl_from_IXMLHTTPRequest( iface );
519     HRESULT hr;
520     VARIANT str;
521
522     TRACE("(%p)->(%s %s)\n", This, debugstr_w(method), debugstr_w(url));
523
524     if (!method || !url) return E_INVALIDARG;
525
526     /* free previously set data */
527     SysFreeString(This->url);
528     SysFreeString(This->user);
529     SysFreeString(This->password);
530     This->url = This->user = This->password = NULL;
531
532     if (lstrcmpiW(method, MethodGetW) == 0)
533     {
534         This->verb = BINDVERB_GET;
535     }
536     else if (lstrcmpiW(method, MethodPutW) == 0)
537     {
538         This->verb = BINDVERB_PUT;
539     }
540     else if (lstrcmpiW(method, MethodPostW) == 0)
541     {
542         This->verb = BINDVERB_POST;
543     }
544     else
545     {
546         FIXME("unsupported request type %s\n", debugstr_w(method));
547         This->verb = -1;
548         return E_FAIL;
549     }
550
551     This->url = SysAllocString(url);
552
553     hr = VariantChangeType(&async, &async, 0, VT_BOOL);
554     This->async = hr == S_OK && V_BOOL(&async) == VARIANT_TRUE;
555
556     VariantInit(&str);
557     hr = VariantChangeType(&str, &user, 0, VT_BSTR);
558     if (hr == S_OK)
559         This->user = V_BSTR(&str);
560
561     hr = VariantChangeType(&str, &password, 0, VT_BSTR);
562     if (hr == S_OK)
563         This->password = V_BSTR(&str);
564
565     httprequest_setreadystate(This, READYSTATE_LOADING);
566
567     return S_OK;
568 }
569
570 static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR header, BSTR value)
571 {
572     httprequest *This = impl_from_IXMLHTTPRequest( iface );
573     struct reqheader *entry;
574
575     TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
576
577     if (!header || !*header) return E_INVALIDARG;
578     if (This->state != READYSTATE_LOADING) return E_FAIL;
579     if (!value) return E_INVALIDARG;
580
581     /* replace existing header value if already added */
582     LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct reqheader, entry)
583     {
584         if (lstrcmpW(entry->header, header) == 0)
585         {
586             return SysReAllocString(&entry->value, value) ? S_OK : E_OUTOFMEMORY;
587         }
588     }
589
590     entry = heap_alloc(sizeof(*entry));
591     if (!entry) return E_OUTOFMEMORY;
592
593     /* new header */
594     entry->header = SysAllocString(header);
595     entry->value  = SysAllocString(value);
596
597     list_add_head(&This->reqheaders, &entry->entry);
598
599     return S_OK;
600 }
601
602 static HRESULT WINAPI httprequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR *pbstrValue)
603 {
604     httprequest *This = impl_from_IXMLHTTPRequest( iface );
605
606     FIXME("stub (%p) %s %p\n", This, debugstr_w(bstrHeader), pbstrValue);
607
608     return E_NOTIMPL;
609 }
610
611 static HRESULT WINAPI httprequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *pbstrHeaders)
612 {
613     httprequest *This = impl_from_IXMLHTTPRequest( iface );
614
615     FIXME("stub (%p) %p\n", This, pbstrHeaders);
616
617     return E_NOTIMPL;
618 }
619
620 static HRESULT WINAPI httprequest_send(IXMLHTTPRequest *iface, VARIANT varBody)
621 {
622     httprequest *This = impl_from_IXMLHTTPRequest( iface );
623     BindStatusCallback *bsc = NULL;
624     HRESULT hr;
625
626     TRACE("(%p)\n", This);
627
628     if (This->state != READYSTATE_LOADING) return E_FAIL;
629
630     hr = BindStatusCallback_create(This, &bsc);
631     if (FAILED(hr)) return hr;
632
633     BindStatusCallback_Detach(This->bsc);
634     This->bsc = bsc;
635
636     return hr;
637 }
638
639 static HRESULT WINAPI httprequest_abort(IXMLHTTPRequest *iface)
640 {
641     httprequest *This = impl_from_IXMLHTTPRequest( iface );
642
643     FIXME("stub (%p)\n", This);
644
645     return E_NOTIMPL;
646 }
647
648 static HRESULT WINAPI httprequest_get_status(IXMLHTTPRequest *iface, LONG *plStatus)
649 {
650     httprequest *This = impl_from_IXMLHTTPRequest( iface );
651
652     FIXME("stub %p %p\n", This, plStatus);
653
654     return E_NOTIMPL;
655 }
656
657 static HRESULT WINAPI httprequest_get_statusText(IXMLHTTPRequest *iface, BSTR *pbstrStatus)
658 {
659     httprequest *This = impl_from_IXMLHTTPRequest( iface );
660
661     FIXME("stub %p %p\n", This, pbstrStatus);
662
663     return E_NOTIMPL;
664 }
665
666 static HRESULT WINAPI httprequest_get_responseXML(IXMLHTTPRequest *iface, IDispatch **ppBody)
667 {
668     httprequest *This = impl_from_IXMLHTTPRequest( iface );
669
670     FIXME("stub %p %p\n", This, ppBody);
671
672     return E_NOTIMPL;
673 }
674
675 static HRESULT WINAPI httprequest_get_responseText(IXMLHTTPRequest *iface, BSTR *pbstrBody)
676 {
677     httprequest *This = impl_from_IXMLHTTPRequest( iface );
678
679     FIXME("stub %p %p\n", This, pbstrBody);
680
681     return E_NOTIMPL;
682 }
683
684 static HRESULT WINAPI httprequest_get_responseBody(IXMLHTTPRequest *iface, VARIANT *pvarBody)
685 {
686     httprequest *This = impl_from_IXMLHTTPRequest( iface );
687
688     FIXME("stub %p %p\n", This, pvarBody);
689
690     return E_NOTIMPL;
691 }
692
693 static HRESULT WINAPI httprequest_get_responseStream(IXMLHTTPRequest *iface, VARIANT *pvarBody)
694 {
695     httprequest *This = impl_from_IXMLHTTPRequest( iface );
696
697     FIXME("stub %p %p\n", This, pvarBody);
698
699     return E_NOTIMPL;
700 }
701
702 static HRESULT WINAPI httprequest_get_readyState(IXMLHTTPRequest *iface, LONG *state)
703 {
704     httprequest *This = impl_from_IXMLHTTPRequest( iface );
705
706     TRACE("(%p)->(%p)\n", This, state);
707
708     if (!state) return E_INVALIDARG;
709
710     *state = This->state;
711     return S_OK;
712 }
713
714 static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *pReadyStateSink)
715 {
716     httprequest *This = impl_from_IXMLHTTPRequest( iface );
717
718     FIXME("stub %p %p\n", This, pReadyStateSink);
719
720     return E_NOTIMPL;
721 }
722
723 static const struct IXMLHTTPRequestVtbl dimimpl_vtbl =
724 {
725     httprequest_QueryInterface,
726     httprequest_AddRef,
727     httprequest_Release,
728     httprequest_GetTypeInfoCount,
729     httprequest_GetTypeInfo,
730     httprequest_GetIDsOfNames,
731     httprequest_Invoke,
732     httprequest_open,
733     httprequest_setRequestHeader,
734     httprequest_getResponseHeader,
735     httprequest_getAllResponseHeaders,
736     httprequest_send,
737     httprequest_abort,
738     httprequest_get_status,
739     httprequest_get_statusText,
740     httprequest_get_responseXML,
741     httprequest_get_responseText,
742     httprequest_get_responseBody,
743     httprequest_get_responseStream,
744     httprequest_get_readyState,
745     httprequest_put_onreadystatechange
746 };
747
748 HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
749 {
750     httprequest *req;
751     HRESULT hr = S_OK;
752
753     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
754
755     req = heap_alloc( sizeof (*req) );
756     if( !req )
757         return E_OUTOFMEMORY;
758
759     req->lpVtbl = &dimimpl_vtbl;
760     req->ref = 1;
761
762     req->async = FALSE;
763     req->verb = -1;
764     req->url = req->user = req->password = NULL;
765     req->state = READYSTATE_UNINITIALIZED;
766     req->bsc = NULL;
767     list_init(&req->reqheaders);
768
769     *ppObj = &req->lpVtbl;
770
771     TRACE("returning iface %p\n", *ppObj);
772
773     return hr;
774 }
775
776 #else
777
778 HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
779 {
780     MESSAGE("This program tried to use a XMLHTTPRequest object, but\n"
781             "libxml2 support was not present at compile time.\n");
782     return E_NOTIMPL;
783 }
784
785 #endif