>From 9cf7af2edac0361ffcd2a399174d16c2fbdfb2a3 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Sat, 19 Nov 2011 16:33:10 +0300
Subject: [PATCH 1/4] Added common ISupportErrorInfo implementation

---
 dlls/msxml3/attribute.c     |   10 ++++
 dlls/msxml3/cdata.c         |   10 ++++
 dlls/msxml3/comment.c       |   10 ++++
 dlls/msxml3/dispex.c        |   18 +++++--
 dlls/msxml3/docfrag.c       |   10 ++++
 dlls/msxml3/domdoc.c        |   52 +++----------------
 dlls/msxml3/element.c       |   10 ++++
 dlls/msxml3/entityref.c     |   10 ++++
 dlls/msxml3/msxml_private.h |    2 +
 dlls/msxml3/node.c          |   91 ++++++++++++++++++++++++++++++++
 dlls/msxml3/pi.c            |   10 ++++
 dlls/msxml3/tests/domdoc.c  |  121 +++++++++++++++++++++++++++++++++++++------
 12 files changed, 288 insertions(+), 66 deletions(-)

diff --git a/dlls/msxml3/attribute.c b/dlls/msxml3/attribute.c
index fc96658..a78d10b 100644
--- a/dlls/msxml3/attribute.c
+++ b/dlls/msxml3/attribute.c
@@ -50,6 +50,12 @@ typedef struct _domattr
     LONG ref;
 } domattr;
 
