From 49eac508b59ca41fd9a10731c5038bd4b799015b Mon Sep 17 00:00:00 2001 From: Gijs Vermeulen Date: Sun, 13 Sep 2020 14:14:41 +0200 Subject: [PATCH] msxml3: Support retrieving more than one element in IEnumVARIANT::Next() for IXMLElementCollection. Signed-off-by: Gijs Vermeulen Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/msxml3/tests/xmldoc.c | 51 +++++++++++++++++++++++++++++++------- dlls/msxml3/xmlelem.c | 24 ++++++++++-------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/dlls/msxml3/tests/xmldoc.c b/dlls/msxml3/tests/xmldoc.c index 693af195717..8854e0e2fa8 100644 --- a/dlls/msxml3/tests/xmldoc.c +++ b/dlls/msxml3/tests/xmldoc.c @@ -656,7 +656,7 @@ static void test_xmlelem_collection(void) WCHAR path[MAX_PATH]; LONG length, type; ULONG num_vars; - VARIANT var, dummy, vIndex, vName; + VARIANT var[3], dummy, vIndex, vName; BSTR url, str; static const CHAR szBankXML[] = "bank.xml"; static const WCHAR szNumber[] = {'N','U','M','B','E','R',0}; @@ -738,16 +738,16 @@ static void test_xmlelem_collection(void) IUnknown_Release(unk); /* 1234 */ - hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars); + hr = IEnumVARIANT_Next(enumVar, 1, &var[0], &num_vars); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var)); + ok(V_VT(&var[0]) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var[0])); ok(num_vars == 1, "Expected 1, got %d\n", num_vars); - hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child); + hr = IDispatch_QueryInterface(V_DISPATCH(&var[0]), &IID_IXMLElement, (LPVOID *)&child); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(child != NULL, "Expected non-NULL child\n"); - VariantClear(&var); + VariantClear(&var[0]); hr = IXMLElement_get_type(child, &type); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); @@ -760,11 +760,13 @@ static void test_xmlelem_collection(void) IXMLElement_Release(child); /* Captain Ahab */ - hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars); + hr = IEnumVARIANT_Next(enumVar, 1, &var[0], &num_vars); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); - ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var)); + ok(V_VT(&var[0]) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var[0])); ok(num_vars == 1, "Expected 1, got %d\n", num_vars); + VariantClear(&var[0]); + /* try advance further, no children left */ V_VT(&dummy) = VT_I4; hr = IEnumVARIANT_Next(enumVar, 1, &dummy, &num_vars); @@ -777,11 +779,42 @@ static void test_xmlelem_collection(void) ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr); ok(V_VT(&dummy) == VT_EMPTY, "Expected 0, got %d\n", V_VT(&dummy)); - hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child); + hr = IEnumVARIANT_Reset(enumVar); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + /* retrieve multiple elements */ + hr = IEnumVARIANT_Next(enumVar, 2, var, &num_vars); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(V_VT(&var[0]) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var[0])); + ok(V_VT(&var[1]) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var[1])); + ok(num_vars == 2, "Expected 2, got %d\n", num_vars); + + V_VT(&dummy) = VT_I4; + hr = IEnumVARIANT_Next(enumVar, 1, &dummy, &num_vars); + ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr); + ok(V_VT(&dummy) == VT_EMPTY, "Expected 0, got %d\n", V_VT(&dummy)); + ok(num_vars == 0, "Expected 0, got %d\n", num_vars); + + hr = IEnumVARIANT_Reset(enumVar); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + VariantClear(&var[1]); + VariantClear(&var[0]); + + /* request more elements than available */ + hr = IEnumVARIANT_Next(enumVar, 3, var, &num_vars); + ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr); + ok(V_VT(&var[0]) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var[0])); + ok(V_VT(&var[1]) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var[1])); + ok(V_VT(&var[2]) == VT_EMPTY, "Expected 0, got %d\n", V_VT(&var[2])); + ok(num_vars == 2, "Expected 2, got %d\n", num_vars); + + hr = IDispatch_QueryInterface(V_DISPATCH(&var[1]), &IID_IXMLElement, (LPVOID *)&child); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); ok(child != NULL, "Expected non-NULL child\n"); - VariantClear(&var); + VariantClear(&var[1]); + VariantClear(&var[0]); hr = IXMLElement_get_type(child, &type); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); diff --git a/dlls/msxml3/xmlelem.c b/dlls/msxml3/xmlelem.c index 96b2007ce38..3addcbd19b5 100644 --- a/dlls/msxml3/xmlelem.c +++ b/dlls/msxml3/xmlelem.c @@ -753,28 +753,32 @@ static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next( IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *fetched) { xmlelem_collection *This = impl_from_IEnumVARIANT(iface); - xmlNodePtr ptr = This->current; + HRESULT hr; TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, fetched); if (!rgVar) return E_INVALIDARG; - /* FIXME: handle celt */ - if (fetched) - *fetched = 1; + if (fetched) *fetched = 0; - if (This->current) - This->current = This->current->next; - else + if (!This->current) { V_VT(rgVar) = VT_EMPTY; - if (fetched) *fetched = 0; return S_FALSE; } - V_VT(rgVar) = VT_DISPATCH; - return XMLElement_create(ptr, (LPVOID *)&V_DISPATCH(rgVar), FALSE); + while (celt > 0 && This->current) + { + V_VT(rgVar) = VT_DISPATCH; + hr = XMLElement_create(This->current, (void **)&V_DISPATCH(rgVar), FALSE); + if (FAILED(hr)) return hr; + This->current = This->current->next; + if (--celt && This->current) ++rgVar; + if (fetched) ++*fetched; + } + + return celt == 0 ? S_OK : S_FALSE; } static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(