Nikolay Sivov : msxml3: Add IEnumVARIANT support for IXMLDOMNodeList.

Alexandre Julliard julliard at winehq.org
Mon Jul 2 13:22:02 CDT 2012


Module: wine
Branch: master
Commit: 03ad0acfad45ea4a6a992645e6fa2c17f6165fd6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=03ad0acfad45ea4a6a992645e6fa2c17f6165fd6

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sun Jul  1 01:12:12 2012 +0400

msxml3: Add IEnumVARIANT support for IXMLDOMNodeList.

---

 dlls/msxml3/msxml_private.h |    8 ++++++++
 dlls/msxml3/nodelist.c      |   31 +++++++++++++++++++++++++++----
 dlls/msxml3/selection.c     |   16 ++++------------
 dlls/msxml3/tests/domdoc.c  |   43 ++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 79 insertions(+), 19 deletions(-)

diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 3a2efb0..4aafc29 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -256,6 +256,13 @@ struct nodemap_funcs
     HRESULT (*next_node)(const xmlNodePtr,LONG*,IXMLDOMNode**);
 };
 
+/* used by IEnumVARIANT to access outer object items */
+struct enumvariant_funcs
+{
+    HRESULT (*get_item)(IUnknown*, LONG, IDispatch**);
+    HRESULT (*next)(IUnknown*);
+};
+
 /* constructors */
 extern IUnknown         *create_domdoc( xmlNodePtr ) DECLSPEC_HIDDEN;
 extern IUnknown         *create_xmldoc( void ) DECLSPEC_HIDDEN;
@@ -273,6 +280,7 @@ extern IUnknown         *create_doc_fragment( xmlNodePtr ) DECLSPEC_HIDDEN;
 extern IUnknown         *create_doc_entity_ref( xmlNodePtr ) DECLSPEC_HIDDEN;
 extern IUnknown         *create_doc_type( xmlNodePtr ) DECLSPEC_HIDDEN;
 extern HRESULT           create_selection( xmlNodePtr, xmlChar*, IXMLDOMNodeList** ) DECLSPEC_HIDDEN;
+extern HRESULT           create_enumvariant( IUnknown*, BOOL, const struct enumvariant_funcs*, IEnumVARIANT**) DECLSPEC_HIDDEN;
 
 /* data accessors */
 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ) DECLSPEC_HIDDEN;
diff --git a/dlls/msxml3/nodelist.c b/dlls/msxml3/nodelist.c
index f948fcf..7e46d40 100644
--- a/dlls/msxml3/nodelist.c
+++ b/dlls/msxml3/nodelist.c
@@ -52,15 +52,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
 
 #ifdef HAVE_LIBXML2
 
-typedef struct _xmlnodelist
+typedef struct
 {
     DispatchEx dispex;
     IXMLDOMNodeList IXMLDOMNodeList_iface;
     LONG ref;
     xmlNodePtr parent;
     xmlNodePtr current;
+    IEnumVARIANT *enumvariant;
 } xmlnodelist;
 
+static HRESULT nodelist_get_item(IUnknown *iface, LONG index, IDispatch** item)
+{
+    return IXMLDOMNodeList_get_item((IXMLDOMNodeList*)iface, index, (IXMLDOMNode**)item);
+}
+
+static const struct enumvariant_funcs nodelist_enumvariant = {
+    nodelist_get_item,
+    NULL
+};
+
 static inline xmlnodelist *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface )
 {
     return CONTAINING_RECORD(iface, xmlnodelist, IXMLDOMNodeList_iface);
@@ -81,6 +92,16 @@ static HRESULT WINAPI xmlnodelist_QueryInterface(
     {
         *ppvObject = iface;
     }
+    else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
+    {
+        if (!This->enumvariant)
+        {
+            HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &nodelist_enumvariant, &This->enumvariant);
+            if (FAILED(hr)) return hr;
+        }
+
+        return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
+    }
     else if (dispex_query_interface(&This->dispex, riid, ppvObject))
     {
         return *ppvObject ? S_OK : E_NOINTERFACE;
@@ -116,6 +137,7 @@ static ULONG WINAPI xmlnodelist_Release(
     if ( ref == 0 )
     {
         xmldoc_release( This->parent->doc );
+        if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
         heap_free( This );
     }
 
@@ -261,11 +283,11 @@ static HRESULT WINAPI xmlnodelist_reset(
 
 static HRESULT WINAPI xmlnodelist__newEnum(
         IXMLDOMNodeList* iface,
-        IUnknown** ppUnk)
+        IUnknown** enumv)
 {
     xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
-    FIXME("(%p)->(%p)\n", This, ppUnk);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%p)\n", This, enumv);
+    return create_enumvariant((IUnknown*)iface, TRUE, &nodelist_enumvariant, (IEnumVARIANT**)enumv);
 }
 
 static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl =
@@ -362,6 +384,7 @@ IXMLDOMNodeList* create_children_nodelist( xmlNodePtr node )
     This->ref = 1;
     This->parent = node;
     This->current = node->children;
+    This->enumvariant = NULL;
     xmldoc_add_ref( node->doc );
 
     init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNodeList_iface, &xmlnodelist_dispex);
diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c
index b41e323..bf5fe61 100644
--- a/dlls/msxml3/selection.c
+++ b/dlls/msxml3/selection.c
@@ -59,12 +59,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
 int registerNamespaces(xmlXPathContextPtr ctxt);
 xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str);
 
