[PATCH 1/2] Fix reference counting behaviour for named map

Nikolay Sivov nsivov at codeweavers.com
Thu Mar 10 12:56:51 CST 2011


---
 dlls/msxml3/element.c       |    6 ++--
 dlls/msxml3/msxml_private.h |    2 +-
 dlls/msxml3/nodemap.c       |   46 ++++++++++--------------------------------
 dlls/msxml3/tests/domdoc.c  |   45 ++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 58 insertions(+), 41 deletions(-)

diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c
index 8d81f67..4c3a9b3 100644
--- a/dlls/msxml3/element.c
+++ b/dlls/msxml3/element.c
@@ -314,13 +314,13 @@ static HRESULT WINAPI domelem_get_nextSibling(
 
 static HRESULT WINAPI domelem_get_attributes(
     IXMLDOMElement *iface,
-    IXMLDOMNamedNodeMap** attributeMap)
+    IXMLDOMNamedNodeMap** map)
 {
     domelem *This = impl_from_IXMLDOMElement( iface );
 
-    TRACE("(%p)->(%p)\n", This, attributeMap);
+    TRACE("(%p)->(%p)\n", This, map);
 
-    *attributeMap = create_nodemap((IXMLDOMNode*)&This->IXMLDOMElement_iface);
+    *map = create_nodemap(This->node.node);
     return S_OK;
 }
 
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 72de7ba..4e3b35b 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -186,7 +186,7 @@ extern IUnknown         *create_pi( xmlNodePtr pi );
 extern IUnknown         *create_comment( xmlNodePtr comment );
 extern IUnknown         *create_cdata( xmlNodePtr text );
 extern IXMLDOMNodeList  *create_children_nodelist( xmlNodePtr );
-extern IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node );
+extern IXMLDOMNamedNodeMap *create_nodemap( const xmlNodePtr );
 extern IUnknown         *create_doc_Implementation(void);
 extern IUnknown         *create_doc_fragment( xmlNodePtr fragment );
 extern IUnknown         *create_doc_entity_ref( xmlNodePtr entity );
diff --git a/dlls/msxml3/nodemap.c b/dlls/msxml3/nodemap.c
index 660eab6..20475ca 100644
--- a/dlls/msxml3/nodemap.c
+++ b/dlls/msxml3/nodemap.c
@@ -48,7 +48,8 @@ typedef struct _xmlnodemap
     IXMLDOMNamedNodeMap IXMLDOMNamedNodeMap_iface;
     ISupportErrorInfo ISupportErrorInfo_iface;
     LONG ref;
-    IXMLDOMNode *node;
+
+    xmlNodePtr node;
     LONG iterator;
 } xmlnodemap;
 