+static const tid_t domattr_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMAttribute_tid,
+    0
+};
+
 static inline domattr *impl_from_IXMLDOMAttribute( IXMLDOMAttribute *iface )
 {
     return CONTAINING_RECORD(iface, domattr, IXMLDOMAttribute_iface);
@@ -74,6 +80,10 @@ static HRESULT WINAPI domattr_QueryInterface(
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
     }
+    else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+    {
+        return node_create_supporterrorinfo(domattr_se_tids, ppvObject);
+    }
     else
     {
         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
diff --git a/dlls/msxml3/cdata.c b/dlls/msxml3/cdata.c
index 348abb8..cd42db0 100644
--- a/dlls/msxml3/cdata.c
+++ b/dlls/msxml3/cdata.c
@@ -49,6 +49,12 @@ typedef struct _domcdata
     LONG ref;
 } domcdata;
 
+static const tid_t domcdata_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMCDATASection_tid,
+    0
+};
+
 static inline domcdata *impl_from_IXMLDOMCDATASection( IXMLDOMCDATASection *iface )
 {
     return CONTAINING_RECORD(iface, domcdata, IXMLDOMCDATASection_iface);
@@ -74,6 +80,10 @@ static HRESULT WINAPI domcdata_QueryInterface(
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
     }
+    else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+    {
+        return node_create_supporterrorinfo(domcdata_se_tids, ppvObject);
+    }
     else
     {
         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
diff --git a/dlls/msxml3/comment.c b/dlls/msxml3/comment.c
index 6ae9965..8aa10ff 100644
--- a/dlls/msxml3/comment.c
+++ b/dlls/msxml3/comment.c
@@ -49,6 +49,12 @@ typedef struct _domcomment
     LONG ref;
 } domcomment;
 
+static const tid_t domcomment_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMComment_tid,
+    0
+};
+
 static inline domcomment *impl_from_IXMLDOMComment( IXMLDOMComment *iface )
 {
     return CONTAINING_RECORD(iface, domcomment, IXMLDOMComment_iface);
@@ -74,6 +80,10 @@ static HRESULT WINAPI domcomment_QueryInterface(
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
     }
+    else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+    {
+        return node_create_supporterrorinfo(domcomment_se_tids, ppvObject);
+    }
     else
     {
         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
diff --git a/dlls/msxml3/dispex.c b/dlls/msxml3/dispex.c
index 6c74173..bcf528d 100644
--- a/dlls/msxml3/dispex.c
+++ b/dlls/msxml3/dispex.c
@@ -151,9 +151,19 @@ static tid_id_t tid_ids[] = {
     { &IID_IVBMXNamespaceManager, LibXml2 }
 };
 
+inline REFIID get_riid_from_tid(tid_t tid)
+{
+    return tid_ids[tid].iid;
+}
+
+static inline unsigned get_libid_from_tid(tid_t tid)
+{
+    return tid_ids[tid].lib;
+}
+
 HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
 {
-    unsigned lib = tid_ids[tid].lib;
+    unsigned lib = get_libid_from_tid(tid);
     HRESULT hres;
 
     if(!typelib[lib]) {
@@ -172,10 +182,10 @@ HRESULT get_typeinfo(enum tid_t tid, ITypeInfo **typeinfo)
     if(!typeinfos[tid]) {
         ITypeInfo *ti;
 
-        hres = ITypeLib_GetTypeInfoOfGuid(typelib[lib], tid_ids[tid].iid, &ti);
+        hres = ITypeLib_GetTypeInfoOfGuid(typelib[lib], get_riid_from_tid(tid), &ti);
         if(FAILED(hres)) {
             /* try harder with typelib from msxml.dll */
-            hres = ITypeLib_GetTypeInfoOfGuid(typelib[LibXml], tid_ids[tid].iid, &ti);
+            hres = ITypeLib_GetTypeInfoOfGuid(typelib[LibXml], get_riid_from_tid(tid), &ti);
             if(FAILED(hres)) {
                 ERR("GetTypeInfoOfGuid failed: %08x\n", hres);
                 return hres;
@@ -581,7 +591,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
         return hres;
     }
 
-    hres = IUnknown_QueryInterface(This->outer, tid_ids[data->funcs[n].tid].iid, (void**)&unk);
+    hres = IUnknown_QueryInterface(This->outer, get_riid_from_tid(data->funcs[n].tid), (void**)&unk);
     if(FAILED(hres)) {
         ERR("Could not get iface: %08x\n", hres);
         return E_FAIL;
diff --git a/dlls/msxml3/docfrag.c b/dlls/msxml3/docfrag.c
index 892ed4b..8c01690 100644
--- a/dlls/msxml3/docfrag.c
+++ b/dlls/msxml3/docfrag.c
@@ -49,6 +49,12 @@ typedef struct _domfrag
     LONG ref;
 } domfrag;
 
+static const tid_t domfrag_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMDocumentFragment_tid,
+    0
+};
+
 static inline domfrag *impl_from_IXMLDOMDocumentFragment( IXMLDOMDocumentFragment *iface )
 {
     return CONTAINING_RECORD(iface, domfrag, IXMLDOMDocumentFragment_iface);
@@ -73,6 +79,10 @@ static HRESULT WINAPI domfrag_QueryInterface(
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
     }
+    else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+    {
+        return node_create_supporterrorinfo(domfrag_se_tids, ppvObject);
+    }
     else
     {
         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index 30b63de..2f67781 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -123,7 +123,6 @@ struct domdoc
     IPersistStreamInit        IPersistStreamInit_iface;
     IObjectWithSite           IObjectWithSite_iface;
     IObjectSafety             IObjectSafety_iface;
-    ISupportErrorInfo         ISupportErrorInfo_iface;
     IConnectionPointContainer IConnectionPointContainer_iface;
     LONG ref;
     VARIANT_BOOL async;
@@ -652,11 +651,6 @@ static inline domdoc *impl_from_IObjectSafety(IObjectSafety *iface)
     return CONTAINING_RECORD(iface, domdoc, IObjectSafety_iface);
 }
 
-static inline domdoc *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
-{
-    return CONTAINING_RECORD(iface, domdoc, ISupportErrorInfo_iface);
-}
-
 static inline domdoc *impl_from_IConnectionPointContainer(IConnectionPointContainer *iface)
 {
     return CONTAINING_RECORD(iface, domdoc, IConnectionPointContainer_iface);
@@ -813,46 +807,15 @@ static const IPersistStreamInitVtbl xmldoc_IPersistStreamInit_VTable =
     domdoc_IPersistStreamInit_InitNew
 };
 
-/* ISupportErrorInfo interface */
-static HRESULT WINAPI support_error_QueryInterface(
-    ISupportErrorInfo *iface,
-    REFIID riid, void** ppvObj )
-{
-    domdoc *This = impl_from_ISupportErrorInfo(iface);
-    return IXMLDOMDocument3_QueryInterface(&This->IXMLDOMDocument3_iface, riid, ppvObj);
-}
-
-static ULONG WINAPI support_error_AddRef(
-    ISupportErrorInfo *iface )
-{
-    domdoc *This = impl_from_ISupportErrorInfo(iface);
-    return IXMLDOMDocument3_AddRef(&This->IXMLDOMDocument3_iface);
-}
+/* IXMLDOMDocument3 interface */
 
-static ULONG WINAPI support_error_Release(
-    ISupportErrorInfo *iface )
-{
-    domdoc *This = impl_from_ISupportErrorInfo(iface);
-    return IXMLDOMDocument3_Release(&This->IXMLDOMDocument3_iface);
-}
-
-static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
-    ISupportErrorInfo *iface,
-    REFIID riid )
-{
-    FIXME("(%p)->(%s)\n", iface, debugstr_guid(riid));
-    return S_FALSE;
-}
-
-static const struct ISupportErrorInfoVtbl support_error_vtbl =
-{
-    support_error_QueryInterface,
-    support_error_AddRef,
-    support_error_Release,
-    support_error_InterfaceSupportsErrorInfo
+static const tid_t domdoc_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMDocument_tid,
+    IXMLDOMDocument2_tid,
+    0
 };
 
-/* IXMLDOMDocument2 interface */
 static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID riid, void** ppvObject )
 {
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
@@ -885,7 +848,7 @@ static HRESULT WINAPI domdoc_QueryInterface( IXMLDOMDocument3 *iface, REFIID rii
     }
     else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
     {
-        *ppvObject = &This->ISupportErrorInfo_iface;
+        return node_create_supporterrorinfo(domdoc_se_tids, ppvObject);
     }
     else if(node_query_interface(&This->node, riid, ppvObject))
     {
@@ -3473,7 +3436,6 @@ HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
     doc->IPersistStreamInit_iface.lpVtbl = &xmldoc_IPersistStreamInit_VTable;
     doc->IObjectWithSite_iface.lpVtbl = &domdocObjectSite;
     doc->IObjectSafety_iface.lpVtbl = &domdocObjectSafetyVtbl;
-    doc->ISupportErrorInfo_iface.lpVtbl = &support_error_vtbl;
     doc->IConnectionPointContainer_iface.lpVtbl = &ConnectionPointContainerVtbl;
     doc->ref = 1;
     doc->async = VARIANT_TRUE;
diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c
index 57fef4c..08a9d1e 100644
--- a/dlls/msxml3/element.c
+++ b/dlls/msxml3/element.c
@@ -55,6 +55,12 @@ typedef struct _domelem
 
 static const struct nodemap_funcs domelem_attr_map;
 
+static const tid_t domelem_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMElement_tid,
+    0
+};
+
 static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
 {
     return CONTAINING_RECORD(iface, domelem, IXMLDOMElement_iface);
@@ -85,6 +91,10 @@ static HRESULT WINAPI domelem_QueryInterface(
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
     }
+    else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+    {
+        return node_create_supporterrorinfo(domelem_se_tids, ppvObject);
+    }
     else
     {
         TRACE("interface %s not implemented\n", debugstr_guid(riid));
diff --git a/dlls/msxml3/entityref.c b/dlls/msxml3/entityref.c
index 091b3d7..dd6c699 100644
--- a/dlls/msxml3/entityref.c
+++ b/dlls/msxml3/entityref.c
@@ -49,6 +49,12 @@ typedef struct _entityref
     LONG ref;
 } entityref;
 
+static const tid_t domentityref_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMEntityReference_tid,
+    0
+};
+
 static inline entityref *impl_from_IXMLDOMEntityReference( IXMLDOMEntityReference *iface )
 {
     return CONTAINING_RECORD(iface, entityref, IXMLDOMEntityReference_iface);
@@ -73,6 +79,10 @@ static HRESULT WINAPI entityref_QueryInterface(
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
     }
+    else if (IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+    {
+        return node_create_supporterrorinfo(domentityref_se_tids, ppvObject);
+    }
     else
     {
         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 9a51886..65f2834 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -156,6 +156,7 @@ extern HINSTANCE MSXML_hInstance DECLSPEC_HIDDEN;
 void init_dispex(DispatchEx*,IUnknown*,dispex_static_data_t*) DECLSPEC_HIDDEN;
 void release_dispex(DispatchEx*) DECLSPEC_HIDDEN;
 BOOL dispex_query_interface(DispatchEx*,REFIID,void**) DECLSPEC_HIDDEN;
+REFIID get_riid_from_tid(enum tid_t tid) DECLSPEC_HIDDEN;
 
 /* memory allocation functions */
 
@@ -336,6 +337,7 @@ extern HRESULT node_get_text(const xmlnode*,BSTR*) DECLSPEC_HIDDEN;
 extern HRESULT node_select_nodes(const xmlnode*,BSTR,IXMLDOMNodeList**) DECLSPEC_HIDDEN;
 extern HRESULT node_select_singlenode(const xmlnode*,BSTR,IXMLDOMNode**) DECLSPEC_HIDDEN;
 extern HRESULT node_transform_node(const xmlnode*,IXMLDOMNode*,BSTR*) DECLSPEC_HIDDEN;
+extern HRESULT node_create_supporterrorinfo(const tid_t*,void**) DECLSPEC_HIDDEN;
 
 extern HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document) DECLSPEC_HIDDEN;
 
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index 38102ec..290019e 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -116,6 +116,97 @@ BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv)
     return dispex_query_interface(&This->dispex, riid, ppv);
 }
 
+/* common ISupportErrorInfo implementation */
+typedef struct {
+   ISupportErrorInfo ISupportErrorInfo_iface;
+   LONG ref;
+
+   const tid_t* iids;
+} SupportErrorInfo;
+
+static inline SupportErrorInfo *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface)
+{
+    return CONTAINING_RECORD(iface, SupportErrorInfo, ISupportErrorInfo_iface);
+}
+
+static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **obj)
+{
+    SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
+    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
+
+    *obj = NULL;
+
+    if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISupportErrorInfo)) {
+        *obj = iface;
+        ISupportErrorInfo_AddRef(iface);
+        return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface)
+{
+    SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p)->(%d)\n", This, ref );
+    return ref;
+}
+
+static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface)
+{
+    SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
+    LONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p)->(%d)\n", This, ref);
+
+    if (ref == 0)
+        heap_free(This);
+
+    return ref;
+}
+
+static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid)
+{
+    SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface);
+    enum tid_t const *tid;
+
+    TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
+
+    tid = This->iids;
+    while (*tid)
+    {
+        if (IsEqualGUID(riid, get_riid_from_tid(*tid)))
+            return S_OK;
+        tid++;
+    }
+
+    return S_FALSE;
+}
+
+static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl = {
+    SupportErrorInfo_QueryInterface,
+    SupportErrorInfo_AddRef,
+    SupportErrorInfo_Release,
+    SupportErrorInfo_InterfaceSupportsErrorInfo
+};
+
+HRESULT node_create_supporterrorinfo(enum tid_t const *iids, void **obj)
+{
+    SupportErrorInfo *This;
+
+    This = heap_alloc(sizeof(*This));
+    if (!This) return E_OUTOFMEMORY;
+
+    This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl;
+    This->ref = 1;
+    This->iids = iids;
+
+    *obj = &This->ISupportErrorInfo_iface;
+
+    return S_OK;
+}
+
 xmlnode *get_node_obj(IXMLDOMNode *node)
 {
     xmlnode *obj = NULL;
diff --git a/dlls/msxml3/pi.c b/dlls/msxml3/pi.c
index b7a9c3a..23027a1 100644
--- a/dlls/msxml3/pi.c
+++ b/dlls/msxml3/pi.c
@@ -51,6 +51,12 @@ typedef struct _dom_pi
 
 static const struct nodemap_funcs dom_pi_attr_map;
 
+static const tid_t dompi_se_tids[] = {
+    IXMLDOMNode_tid,
+    IXMLDOMProcessingInstruction_tid,
+    0
+};
+
 static inline dom_pi *impl_from_IXMLDOMProcessingInstruction( IXMLDOMProcessingInstruction *iface )
 {
     return CONTAINING_RECORD(iface, dom_pi, IXMLDOMProcessingInstruction_iface);
@@ -75,6 +81,10 @@ static HRESULT WINAPI dom_pi_QueryInterface(
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
     }
+    else if(IsEqualGUID( riid, &IID_ISupportErrorInfo ))
+    {
+        return node_create_supporterrorinfo(dompi_se_tids, ppvObject);
+    }
     else
     {
         TRACE("Unsupported interface %s\n", debugstr_guid(riid));
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 1a12c11..03d19c1 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -2023,11 +2023,10 @@ static void test_domdoc( void )
     IXMLDOMAttribute *node_attr = NULL;
     IXMLDOMNode *nodeChild = NULL;
     IXMLDOMProcessingInstruction *nodePI = NULL;
-    ISupportErrorInfo *support_error = NULL;
     VARIANT_BOOL b;
     VARIANT var;
     BSTR str;
-    LONG code;
+    LONG code, ref;
     LONG nLength = 0;
     WCHAR buff[100];
     const char **ptr;
@@ -2667,17 +2666,8 @@ if (0)
         IXMLDOMProcessingInstruction_Release(nodePI);
     }
 
-    r = IXMLDOMDocument_QueryInterface( doc, &IID_ISupportErrorInfo, (void**)&support_error );
-    ok( r == S_OK, "ret %08x\n", r );
-    if(r == S_OK)
-    {
-        r = ISupportErrorInfo_InterfaceSupportsErrorInfo( support_error, &IID_IXMLDOMDocument );
-        todo_wine ok( r == S_OK, "ret %08x\n", r );
-        ISupportErrorInfo_Release( support_error );
-    }
-
-    r = IXMLDOMDocument_Release( doc );
-    ok( r == 0, "document ref count incorrect\n");
+    ref = IXMLDOMDocument_Release( doc );
+    ok( ref == 0, "got %d\n", ref);
 
     free_bstrs();
 }
@@ -2830,10 +2820,7 @@ static void test_domnode( void )
         ok( r == S_OK, "ret %08x\n", r );
 
         r = ISupportErrorInfo_InterfaceSupportsErrorInfo( support_error, &IID_IXMLDOMNamedNodeMap );
-todo_wine
-{
-        ok( r == S_OK, "ret %08x\n", r );
-}
+        todo_wine EXPECT_HR(r, S_OK);
         ISupportErrorInfo_Release( support_error );
 
         str = SysAllocString( szdl );
@@ -10706,6 +10693,105 @@ static void test_getAttributeNode(void)
     free_bstrs();
 }
 
