Piotr Caban : msxml3: Update xmlNode reference count when nodes are merged in node_insert_before.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Dec 21 15:10:33 CST 2015
Module: wine
Branch: master
Commit: 7bd995a1166d0807e830ccb8b810db4e7d65e27c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=7bd995a1166d0807e830ccb8b810db4e7d65e27c
Author: Piotr Caban <piotr at 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 at codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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)
More information about the wine-cvs
mailing list