Module: wine Branch: master Commit: 0f3c247e46dbc7935bf6e2d563ce16f01cada9ee URL: http://source.winehq.org/git/wine.git/?a=commit;h=0f3c247e46dbc7935bf6e2d563...
Author: Nikolay Sivov nsivov@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();