Nikolay Sivov : msxml3: Properly update xmldoc refcounts on insertBefore().
Alexandre Julliard
julliard at winehq.org
Mon Mar 7 12:22:46 CST 2011
Module: wine
Branch: master
Commit: 0f3c247e46dbc7935bf6e2d563ce16f01cada9ee
URL: http://source.winehq.org/git/wine.git/?a=commit;h=0f3c247e46dbc7935bf6e2d563ce16f01cada9ee
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sun Mar 6 22:28:29 2011 +0300
msxml3: Properly update xmldoc refcounts on insertBefore().
insertBefore() is able to work on nodes from different documents, so on
adding child or sibling it's possible that libxml2 switches doc pointer
for a node, we need to update refcounts to cover that case.
---
dlls/msxml3/node.c | 7 ++++
dlls/msxml3/tests/domdoc.c | 66 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index fc15a5d..18b3db2 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -295,6 +295,7 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
xmlNodePtr new_child_node;
IXMLDOMNode *before = NULL;
xmlnode *node_obj;
+ xmlDocPtr doc;
HRESULT hr;
if(!new_child)
@@ -336,7 +337,10 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
/* unlink from current parent first */
if(node_obj->parent)
IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
+ doc = new_child_node->doc;
+ xmldoc_add_ref(before_node_obj->node->doc);
xmlAddPrevSibling(before_node_obj->node, new_child_node);
+ xmldoc_release(doc);
node_obj->parent = This->parent;
}
else
@@ -344,7 +348,10 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
/* unlink from current parent first */
if(node_obj->parent)
IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL);
+ doc = new_child_node->doc;
+ xmldoc_add_ref(This->node->doc);
xmlAddChild(This->node, new_child_node);
+ xmldoc_release(doc);
node_obj->parent = This->iface;
}
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 439207f..9dca668 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -2064,6 +2064,7 @@ static void test_refs(void)
doc = create_document(&IID_IXMLDOMDocument);
if (!doc) return;
+ EXPECT_REF(doc, 1);
ref = IXMLDOMDocument_Release(doc);
ok( ref == 0, "ref %d\n", ref);
@@ -2076,6 +2077,7 @@ static void test_refs(void)
ok( b == VARIANT_TRUE, "failed to load XML string\n");
SysFreeString( str );
+ EXPECT_REF(doc, 1);
IXMLDOMDocument_AddRef( doc );
EXPECT_REF(doc, 2);
IXMLDOMDocument_AddRef( doc );
@@ -2089,19 +2091,27 @@ static void test_refs(void)
ok( element != NULL, "should be an element\n");
EXPECT_REF(doc, 1);
+ todo_wine EXPECT_REF(element, 2);
+
+ IXMLDOMElement_AddRef(element);
+ todo_wine EXPECT_REF(element, 3);
+ IXMLDOMElement_Release(element);
r = IXMLDOMElement_get_childNodes( element, &node_list );
ok( r == S_OK, "rets %08x\n", r);
+ todo_wine EXPECT_REF(element, 2);
EXPECT_REF(node_list, 1);
IXMLDOMNodeList_get_item( node_list, 0, &node );
ok( r == S_OK, "rets %08x\n", r);
+ EXPECT_REF(node_list, 1);
+ EXPECT_REF(node, 1);
IXMLDOMNodeList_get_item( node_list, 0, &node2 );
ok( r == S_OK, "rets %08x\n", r);
-
- EXPECT_REF(node, 1);
+ EXPECT_REF(node_list, 1);
+ EXPECT_REF(node2, 1);
ref = IXMLDOMNode_Release( node );
ok( ref == 0, "ref %d\n", ref );
@@ -2121,18 +2131,22 @@ static void test_refs(void)
/* IUnknown must be unique however we obtain it */
r = IXMLDOMElement_QueryInterface( element, &IID_IUnknown, (void**)&unk );
ok( r == S_OK, "rets %08x\n", r );
+ EXPECT_REF(element, 2);
r = IXMLDOMElement_QueryInterface( element, &IID_IXMLDOMNode, (void**)&node );
ok( r == S_OK, "rets %08x\n", r );
+ todo_wine EXPECT_REF(element, 2);
r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (void**)&unk2 );
ok( r == S_OK, "rets %08x\n", r );
+ todo_wine EXPECT_REF(element, 2);
ok( unk == unk2, "unk %p unk2 %p\n", unk, unk2 );
+ todo_wine ok( element != (void*)node, "node %p element %p\n", node, element );
IUnknown_Release( unk2 );
IUnknown_Release( unk );
IXMLDOMNode_Release( node );
+ todo_wine EXPECT_REF(element, 2);
IXMLDOMElement_Release( element );
-
}
static void test_create(void)
@@ -2156,6 +2170,8 @@ static void test_create(void)
doc = create_document(&IID_IXMLDOMDocument);
if (!doc) return;
+ EXPECT_REF(doc, 1);
+
/* types not supported for creation */
V_VT(&var) = VT_I1;
V_I1(&var) = NODE_DOCUMENT;
@@ -2452,9 +2468,12 @@ static void test_create(void)
V_I4(&var) = NODE_ELEMENT;
r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
ok( r == S_OK, "returns %08x\n", r );
+
+ EXPECT_REF(doc, 1);
r = IXMLDOMDocument_appendChild( doc, node, &root );
ok( r == S_OK, "returns %08x\n", r );
ok( node == root, "%p %p\n", node, root );
+ EXPECT_REF(doc, 1);
EXPECT_REF(node, 2);
@@ -8250,7 +8269,45 @@ static void test_insertBefore(void)
SysFreeString(p);
IXMLDOMDocument_Release(doc);
- free_bstrs();
+}
+
+static void test_appendChild(void)
+{
+ IXMLDOMDocument *doc, *doc2;
+ IXMLDOMElement *elem, *elem2;
+ HRESULT hr;
+
+ doc = create_document(&IID_IXMLDOMDocument);
+ doc2 = create_document(&IID_IXMLDOMDocument);
+
+ hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem2"), &elem2);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ EXPECT_REF(doc, 1);
+ todo_wine EXPECT_REF(elem, 2);
+ EXPECT_REF(doc2, 1);
+ todo_wine EXPECT_REF(elem2, 2);
+ EXPECT_NO_CHILDREN(doc);
+ EXPECT_NO_CHILDREN(doc2);
+
+ /* append from another document */
+ hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, NULL);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ EXPECT_REF(doc, 1);
+ todo_wine EXPECT_REF(elem, 2);
+ EXPECT_REF(doc2, 1);
+ todo_wine EXPECT_REF(elem2, 2);
+ EXPECT_NO_CHILDREN(doc);
+ EXPECT_CHILDREN(doc2);
+
+ IXMLDOMElement_Release(elem);
+ IXMLDOMElement_Release(elem2);
+ IXMLDOMDocument_Release(doc);
+ IXMLDOMDocument_Release(doc2);
}
START_TEST(domdoc)
@@ -8318,6 +8375,7 @@ START_TEST(domdoc)
test_put_nodeTypedValue();
test_get_xml();
test_insertBefore();
+ test_appendChild();
test_xsltemplate();
CoUninitialize();
More information about the wine-cvs
mailing list