-struct enumvariant_funcs
-{
-    HRESULT (*get_item)(IUnknown*, LONG, IDispatch**);
-    HRESULT (*next)(IUnknown*);
-};
-
 typedef struct
 {
     IEnumVARIANT IEnumVARIANT_iface;
@@ -117,8 +111,6 @@ static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
     return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface);
 }
 
-static HRESULT create_enumvariant(IUnknown*, BOOL, IEnumVARIANT**);
-
 static HRESULT WINAPI domselection_QueryInterface(
     IXMLDOMSelection *iface,
     REFIID riid,
@@ -141,7 +133,7 @@ static HRESULT WINAPI domselection_QueryInterface(
     {
         if (!This->enumvariant)
         {
-            HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &This->enumvariant);
+            HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &selection_enumvariant, &This->enumvariant);
             if (FAILED(hr)) return hr;
         }
 
@@ -316,7 +308,7 @@ static HRESULT WINAPI domselection_get__newEnum(
 
     TRACE("(%p)->(%p)\n", This, enumv);
 
-    return create_enumvariant((IUnknown*)iface, TRUE, (IEnumVARIANT**)enumv);
+    return create_enumvariant((IUnknown*)iface, TRUE, &selection_enumvariant, (IEnumVARIANT**)enumv);
 }
 
 static HRESULT WINAPI domselection_get_expr(
@@ -577,7 +569,7 @@ static const struct IEnumVARIANTVtbl EnumVARIANTVtbl =
     enumvariant_Clone
 };
 
-static HRESULT create_enumvariant(IUnknown *outer, BOOL own, IEnumVARIANT **penum)
+HRESULT create_enumvariant(IUnknown *outer, BOOL own, const struct enumvariant_funcs *funcs, IEnumVARIANT **penum)
 {
     enumvariant *This;
 
@@ -589,7 +581,7 @@ static HRESULT create_enumvariant(IUnknown *outer, BOOL own, IEnumVARIANT **penu
     This->outer = outer;
     This->own = own;
     This->pos = 0;
-    This->funcs = &selection_enumvariant;
+    This->funcs = funcs;
 
     if (This->own)
         IUnknown_AddRef(This->outer);
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 4b73d47..92e8d5e 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -4130,6 +4130,7 @@ static void test_get_childNodes(void)
     IXMLDOMElement *element;
     IUnknown *unk1, *unk2;
     HRESULT hr;
+    VARIANT v;
     BSTR str;
     LONG len;
 
@@ -4153,8 +4154,7 @@ static void test_get_childNodes(void)
     /* refcount tests for IEnumVARIANT support */
     EXPECT_REF(node_list, 1);
     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum1);
-if (hr == S_OK)
-{
+    EXPECT_HR(hr, S_OK);
     EXPECT_REF(node_list, 1);
     EXPECT_REF(enum1, 2);
 
@@ -4199,8 +4199,45 @@ if (hr == S_OK)
     IEnumVARIANT_Release(enum3);
     IEnumVARIANT_Release(enum2);
 
+    /* iteration tests */
+    hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
+    EXPECT_HR(hr, S_OK);
+    hr = IXMLDOMNode_get_nodeName(node, &str);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    IXMLDOMNode_Release(node);
+
+    hr = IXMLDOMNodeList_nextNode(node_list, &node);
+    EXPECT_HR(hr, S_OK);
+    hr = IXMLDOMNode_get_nodeName(node, &str);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    IXMLDOMNode_Release(node);
+
+    V_VT(&v) = VT_EMPTY;
+    hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
+    EXPECT_HR(hr, S_OK);
+    ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
+    hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
+    EXPECT_HR(hr, S_OK);
+    hr = IXMLDOMNode_get_nodeName(node, &str);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(str, _bstr_("bs")), "got node name %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    IXMLDOMNode_Release(node);
+    VariantClear(&v);
+
+    hr = IXMLDOMNodeList_nextNode(node_list, &node);
+    EXPECT_HR(hr, S_OK);
+    hr = IXMLDOMNode_get_nodeName(node, &str);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(str, _bstr_("pr")), "got %s\n", wine_dbgstr_w(str));
+    SysFreeString(str);
+    IXMLDOMNode_Release(node);
+
     IEnumVARIANT_Release(enum1);
-}
 
     hr = IXMLDOMNodeList_get_item( node_list, 2, &node );
     EXPECT_HR(hr, S_OK);




More information about the wine-cvs mailing list