@@ -109,7 +110,7 @@ static ULONG WINAPI xmlnodemap_Release(
     TRACE("(%p)->(%d)\n", This, ref);
     if ( ref == 0 )
     {
-        IXMLDOMNode_Release( This->node );
+        xmldoc_release( This->node->doc );
         heap_free( This );
     }
 
@@ -217,7 +218,6 @@ static HRESULT WINAPI xmlnodemap_setNamedItem(
 {
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
     xmlNodePtr nodeNew;
-    xmlNodePtr node;
     xmlnode *ThisNew;
 
     TRACE("(%p)->(%p %p)\n", This, newItem, namedItem );
@@ -227,10 +227,6 @@ static HRESULT WINAPI xmlnodemap_setNamedItem(
 
     if(namedItem) *namedItem = NULL;
 
-    node = xmlNodePtr_from_domnode( This->node, 0 );
-    if ( !node )
-        return E_FAIL;
-
     /* Must be an Attribute */
     ThisNew = get_node_obj( newItem );
     if(!ThisNew) return E_FAIL;
@@ -242,7 +238,7 @@ static HRESULT WINAPI xmlnodemap_setNamedItem(
         if(xmldoc_remove_orphan(ThisNew->node->doc, ThisNew->node) != S_OK)
             WARN("%p is not an orphan of %p\n", ThisNew->node, ThisNew->node->doc);
 
-    nodeNew = xmlAddChild(node, ThisNew->node);
+    nodeNew = xmlAddChild(This->node, ThisNew->node);
 
     if(namedItem)
         *namedItem = create_node( nodeNew );
@@ -265,7 +261,6 @@ static HRESULT WINAPI xmlnodemap_get_item(
     IXMLDOMNode** listItem)
 {
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
-    xmlNodePtr node;
     xmlAttrPtr curr;
     LONG attrIndex;
 
@@ -276,8 +271,7 @@ static HRESULT WINAPI xmlnodemap_get_item(
     if (index < 0)
         return S_FALSE;
 
-    node = xmlNodePtr_from_domnode( This->node, 0 );
-    curr = node->properties;
+    curr = This->node->properties;
 
     for (attrIndex = 0; attrIndex < index; attrIndex++) {
         if (curr->next == NULL)
@@ -295,7 +289,6 @@ static HRESULT WINAPI xmlnodemap_get_length(
     IXMLDOMNamedNodeMap *iface,
     LONG *listLength)
 {
-    xmlNodePtr node;
     xmlAttrPtr first;
     xmlAttrPtr curr;
     LONG attrCount;
@@ -307,11 +300,7 @@ static HRESULT WINAPI xmlnodemap_get_length(
     if( !listLength )
         return E_INVALIDARG;
 
-    node = xmlNodePtr_from_domnode( This->node, 0 );
-    if ( !node )
-        return E_FAIL;
-
-    first = node->properties;
+    first = This->node->properties;
     if (first == NULL) {
 	*listLength = 0;
 	return S_OK;
@@ -336,7 +325,6 @@ static HRESULT WINAPI xmlnodemap_getQualifiedItem(
 {
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
     xmlAttrPtr attr;
-    xmlNodePtr node;
     xmlChar *href;
     xmlChar *name;
 
@@ -344,10 +332,6 @@ static HRESULT WINAPI xmlnodemap_getQualifiedItem(
 
     if (!baseName || !qualifiedItem) return E_INVALIDARG;
 
-    node = xmlNodePtr_from_domnode(This->node, XML_ELEMENT_NODE);
-    if ( !node )
-        return E_FAIL;
-
     if (namespaceURI && *namespaceURI)
     {
         href = xmlChar_from_wchar(namespaceURI);
@@ -363,7 +347,7 @@ static HRESULT WINAPI xmlnodemap_getQualifiedItem(
         return E_OUTOFMEMORY;
     }
 
-    attr = xmlHasNsProp(node, name, href);
+    attr = xmlHasNsProp(This->node, name, href);
 
     heap_free(name);
     heap_free(href);
@@ -387,7 +371,6 @@ static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
 {
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
     xmlAttrPtr attr;
-    xmlNodePtr node;
     xmlChar *name;
     xmlChar *href;
 
@@ -395,10 +378,6 @@ static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
 
     if (!baseName) return E_INVALIDARG;
 
-    node = xmlNodePtr_from_domnode( This->node, XML_ELEMENT_NODE );
-    if ( !node )
-        return E_FAIL;
-
     if (namespaceURI && *namespaceURI)
     {
         href = xmlChar_from_wchar(namespaceURI);
@@ -414,7 +393,7 @@ static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
         return E_OUTOFMEMORY;
     }
 
-    attr = xmlHasNsProp( node, name, href );
+    attr = xmlHasNsProp( This->node, name, href );
 
     heap_free(name);
     heap_free(href);
@@ -445,7 +424,6 @@ static HRESULT WINAPI xmlnodemap_nextNode(
     IXMLDOMNode** nextItem)
 {
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
-    xmlNodePtr node;
     xmlAttrPtr curr;
     LONG attrIndex;
 
@@ -453,8 +431,7 @@ static HRESULT WINAPI xmlnodemap_nextNode(
 
     *nextItem = NULL;
 
-    node = xmlNodePtr_from_domnode( This->node, 0 );
-    curr = node->properties;
+    curr = This->node->properties;
 
     for (attrIndex = 0; attrIndex < This->iterator; attrIndex++) {
         if (curr->next == NULL)
@@ -551,7 +528,7 @@ static const struct ISupportErrorInfoVtbl support_error_vtbl =
     support_error_InterfaceSupportsErrorInfo
 };
 
-IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node )
+IXMLDOMNamedNodeMap *create_nodemap( const xmlNodePtr node )
 {
     xmlnodemap *nodemap;
 
@@ -565,8 +542,7 @@ IXMLDOMNamedNodeMap *create_nodemap( IXMLDOMNode *node )
     nodemap->ref = 1;
     nodemap->iterator = 0;
 
-    IXMLDOMNode_AddRef( node );
-    /* Since we AddRef a node here, we don't need to call xmldoc_add_ref() */
+    xmldoc_add_ref(node->doc);
 
     return &nodemap->IXMLDOMNamedNodeMap_iface;
 }
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 42fd22a..370c56e 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -8329,6 +8329,7 @@ static void test_get_nodeTypeString(void)
         ok(!lstrcmpW(str, _bstr_(entry->string)), "got string %s, expected %s. node type %d\n",
             wine_dbgstr_w(str), entry->string, entry->type);
         SysFreeString(str);
+        IXMLDOMNode_Release(node);
 
         entry++;
     }
@@ -8358,14 +8359,15 @@ static void test_get_attributes(void)
     const get_attributes_t *entry = get_attributes;
     IXMLDOMNamedNodeMap *map;
     IXMLDOMDocument *doc;
-    IXMLDOMNode *node;
+    IXMLDOMNode *node, *node2;
     VARIANT_BOOL b;
     HRESULT hr;
     BSTR str;
+    LONG length;
 
     doc = create_document(&IID_IXMLDOMDocument);
 
-    str = SysAllocString( szComplete3 );
+    str = SysAllocString( szComplete4 );
     hr = IXMLDOMDocument_loadXML(doc, str, &b);
     SysFreeString(str);
 
@@ -8403,6 +8405,43 @@ static void test_get_attributes(void)
 
     IXMLDOMNode_Release(node);
 
+    /* last child is element */
+    EXPECT_REF(doc, 1);
+    hr = IXMLDOMDocument_get_lastChild(doc, &node);
+    ok(hr == S_OK, "got %08x\n", hr);
+    EXPECT_REF(doc, 1);
+
+    EXPECT_REF(node, 1);
+    hr = IXMLDOMNode_get_attributes(node, &map);
+    ok(hr == S_OK, "got %08x\n", hr);
+    EXPECT_REF(node, 1);
+    EXPECT_REF(doc, 1);
+
+    EXPECT_REF(map, 1);
+    hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
+    ok(hr == S_OK, "got %08x\n", hr);
+    EXPECT_REF(node, 1);
+    EXPECT_REF(node2, 1);
+    EXPECT_REF(map, 1);
+    EXPECT_REF(doc, 1);
+    IXMLDOMNode_Release(node2);
+
+    /* release node before map release, map still works */
+    IXMLDOMNode_Release(node);
+
+    length = 0;
+    hr = IXMLDOMNamedNodeMap_get_length(map, &length);
+    ok(hr == S_OK, "got %08x\n", hr);
+    ok(length == 1, "got %d\n", length);
+
+    node2 = NULL;
+    hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
+    ok(hr == S_OK, "got %08x\n", hr);
+    EXPECT_REF(node2, 1);
+    IXMLDOMNode_Release(node2);
+
+    IXMLDOMNamedNodeMap_Release(map);
+
     while (entry->type)
     {
         VARIANT var;
@@ -8423,6 +8462,8 @@ static void test_get_attributes(void)
             hr, entry->hr, entry->type);
         ok(map == NULL, "got %p\n", map);
 
+        IXMLDOMNode_Release(node);
+
         entry++;
     }
 
-- 
1.5.6.5



--------------040909010802040402090002--



More information about the wine-patches mailing list