Commit 03ad0acf authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msxml3: Add IEnumVARIANT support for IXMLDOMNodeList.

parent 27eedd5f
...@@ -256,6 +256,13 @@ struct nodemap_funcs ...@@ -256,6 +256,13 @@ struct nodemap_funcs
HRESULT (*next_node)(const xmlNodePtr,LONG*,IXMLDOMNode**); 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 */ /* constructors */
extern IUnknown *create_domdoc( xmlNodePtr ) DECLSPEC_HIDDEN; extern IUnknown *create_domdoc( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IUnknown *create_xmldoc( void ) DECLSPEC_HIDDEN; extern IUnknown *create_xmldoc( void ) DECLSPEC_HIDDEN;
...@@ -273,6 +280,7 @@ extern IUnknown *create_doc_fragment( xmlNodePtr ) 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_entity_ref( xmlNodePtr ) DECLSPEC_HIDDEN;
extern IUnknown *create_doc_type( xmlNodePtr ) DECLSPEC_HIDDEN; extern IUnknown *create_doc_type( xmlNodePtr ) DECLSPEC_HIDDEN;
extern HRESULT create_selection( xmlNodePtr, xmlChar*, IXMLDOMNodeList** ) 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 */ /* data accessors */
xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ) DECLSPEC_HIDDEN; xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ) DECLSPEC_HIDDEN;
......
...@@ -52,15 +52,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); ...@@ -52,15 +52,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
#ifdef HAVE_LIBXML2 #ifdef HAVE_LIBXML2
typedef struct _xmlnodelist typedef struct
{ {
DispatchEx dispex; DispatchEx dispex;
IXMLDOMNodeList IXMLDOMNodeList_iface; IXMLDOMNodeList IXMLDOMNodeList_iface;
LONG ref; LONG ref;
xmlNodePtr parent; xmlNodePtr parent;
xmlNodePtr current; xmlNodePtr current;
IEnumVARIANT *enumvariant;
} xmlnodelist; } 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 ) static inline xmlnodelist *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface )
{ {
return CONTAINING_RECORD(iface, xmlnodelist, IXMLDOMNodeList_iface); return CONTAINING_RECORD(iface, xmlnodelist, IXMLDOMNodeList_iface);
...@@ -81,6 +92,16 @@ static HRESULT WINAPI xmlnodelist_QueryInterface( ...@@ -81,6 +92,16 @@ static HRESULT WINAPI xmlnodelist_QueryInterface(
{ {
*ppvObject = iface; *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)) else if (dispex_query_interface(&This->dispex, riid, ppvObject))
{ {
return *ppvObject ? S_OK : E_NOINTERFACE; return *ppvObject ? S_OK : E_NOINTERFACE;
...@@ -116,6 +137,7 @@ static ULONG WINAPI xmlnodelist_Release( ...@@ -116,6 +137,7 @@ static ULONG WINAPI xmlnodelist_Release(
if ( ref == 0 ) if ( ref == 0 )
{ {
xmldoc_release( This->parent->doc ); xmldoc_release( This->parent->doc );
if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
heap_free( This ); heap_free( This );
} }
...@@ -261,11 +283,11 @@ static HRESULT WINAPI xmlnodelist_reset( ...@@ -261,11 +283,11 @@ static HRESULT WINAPI xmlnodelist_reset(
static HRESULT WINAPI xmlnodelist__newEnum( static HRESULT WINAPI xmlnodelist__newEnum(
IXMLDOMNodeList* iface, IXMLDOMNodeList* iface,
IUnknown** ppUnk) IUnknown** enumv)
{ {
xmlnodelist *This = impl_from_IXMLDOMNodeList( iface ); xmlnodelist *This = impl_from_IXMLDOMNodeList( iface );
FIXME("(%p)->(%p)\n", This, ppUnk); TRACE("(%p)->(%p)\n", This, enumv);
return E_NOTIMPL; return create_enumvariant((IUnknown*)iface, TRUE, &nodelist_enumvariant, (IEnumVARIANT**)enumv);
} }
static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl = static const struct IXMLDOMNodeListVtbl xmlnodelist_vtbl =
...@@ -362,6 +384,7 @@ IXMLDOMNodeList* create_children_nodelist( xmlNodePtr node ) ...@@ -362,6 +384,7 @@ IXMLDOMNodeList* create_children_nodelist( xmlNodePtr node )
This->ref = 1; This->ref = 1;
This->parent = node; This->parent = node;
This->current = node->children; This->current = node->children;
This->enumvariant = NULL;
xmldoc_add_ref( node->doc ); xmldoc_add_ref( node->doc );
init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNodeList_iface, &xmlnodelist_dispex); init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNodeList_iface, &xmlnodelist_dispex);
......
...@@ -59,12 +59,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); ...@@ -59,12 +59,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
int registerNamespaces(xmlXPathContextPtr ctxt); int registerNamespaces(xmlXPathContextPtr ctxt);
xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str); xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str);
struct enumvariant_funcs
{
HRESULT (*get_item)(IUnknown*, LONG, IDispatch**);
HRESULT (*next)(IUnknown*);
};
typedef struct typedef struct
{ {
IEnumVARIANT IEnumVARIANT_iface; IEnumVARIANT IEnumVARIANT_iface;
...@@ -117,8 +111,6 @@ static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface ) ...@@ -117,8 +111,6 @@ static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface); return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface);
} }
static HRESULT create_enumvariant(IUnknown*, BOOL, IEnumVARIANT**);
static HRESULT WINAPI domselection_QueryInterface( static HRESULT WINAPI domselection_QueryInterface(
IXMLDOMSelection *iface, IXMLDOMSelection *iface,
REFIID riid, REFIID riid,
...@@ -141,7 +133,7 @@ static HRESULT WINAPI domselection_QueryInterface( ...@@ -141,7 +133,7 @@ static HRESULT WINAPI domselection_QueryInterface(
{ {
if (!This->enumvariant) 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; if (FAILED(hr)) return hr;
} }
...@@ -316,7 +308,7 @@ static HRESULT WINAPI domselection_get__newEnum( ...@@ -316,7 +308,7 @@ static HRESULT WINAPI domselection_get__newEnum(
TRACE("(%p)->(%p)\n", This, enumv); 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( static HRESULT WINAPI domselection_get_expr(
...@@ -577,7 +569,7 @@ static const struct IEnumVARIANTVtbl EnumVARIANTVtbl = ...@@ -577,7 +569,7 @@ static const struct IEnumVARIANTVtbl EnumVARIANTVtbl =
enumvariant_Clone 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; enumvariant *This;
...@@ -589,7 +581,7 @@ static HRESULT create_enumvariant(IUnknown *outer, BOOL own, IEnumVARIANT **penu ...@@ -589,7 +581,7 @@ static HRESULT create_enumvariant(IUnknown *outer, BOOL own, IEnumVARIANT **penu
This->outer = outer; This->outer = outer;
This->own = own; This->own = own;
This->pos = 0; This->pos = 0;
This->funcs = &selection_enumvariant; This->funcs = funcs;
if (This->own) if (This->own)
IUnknown_AddRef(This->outer); IUnknown_AddRef(This->outer);
......
...@@ -4130,6 +4130,7 @@ static void test_get_childNodes(void) ...@@ -4130,6 +4130,7 @@ static void test_get_childNodes(void)
IXMLDOMElement *element; IXMLDOMElement *element;
IUnknown *unk1, *unk2; IUnknown *unk1, *unk2;
HRESULT hr; HRESULT hr;
VARIANT v;
BSTR str; BSTR str;
LONG len; LONG len;
...@@ -4153,8 +4154,7 @@ static void test_get_childNodes(void) ...@@ -4153,8 +4154,7 @@ static void test_get_childNodes(void)
/* refcount tests for IEnumVARIANT support */ /* refcount tests for IEnumVARIANT support */
EXPECT_REF(node_list, 1); EXPECT_REF(node_list, 1);
hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum1); 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(node_list, 1);
EXPECT_REF(enum1, 2); EXPECT_REF(enum1, 2);
...@@ -4199,8 +4199,45 @@ if (hr == S_OK) ...@@ -4199,8 +4199,45 @@ if (hr == S_OK)
IEnumVARIANT_Release(enum3); IEnumVARIANT_Release(enum3);
IEnumVARIANT_Release(enum2); 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); IEnumVARIANT_Release(enum1);
}
hr = IXMLDOMNodeList_get_item( node_list, 2, &node ); hr = IXMLDOMNodeList_get_item( node_list, 2, &node );
EXPECT_HR(hr, S_OK); EXPECT_HR(hr, S_OK);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment