From 03ad0acfad45ea4a6a992645e6fa2c17f6165fd6 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sun, 1 Jul 2012 01:12:12 +0400 Subject: [PATCH] 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 3a2efb03b83..4aafc29ee99 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 f948fcf5cb3..7e46d40fe04 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 b41e323fc32..bf5fe6171ee 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 4b73d473b06..92e8d5edf85 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); -- 2.11.4.GIT