Nikolay Sivov : msxml3: Track linked/ unlinked state for element and free node data only when unlinked.

Alexandre Julliard julliard at winehq.org
Mon Jan 18 10:58:51 CST 2010


Module: wine
Branch: master
Commit: f9cb63116d2558dd2bb0759218b2d6773fb048a3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f9cb63116d2558dd2bb0759218b2d6773fb048a3

Author: Nikolay Sivov <bunglehead at gmail.com>
Date:   Fri Jan 15 00:18:32 2010 +0300

msxml3: Track linked/unlinked state for element and free node data only when unlinked.

---

 dlls/msxml3/msxml_private.h |    2 +-
 dlls/msxml3/tests/xmlelem.c |    1 +
 dlls/msxml3/xmldoc.c        |    4 ++--
 dlls/msxml3/xmlelem.c       |   16 ++++++++++++----
 4 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index d62a8a4..e46642d 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -135,7 +135,7 @@ extern LONG xmldoc_release( xmlDocPtr doc );
 extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node );
 extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node );
 
-extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj );
+extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own );
 
 extern xmlDocPtr parse_xml(char *ptr, int len);
 
diff --git a/dlls/msxml3/tests/xmlelem.c b/dlls/msxml3/tests/xmlelem.c
index bcbae94..3304d5a 100644
--- a/dlls/msxml3/tests/xmlelem.c
+++ b/dlls/msxml3/tests/xmlelem.c
@@ -523,6 +523,7 @@ static void test_xmlelem_children(void)
     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
     ok(child2 != NULL, "Expected not NULL child\n");
     IXMLElementCollection_Release(collection);
+    IXMLElement_Release(child2);
 
     /* add element->child->child2 structure, then remove child2 from node */
     V_VT(&vType) = VT_I4;
diff --git a/dlls/msxml3/xmldoc.c b/dlls/msxml3/xmldoc.c
index af67d4e..b77fd00 100644
--- a/dlls/msxml3/xmldoc.c
+++ b/dlls/msxml3/xmldoc.c
@@ -209,7 +209,7 @@ static HRESULT WINAPI xmldoc_get_root(IXMLDocument *iface, IXMLElement **p)
     if (!(root = xmlDocGetRootElement(This->xmldoc)))
         return E_FAIL;
 
-    return XMLElement_create((IUnknown *)This, root, (LPVOID *)p);
+    return XMLElement_create((IUnknown *)This, root, (LPVOID *)p, FALSE);
 }
 
 static HRESULT WINAPI xmldoc_get_fileSize(IXMLDocument *iface, BSTR *p)
@@ -520,7 +520,7 @@ static HRESULT WINAPI xmldoc_createElement(IXMLDocument *iface, VARIANT vType,
     node->type = type_msxml_to_libxml(V_I4(&vType));
 
     /* FIXME: create xmlNodePtr based on vType and var1 */
-    return XMLElement_create((IUnknown *)iface, node, (LPVOID *)ppElem);
+    return XMLElement_create((IUnknown *)iface, node, (LPVOID *)ppElem, TRUE);
 }
 
 static const struct IXMLDocumentVtbl xmldoc_vtbl =
diff --git a/dlls/msxml3/xmlelem.c b/dlls/msxml3/xmlelem.c
index b96df3a..3c1f4f2 100644
--- a/dlls/msxml3/xmlelem.c
+++ b/dlls/msxml3/xmlelem.c
@@ -48,6 +48,7 @@ typedef struct _xmlelem
     const IXMLElementVtbl *lpVtbl;
     LONG ref;
     xmlNodePtr node;
+    BOOL own;
 } xmlelem;
 
 static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface)
@@ -94,6 +95,7 @@ static ULONG WINAPI xmlelem_Release(IXMLElement *iface)
     ref = InterlockedDecrement(&This->ref);
     if (ref == 0)
     {
+        if (This->own) xmlFreeNode(This->node);
         HeapFree(GetProcessHeap(), 0, This);
     }
 
@@ -212,7 +214,7 @@ static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **paren
     if (!This->node->parent)
         return S_FALSE;
 
-    return XMLElement_create((IUnknown *)iface, This->node->parent, (LPVOID *)parent);
+    return XMLElement_create((IUnknown *)iface, This->node->parent, (LPVOID *)parent, FALSE);
 }
 
 static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName,
@@ -407,6 +409,9 @@ static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildEl
     else
         child = xmlAddNextSibling(This->node, childElem->node->last);
 
+    /* parent is responsible for child data */
+    if (child) childElem->own = FALSE;
+
     return (child) ? S_OK : S_FALSE;
 }
 
@@ -425,6 +430,8 @@ static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChil
         return E_INVALIDARG;
 
     xmlUnlinkNode(childElem->node);
+    /* standalone element now */
+    childElem->own = TRUE;
 
     return S_OK;
 }
@@ -452,7 +459,7 @@ static const struct IXMLElementVtbl xmlelem_vtbl =
     xmlelem_removeChild
 };
 
-HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
+HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj, BOOL own)
 {
     xmlelem *elem;
 
@@ -470,6 +477,7 @@ HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
     elem->lpVtbl = &xmlelem_vtbl;
     elem->ref = 1;
     elem->node = node;
+    elem->own  = own;
 
     *ppObj = &elem->lpVtbl;
 
@@ -652,7 +660,7 @@ static HRESULT WINAPI xmlelem_collection_item(IXMLElementCollection *iface, VARI
     for (i = 0; i < index; i++)
         ptr = ptr->next;
 
-    return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)ppDisp);
+    return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)ppDisp, FALSE);
 }
 
 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl =
@@ -712,7 +720,7 @@ static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next(
     This->current = This->current->next;
 
     V_VT(rgVar) = VT_DISPATCH;
-    return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)&V_DISPATCH(rgVar));
+    return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)&V_DISPATCH(rgVar), FALSE);
 }
 
 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(




More information about the wine-cvs mailing list