[PATCH] Add IXMLHTTPRequest support

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Fri Oct 3 06:50:59 CDT 2008


---
 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 54650cd..c4293dd 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 0ccda74..9272068 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 beb5bbc..37dfe01 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 0000000..ef26570
--- /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 <stdarg.h>
+#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 httpreques_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 httpreques_AddRef(IXMLHTTPRequest *iface)
+{
+    httprequest *This = impl_from_IXMLHTTPRequest( iface );
+    return InterlockedIncrement( &This->ref );
+}
+
+ULONG WINAPI httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *pbstrHeaders)
+{
+    httprequest *This = impl_from_IXMLHTTPRequest( iface );
+
+    FIXME("stub (%p) %p\n", This, pbstrHeaders);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI httpreques_send(IXMLHTTPRequest *iface, VARIANT varBody)
+{
+    httprequest *This = impl_from_IXMLHTTPRequest( iface );
+
+    FIXME("stub (%p)\n", This);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI httpreques_abort(IXMLHTTPRequest *iface)
+{
+    httprequest *This = impl_from_IXMLHTTPRequest( iface );
+
+    FIXME("stub (%p)\n", This);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 httpreques_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 =
+{
+    httpreques_QueryInterface,
+    httpreques_AddRef,
+    httpreques_Release,
+    httpreques_GetTypeInfoCount,
+    httpreques_GetTypeInfo,
+    httpreques_GetIDsOfNames,
+    httpreques_Invoke,
+    httpreques_open,
+    httpreques_setRequestHeader,
+    httpreques_getResponseHeader,
+    httpreques_getAllResponseHeaders,
+    httpreques_send,
+    httpreques_abort,
+    httpreques_get_status,
+    httpreques_get_statusText,
+    httpreques_get_responseXML,
+    httpreques_get_responseText,
+    httpreques_get_responseBody,
+    httpreques_get_responseStream,
+    httpreques_get_readyState,
+    httpreques_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 55b84df..b342742 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 aeb53d7..96f84cd 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 eae84c4..49d057c 100644
--- a/include/msxml2.idl
+++ b/include/msxml2.idl
@@ -961,6 +961,60 @@ interface IXSLTemplate : IDispatch
 } 
 
 [
+    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,
 uuid (3efaa426-272f-11d2-836f-0000f87a7782)
-- 
1.5.4.3


--------------000501020002080506090807--



More information about the wine-patches mailing list