From bcc1fda7276121668a92d8445cefed2777f2adce Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 3 Oct 2008 21:50:59 +1000 Subject: [PATCH] msxml3: Add IXMLHTTPRequest support. --- dlls/msxml3/Makefile.in | 1 + dlls/msxml3/dispex.c | 1 + dlls/msxml3/factory.c | 5 + dlls/msxml3/httprequest.c | 343 ++++++++++++++++++++++++++++++++++++ dlls/msxml3/msxml_private.h | 2 + dlls/msxml3/tests/domdoc.c | 15 +- include/msxml2.idl | 54 ++++++ 7 files changed, 414 insertions(+), 7 deletions(-) create mode 100644 dlls/msxml3/httprequest.c diff --git a/dlls/msxml3/Makefile.in b/dlls/msxml3/Makefile.in index 54650cda2f1..c4293ddd33e 100644 --- a/dlls/msxml3/Makefile.in +++ b/dlls/msxml3/Makefile.in @@ -20,6 +20,7 @@ C_SRCS = \ element.c \ entityref.c \ factory.c \ + httprequest.c \ main.c \ node.c \ nodelist.c \ diff --git a/dlls/msxml3/dispex.c b/dlls/msxml3/dispex.c index 0ccda74bca2..927206879a2 100644 --- a/dlls/msxml3/dispex.c +++ b/dlls/msxml3/dispex.c @@ -94,6 +94,7 @@ static REFIID tid_ids[] = { &IID_IXMLDOMText, &IID_IXMLElement, &IID_IXMLDOMDocument, + &IID_IXMLHTTPRequest, &IID_IVBSAXAttributes, &IID_IVBSAXContentHandler, &IID_IVBSAXDeclHandler, diff --git a/dlls/msxml3/factory.c b/dlls/msxml3/factory.c index beb5bbcf8b2..37dfe01afcc 100644 --- a/dlls/msxml3/factory.c +++ b/dlls/msxml3/factory.c @@ -134,6 +134,7 @@ static xmlcf domdoccf = { &xmlcf_vtbl, DOMDocument_create }; static xmlcf schemacf = { &xmlcf_vtbl, SchemaCache_create }; static xmlcf xmldoccf = { &xmlcf_vtbl, XMLDocument_create }; static xmlcf saxreadcf = { &xmlcf_vtbl, SAXXMLReader_create }; +static xmlcf httpreqcf = { &xmlcf_vtbl, XMLHTTPRequest_create }; /****************************************************************** * DllGetClassObject (MSXML3.@) @@ -169,6 +170,10 @@ HRESULT WINAPI DllGetClassObject( REFCLSID rclsid, REFIID iid, LPVOID *ppv ) { cf = (IClassFactory*) &saxreadcf.lpVtbl; } + else if( IsEqualCLSID( rclsid, &CLSID_XMLHTTPRequest)) + { + cf = (IClassFactory*) &httpreqcf.lpVtbl; + } if ( !cf ) return CLASS_E_CLASSNOTAVAILABLE; diff --git a/dlls/msxml3/httprequest.c b/dlls/msxml3/httprequest.c new file mode 100644 index 00000000000..3c962772d2d --- /dev/null +++ b/dlls/msxml3/httprequest.c @@ -0,0 +1,343 @@ +/* + * IXMLHTTPRequest implementation + * + * Copyright 2008 Alistair Leslie-Hughes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS + +#include "config.h" + +#include +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "ole2.h" +#include "msxml2.h" + +#include "msxml_private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msxml); + +#ifdef HAVE_LIBXML2 + +typedef struct _httprequest +{ + const struct IXMLHTTPRequestVtbl *lpVtbl; + LONG ref; +} httprequest; + +static inline httprequest *impl_from_IXMLHTTPRequest( IXMLHTTPRequest *iface ) +{ + return (httprequest *)((char*)iface - FIELD_OFFSET(httprequest, lpVtbl)); +} + +static HRESULT WINAPI httprequest_QueryInterface(IXMLHTTPRequest *iface, REFIID riid, void **ppvObject) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); + + if ( IsEqualGUID( riid, &IID_IXMLHTTPRequest) || + IsEqualGUID( riid, &IID_IDispatch) || + IsEqualGUID( riid, &IID_IUnknown) ) + { + *ppvObject = iface; + } + else + { + FIXME("Unsupported interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } + + IXMLHTTPRequest_AddRef( iface ); + + return S_OK; +} + +static ULONG WINAPI httprequest_AddRef(IXMLHTTPRequest *iface) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + return InterlockedIncrement( &This->ref ); +} + +ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + ULONG ref; + + ref = InterlockedDecrement( &This->ref ); + if ( ref == 0 ) + { + HeapFree( GetProcessHeap(), 0, This ); + } + + return ref; +} + +static HRESULT WINAPI httprequest_GetTypeInfoCount(IXMLHTTPRequest *iface, UINT *pctinfo) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + TRACE("(%p)->(%p)\n", This, pctinfo); + + *pctinfo = 1; + + return S_OK; +} + +static HRESULT WINAPI httprequest_GetTypeInfo(IXMLHTTPRequest *iface, UINT iTInfo, + LCID lcid, ITypeInfo **ppTInfo) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + HRESULT hr; + + TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); + + hr = get_typeinfo(IXMLHTTPRequest_tid, ppTInfo); + + return hr; +} + +static HRESULT WINAPI httprequest_GetIDsOfNames(IXMLHTTPRequest *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, + lcid, rgDispId); + + if(!rgszNames || cNames == 0 || !rgDispId) + return E_INVALIDARG; + + hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI httprequest_Invoke(IXMLHTTPRequest *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + ITypeInfo *typeinfo; + HRESULT hr; + + TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), + lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + + hr = get_typeinfo(IXMLHTTPRequest_tid, &typeinfo); + if(SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams, + pVarResult, pExcepInfo, puArgErr); + ITypeInfo_Release(typeinfo); + } + + return hr; +} + +static HRESULT WINAPI httprequest_open(IXMLHTTPRequest *iface, BSTR bstrMethod, BSTR bstrUrl, + VARIANT varAsync, VARIANT bstrUser, VARIANT bstrPassword) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub (%p)\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR bstrValue) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub (%p) %s %s\n", This, debugstr_w(bstrHeader), debugstr_w(bstrValue)); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR *pbstrValue) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub (%p) %s %p\n", This, debugstr_w(bstrHeader), pbstrValue); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *pbstrHeaders) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub (%p) %p\n", This, pbstrHeaders); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_send(IXMLHTTPRequest *iface, VARIANT varBody) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub (%p)\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_abort(IXMLHTTPRequest *iface) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub (%p)\n", This); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_get_status(IXMLHTTPRequest *iface, long *plStatus) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, plStatus); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_get_statusText(IXMLHTTPRequest *iface, BSTR *pbstrStatus) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, pbstrStatus); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_get_responseXML(IXMLHTTPRequest *iface, IDispatch **ppBody) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, ppBody); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_get_responseText(IXMLHTTPRequest *iface, BSTR *pbstrBody) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, pbstrBody); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_get_responseBody(IXMLHTTPRequest *iface, VARIANT *pvarBody) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, pvarBody); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_get_responseStream(IXMLHTTPRequest *iface, VARIANT *pvarBody) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, pvarBody); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_get_readyState(IXMLHTTPRequest *iface, long *plState) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, plState); + + return E_NOTIMPL; +} + +static HRESULT WINAPI httprequest_put_onreadystatechange(IXMLHTTPRequest *iface, IDispatch *pReadyStateSink) +{ + httprequest *This = impl_from_IXMLHTTPRequest( iface ); + + FIXME("stub %p %p\n", This, pReadyStateSink); + + return E_NOTIMPL; +} + +static const struct IXMLHTTPRequestVtbl dimimpl_vtbl = +{ + httprequest_QueryInterface, + httprequest_AddRef, + httprequest_Release, + httprequest_GetTypeInfoCount, + httprequest_GetTypeInfo, + httprequest_GetIDsOfNames, + httprequest_Invoke, + httprequest_open, + httprequest_setRequestHeader, + httprequest_getResponseHeader, + httprequest_getAllResponseHeaders, + httprequest_send, + httprequest_abort, + httprequest_get_status, + httprequest_get_statusText, + httprequest_get_responseXML, + httprequest_get_responseText, + httprequest_get_responseBody, + httprequest_get_responseStream, + httprequest_get_readyState, + httprequest_put_onreadystatechange +}; + +HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + httprequest *req; + HRESULT hr = S_OK; + + TRACE("(%p,%p)\n", pUnkOuter, ppObj); + + req = HeapAlloc( GetProcessHeap(), 0, sizeof (*req) ); + if( !req ) + return E_OUTOFMEMORY; + + req->lpVtbl = &dimimpl_vtbl; + req->ref = 1; + + *ppObj = &req->lpVtbl; + + TRACE("returning iface %p\n", *ppObj); + + return hr; +} + +#else + +HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + MESSAGE("This program tried to use a XMLHTTPRequest object, but\n" + "libxml2 support was not present at compile time.\n"); + return E_NOTIMPL; +} + +#endif diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h index 55b84dfa1d8..b3427427861 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -96,6 +96,7 @@ extern HRESULT DOMDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); extern HRESULT SchemaCache_create( IUnknown *pUnkOuter, LPVOID *ppObj ); extern HRESULT XMLDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj ); extern HRESULT SAXXMLReader_create(IUnknown *pUnkOuter, LPVOID *ppObj ); +extern HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, LPVOID *ppObj); typedef struct bsc_t bsc_t; @@ -122,6 +123,7 @@ typedef enum tid_t { IXMLDOMText_tid, IXMLElement_tid, IXMLDocument_tid, + IXMLHTTPRequest_tid, IVBSAXAttributes_tid, IVBSAXContentHandler_tid, IVBSAXDeclHandler_tid, diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 03b201b8f90..9bc14699b79 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -1998,9 +1998,7 @@ static void test_XMLHTTP(void) HRESULT hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLHttpRequest, (void **)&pXMLHttpRequest); - todo_wine { ok(hr == S_OK, "CoCreateInstance(CLSID_XMLHTTPRequest) should have succeeded instead of failing with 0x%08x\n", hr); - } if (hr != S_OK) return; @@ -2014,18 +2012,21 @@ static void test_XMLHTTP(void) V_BSTR(&varbody) = SysAllocString(wszBody); hr = IXMLHttpRequest_open(pXMLHttpRequest, wszPOST, wszUrl, varfalse, dummy, dummy); - ok(hr == S_OK, "IXMLHttpRequest_open should have succeeded instead of failing with 0x%08x\n", hr); + todo_wine ok(hr == S_OK, "IXMLHttpRequest_open should have succeeded instead of failing with 0x%08x\n", hr); hr = IXMLHttpRequest_send(pXMLHttpRequest, varbody); - ok(hr == S_OK, "IXMLHttpRequest_send should have succeeded instead of failing with 0x%08x\n", hr); + todo_wine ok(hr == S_OK, "IXMLHttpRequest_send should have succeeded instead of failing with 0x%08x\n", hr); VariantClear(&varbody); hr = IXMLHttpRequest_get_responseText(pXMLHttpRequest, &bstrResponse); - ok(hr == S_OK, "IXMLHttpRequest_get_responseText should have succeeded instead of failing with 0x%08x\n", hr); + todo_wine ok(hr == S_OK, "IXMLHttpRequest_get_responseText should have succeeded instead of failing with 0x%08x\n", hr); /* the server currently returns "FAILED" because the Content-Type header is * not what the server expects */ - ok(!memcmp(bstrResponse, wszExpectedResponse, sizeof(wszExpectedResponse)), "bstrResponse differs from what was expected\n"); - SysFreeString(bstrResponse); + if(hr == S_OK) + { + ok(!memcmp(bstrResponse, wszExpectedResponse, sizeof(wszExpectedResponse)), "bstrResponse differs from what was expected\n"); + SysFreeString(bstrResponse); + } } static void test_IXMLDOMDocument2(void) diff --git a/include/msxml2.idl b/include/msxml2.idl index eae84c4db36..49d057c2b4e 100644 --- a/include/msxml2.idl +++ b/include/msxml2.idl @@ -960,6 +960,60 @@ interface IXSLTemplate : IDispatch [retval, out] IXSLProcessor **ppProcessor); } +[ + object, + uuid(ED8C108D-4349-11D2-91A4-00C04F7969E8), + odl, + dual, + oleautomation, + pointer_default(unique) +] +interface IXMLHTTPRequest : IDispatch +{ + [id(1)] + HRESULT open([in] BSTR bstrMethod, [in] BSTR bstrUrl, [in, optional] VARIANT varAsync, + [in,optional] VARIANT username, [in,optional] VARIANT password); + + [id(2)] + HRESULT setRequestHeader([in] BSTR bstrHeader, [in] BSTR bstrValue); + + [id(3)] + HRESULT getResponseHeader([in] BSTR bstrHeader, [out, retval] BSTR * value); + + [id(4)] + HRESULT getAllResponseHeaders([out, retval] BSTR * pbstrHeaders); + + [id(5)] + HRESULT send([in, optional] VARIANT body); + + [id(6)] + HRESULT abort(); + + [propget, id(7)] + HRESULT status([out, retval] long *pStatus); + + [propget, id(8)] + HRESULT statusText([out, retval] BSTR *pStatus); + + [propget, id(9)] + HRESULT responseXML([out, retval] IDispatch **pBody); + + [propget, id(10)] + HRESULT responseText([out, retval] BSTR *pBody); + + [propget, id(11)] + HRESULT responseBody([out, retval] VARIANT *pBody); + + [propget, id(12)] + HRESULT responseStream([out, retval] VARIANT *pBody); + + [propget, id(13)] + HRESULT readyState([out, retval] long *pState); + + [propput, id(14)] + HRESULT onreadystatechange([in] IDispatch *pReadyStateSink); +}; + [ local, object,