+typedef struct {
+    DOMNodeType type;
+    const char *name;
+    REFIID iids[3];
+} supporterror_t;
+
+static const supporterror_t supporterror_test[] = {
+    { NODE_ELEMENT,                "element",   { &IID_IXMLDOMNode, &IID_IXMLDOMElement } },
+    { NODE_ATTRIBUTE,              "attribute", { &IID_IXMLDOMNode, &IID_IXMLDOMAttribute } },
+    { NODE_CDATA_SECTION,          "cdata",     { &IID_IXMLDOMNode, &IID_IXMLDOMCDATASection } },
+    { NODE_ENTITY_REFERENCE,       "entityref", { &IID_IXMLDOMNode, &IID_IXMLDOMEntityReference } },
+    { NODE_PROCESSING_INSTRUCTION, "pi",        { &IID_IXMLDOMNode, &IID_IXMLDOMProcessingInstruction } },
+    { NODE_COMMENT,                "comment",   { &IID_IXMLDOMNode, &IID_IXMLDOMComment } },
+    { NODE_DOCUMENT_FRAGMENT,      "fragment",  { &IID_IXMLDOMNode, &IID_IXMLDOMDocumentFragment } },
+    { NODE_INVALID }
+};
+
+static void test_supporterrorinfo(void)
+{
+    static REFIID iids[3] = { &IID_IXMLDOMDocument, &IID_IXMLDOMDocument2 };
+    const supporterror_t *ptr = supporterror_test;
+    ISupportErrorInfo *errorinfo, *info2;
+    IXMLDOMDocument *doc;
+    IUnknown *unk;
+    REFIID *iid;
+    HRESULT hr;
+
+    doc = create_document_version(60, &IID_IXMLDOMDocument3);
+    if (!doc) return;
+
+    EXPECT_REF(doc, 1);
+    hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&errorinfo);
+    EXPECT_HR(hr, S_OK);
+    EXPECT_REF(doc, 1);
+    ISupportErrorInfo_AddRef(errorinfo);
+    EXPECT_REF(errorinfo, 2);
+    EXPECT_REF(doc, 1);
+    ISupportErrorInfo_Release(errorinfo);
+
+    hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&info2);
+    EXPECT_HR(hr, S_OK);
+    ok(errorinfo != info2, "got %p, %p\n", info2, errorinfo);
+    ISupportErrorInfo_Release(info2);
+
+    iid = iids;
+    while (*iid)
+    {
+        hr = IXMLDOMDocument_QueryInterface(doc, *iid, (void**)&unk);
+        EXPECT_HR(hr, S_OK);
+        if (hr == S_OK)
+        {
+            hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
+            ok(hr == S_OK, "got 0x%08x for %s\n", hr, debugstr_guid(*iid));
+            IUnknown_Release(unk);
+        }
+
+        iid++;
+    }
+
+    ISupportErrorInfo_Release(errorinfo);
+
+    while (ptr->type != NODE_INVALID)
+    {
+        IXMLDOMNode *node;
+        VARIANT type;
+
+        V_VT(&type) = VT_I1;
+        V_I1(&type) = ptr->type;
+
+        hr = IXMLDOMDocument_createNode(doc, type, _bstr_(ptr->name), NULL, &node);
+        ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
+
+        hr = IXMLDOMNode_QueryInterface(node, &IID_ISupportErrorInfo, (void**)&errorinfo);
+        ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
+
+        iid = ptr->iids;
+
+        while (*iid)
+        {
+            hr = IXMLDOMNode_QueryInterface(node, *iid, (void**)&unk);
+            if (hr == S_OK)
+            {
+                hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
+                ok(hr == S_OK, "%d: got 0x%08x for %s\n", ptr->type, hr, debugstr_guid(*iid));
+                IUnknown_Release(unk);
+            }
+
+            iid++;
+        }
+
+        ISupportErrorInfo_Release(errorinfo);
+        IXMLDOMNode_Release(node);
+        ptr++;
+    }
+
+    IXMLDOMDocument_Release(doc);
+    free_bstrs();
+}
+
 START_TEST(domdoc)
 {
     IXMLDOMDocument *doc;
@@ -10780,6 +10866,7 @@ START_TEST(domdoc)
     test_dispex();
     test_parseerror();
     test_getAttributeNode();
+    test_supporterrorinfo();
 
     test_xsltemplate();
 
-- 
1.5.6.5


