Module: wine Branch: master Commit: 4bb9da77767602e3fb798654da0920b7f157691c URL: http://source.winehq.org/git/wine.git/?a=commit;h=4bb9da77767602e3fb798654da...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Sun Oct 30 10:57:09 2011 +0300
msxml3: Implement IEnumVARIANT::Next() for IXMLDOMSelection.
---
dlls/msxml3/selection.c | 43 ++++++++++++++++++-- dlls/msxml3/tests/domdoc.c | 95 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 133 insertions(+), 5 deletions(-)
diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c index 0e62a68..31137f3 100644 --- a/dlls/msxml3/selection.c +++ b/dlls/msxml3/selection.c @@ -65,6 +65,8 @@ typedef struct _enumvariant
IXMLDOMSelection *selection; BOOL own; + + LONG pos; } enumvariant;
typedef struct _domselection @@ -507,12 +509,44 @@ static ULONG WINAPI enumvariant_Release(IEnumVARIANT *iface ) static HRESULT WINAPI enumvariant_Next( IEnumVARIANT *iface, ULONG celt, - VARIANT *rgvar, - ULONG *pceltFetched) + VARIANT *var, + ULONG *fetched) { enumvariant *This = impl_from_IEnumVARIANT( iface ); - FIXME("(%p)->(%u %p %p): stub\n", This, celt, rgvar, pceltFetched); - return E_NOTIMPL; + IXMLDOMNode *node; + ULONG ret_count = 0; + + TRACE("(%p)->(%u %p %p)\n", This, celt, var, fetched); + + if (fetched) *fetched = 0; + + if (celt && !var) return E_INVALIDARG; + + for (; celt > 0; celt--, var++, This->pos++) + { + IDispatch *disp = NULL; + HRESULT hr; + + node = NULL; + hr = IXMLDOMSelection_get_item(This->selection, This->pos, &node); + if (hr != S_OK) break; + + IXMLDOMNode_QueryInterface(node, &IID_IDispatch, (void**)&disp); + IXMLDOMNode_Release(node); + + V_VT(var) = VT_DISPATCH; + V_DISPATCH(var) = disp; + + ret_count++; + } + + if (fetched) (*fetched)++; + + /* we need to advance one step more for some reason */ + if (ret_count) + IXMLDOMSelection_nextNode(This->selection, &node); + + return celt == 0 ? S_OK : S_FALSE; }
static HRESULT WINAPI enumvariant_Skip( @@ -561,6 +595,7 @@ static HRESULT create_enumvariant(IXMLDOMSelection *selection, BOOL own, IUnknow This->ref = 0; This->selection = selection; This->own = own; + This->pos = 0;
if (This->own) IXMLDOMSelection_AddRef(selection); diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 62ccb4e..ee2128b 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -1728,6 +1728,15 @@ SZ_EMAIL_DTD " <attachment id="patch1">0001-msxml3-tests-DTD-validation.patch</attachment>" "</email>";
+static const char xpath_simple_list[] = +"<?xml version=\"1.0\"?>" +"<root>" +" <a/>" +" <b/>" +" <c/>" +" <d/>" +"</root>"; + static const WCHAR szNonExistentFile[] = { 'c', ':', '\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0 }; @@ -10043,11 +10052,16 @@ static void test_selection(void) { IXMLDOMSelection *selection, *selection2; IEnumVARIANT *enum1, *enum2, *enum3; - IDispatch *disp; IXMLDOMNodeList *list; IXMLDOMDocument *doc; + IXMLDOMNode *node; + IDispatch *disp; VARIANT_BOOL b; HRESULT hr; + VARIANT v; + BSTR name; + ULONG ret; + LONG len;
doc = create_document(&IID_IXMLDOMDocument);
@@ -10150,7 +10164,86 @@ static void test_selection(void)
IXMLDOMNodeList_Release(list);
+ /* test if IEnumVARIANT touches selection context */ + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(xpath_simple_list), &b); + EXPECT_HR(hr, S_OK); + + hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/*"), &list); + EXPECT_HR(hr, S_OK); + + hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection); + EXPECT_HR(hr, S_OK); + + len = 0; + hr = IXMLDOMSelection_get_length(selection, &len); + EXPECT_HR(hr, S_OK); + ok(len == 4, "got %d\n", len); + + enum1 = NULL; + hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1); + EXPECT_HR(hr, S_OK); + + /* no-op if zero count */ + V_VT(&v) = VT_I2; + hr = IEnumVARIANT_Next(enum1, 0, &v, NULL); + EXPECT_HR(hr, S_OK); + ok(V_VT(&v) == VT_I2, "got var type %d\n", V_VT(&v)); + + /* positive count, null array pointer */ + hr = IEnumVARIANT_Next(enum1, 1, NULL, NULL); + EXPECT_HR(hr, E_INVALIDARG); + + ret = 1; + hr = IEnumVARIANT_Next(enum1, 1, NULL, &ret); + EXPECT_HR(hr, E_INVALIDARG); + ok(ret == 0, "got %d\n", ret); + + V_VT(&v) = VT_I2; + 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, &name); + EXPECT_HR(hr, S_OK); + ok(!lstrcmpW(name, _bstr_("a")), "got node name %s\n", wine_dbgstr_w(name)); + SysFreeString(name); + IXMLDOMNode_Release(node); + VariantClear(&v); + + /* list cursor is updated */ + hr = IXMLDOMSelection_nextNode(selection, &node); + EXPECT_HR(hr, S_OK); + hr = IXMLDOMNode_get_nodeName(node, &name); + EXPECT_HR(hr, S_OK); + ok(!lstrcmpW(name, _bstr_("c")), "got node name %s\n", wine_dbgstr_w(name)); + IXMLDOMNode_Release(node); + + V_VT(&v) = VT_I2; + 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, &name); + EXPECT_HR(hr, S_OK); + ok(!lstrcmpW(name, _bstr_("b")), "got node name %s\n", wine_dbgstr_w(name)); + SysFreeString(name); + IXMLDOMNode_Release(node); + VariantClear(&v); + + hr = IXMLDOMSelection_nextNode(selection, &node); + EXPECT_HR(hr, S_OK); + hr = IXMLDOMNode_get_nodeName(node, &name); + EXPECT_HR(hr, S_OK); + ok(!lstrcmpW(name, _bstr_("d")), "got node name %s\n", wine_dbgstr_w(name)); + IXMLDOMNode_Release(node); + + IXMLDOMSelection_Release(selection); + IXMLDOMNodeList_Release(list); IXMLDOMDocument_Release(doc); + free_bstrs(); }