Module: wine Branch: master Commit: 7bd995a1166d0807e830ccb8b810db4e7d65e27c URL: http://source.winehq.org/git/wine.git/?a=commit;h=7bd995a1166d0807e830ccb8b8...
Author: Piotr Caban piotr@codeweavers.com Date: Mon Dec 21 11:41:10 2015 +0100
msxml3: Update xmlNode reference count when nodes are merged in node_insert_before.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/msxml3/node.c | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-)
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c index f8d7761..9c768bd 100644 --- a/dlls/msxml3/node.c +++ b/dlls/msxml3/node.c @@ -429,6 +429,19 @@ int xmlnode_get_inst_cnt(xmlnode *node) return node_get_inst_cnt(node->node); }
+/* _private field holds a number of COM instances spawned from this libxml2 node */ +static void xmlnode_add_ref(xmlNodePtr node) +{ + if (node->type == XML_DOCUMENT_NODE) return; + InterlockedIncrement((LONG*)&node->_private); +} + +static void xmlnode_release(xmlNodePtr node) +{ + if (node->type == XML_DOCUMENT_NODE) return; + InterlockedDecrement((LONG*)&node->_private); +} + HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child, IXMLDOMNode **ret) { @@ -489,6 +502,7 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT
if(before) { + xmlNodePtr new_node; xmlnode *before_node_obj = get_node_obj(before);
/* refs count including subtree */ @@ -496,19 +510,35 @@ HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT refcount = xmlnode_get_inst_cnt(node_obj);
if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount); - node_obj->node = xmlAddPrevSibling(before_node_obj->node, node_obj->node); + new_node = xmlAddPrevSibling(before_node_obj->node, node_obj->node); + if (new_node != node_obj->node) + { + if (refcount != 1) + FIXME("referenced xmlNode was freed, expect crashes\n"); + xmlnode_add_ref(new_node); + node_obj->node = new_node; + } if (refcount) xmldoc_release_refs(doc, refcount); node_obj->parent = This->parent; } else { + xmlNodePtr new_node; + if (doc != This->node->doc) refcount = xmlnode_get_inst_cnt(node_obj);
if (refcount) xmldoc_add_refs(This->node->doc, refcount); /* xmlAddChild doesn't unlink node from previous parent */ xmlUnlinkNode(node_obj->node); - node_obj->node = xmlAddChild(This->node, node_obj->node); + new_node = xmlAddChild(This->node, node_obj->node); + if (new_node != node_obj->node) + { + if (refcount != 1) + FIXME("referenced xmlNode was freed, expect crashes\n"); + xmlnode_add_ref(new_node); + node_obj->node = new_node; + } if (refcount) xmldoc_release_refs(doc, refcount); node_obj->parent = This->iface; } @@ -1392,19 +1422,6 @@ HRESULT node_get_base_name(xmlnode *This, BSTR *name) return S_OK; }
-/* _private field holds a number of COM instances spawned from this libxml2 node */ -static void xmlnode_add_ref(xmlNodePtr node) -{ - if (node->type == XML_DOCUMENT_NODE) return; - InterlockedIncrement((LONG*)&node->_private); -} - -static void xmlnode_release(xmlNodePtr node) -{ - if (node->type == XML_DOCUMENT_NODE) return; - InterlockedDecrement((LONG*)&node->_private); -} - void destroy_xmlnode(xmlnode *This) { if(This->node)