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