msxml3: Refcount the domdoc/xmldoc properties.
Multiple domdoc and xmlDoc objects may need to share a common properties object but may be released independently. So add a reference count on the properties object. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43377 Signed-off-by: Francois Gouget <fgouget@codeweavers.com> Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
54459e593f
commit
0e87427500
|
@ -80,6 +80,7 @@ static const WCHAR PropertyNormalizeAttributeValuesW[] = {'N','o','r','m','a','l
|
||||||
* We need to preserve this when reloading a document,
|
* We need to preserve this when reloading a document,
|
||||||
* and also need access to it from the libxml backend. */
|
* and also need access to it from the libxml backend. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
LONG refs;
|
||||||
MSXML_VERSION version;
|
MSXML_VERSION version;
|
||||||
VARIANT_BOOL preserving;
|
VARIANT_BOOL preserving;
|
||||||
IXMLDOMSchemaCollection2* schemaCache;
|
IXMLDOMSchemaCollection2* schemaCache;
|
||||||
|
@ -290,6 +291,7 @@ static domdoc_properties *create_properties(MSXML_VERSION version)
|
||||||
{
|
{
|
||||||
domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
|
domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
|
||||||
|
|
||||||
|
properties->refs = 1;
|
||||||
list_init(&properties->selectNsList);
|
list_init(&properties->selectNsList);
|
||||||
properties->preserving = VARIANT_FALSE;
|
properties->preserving = VARIANT_FALSE;
|
||||||
properties->schemaCache = NULL;
|
properties->schemaCache = NULL;
|
||||||
|
@ -316,6 +318,7 @@ static domdoc_properties* copy_properties(domdoc_properties const* properties)
|
||||||
|
|
||||||
if (pcopy)
|
if (pcopy)
|
||||||
{
|
{
|
||||||
|
pcopy->refs = 1;
|
||||||
pcopy->version = properties->version;
|
pcopy->version = properties->version;
|
||||||
pcopy->preserving = properties->preserving;
|
pcopy->preserving = properties->preserving;
|
||||||
pcopy->schemaCache = properties->schemaCache;
|
pcopy->schemaCache = properties->schemaCache;
|
||||||
|
@ -345,9 +348,31 @@ static domdoc_properties* copy_properties(domdoc_properties const* properties)
|
||||||
return pcopy;
|
return pcopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_properties(domdoc_properties* properties)
|
static domdoc_properties * properties_add_ref(domdoc_properties *properties)
|
||||||
{
|
{
|
||||||
if (properties)
|
LONG ref;
|
||||||
|
|
||||||
|
if (!properties) return NULL;
|
||||||
|
|
||||||
|
ref = InterlockedIncrement(&properties->refs);
|
||||||
|
TRACE("%p, %d.\n", properties, ref);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void properties_release(domdoc_properties *properties)
|
||||||
|
{
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
if (!properties) return;
|
||||||
|
|
||||||
|
ref = InterlockedDecrement(&properties->refs);
|
||||||
|
|
||||||
|
TRACE("%p, %d.\n", properties, ref);
|
||||||
|
|
||||||
|
if (ref < 0)
|
||||||
|
WARN("negative refcount, expect troubles\n");
|
||||||
|
|
||||||
|
if (ref == 0)
|
||||||
{
|
{
|
||||||
if (properties->schemaCache)
|
if (properties->schemaCache)
|
||||||
IXMLDOMSchemaCollection2_Release(properties->schemaCache);
|
IXMLDOMSchemaCollection2_Release(properties->schemaCache);
|
||||||
|
@ -622,7 +647,7 @@ LONG xmldoc_release_refs(xmlDocPtr doc, LONG refs)
|
||||||
xmlFreeNode( orphan->node );
|
xmlFreeNode( orphan->node );
|
||||||
heap_free( orphan );
|
heap_free( orphan );
|
||||||
}
|
}
|
||||||
free_properties(priv->properties);
|
properties_release(priv->properties);
|
||||||
heap_free(doc->_private);
|
heap_free(doc->_private);
|
||||||
|
|
||||||
xmlFreeDoc(doc);
|
xmlFreeDoc(doc);
|
||||||
|
@ -679,10 +704,16 @@ static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
|
||||||
|
|
||||||
if(This->node.node)
|
if(This->node.node)
|
||||||
{
|
{
|
||||||
|
properties_release(properties_from_xmlDocPtr(get_doc(This)));
|
||||||
priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
|
priv_from_xmlDocPtr(get_doc(This))->properties = NULL;
|
||||||
if (xmldoc_release(get_doc(This)) != 0)
|
if (xmldoc_release(get_doc(This)) != 0)
|
||||||
|
{
|
||||||
|
/* The xmlDocPtr object can no longer use the properties of this
|
||||||
|
* domdoc object. So give it its own copy.
|
||||||
|
*/
|
||||||
priv_from_xmlDocPtr(get_doc(This))->properties =
|
priv_from_xmlDocPtr(get_doc(This))->properties =
|
||||||
copy_properties(This->properties);
|
copy_properties(This->properties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
This->node.node = (xmlNodePtr) xml;
|
This->node.node = (xmlNodePtr) xml;
|
||||||
|
@ -690,7 +721,10 @@ static HRESULT attach_xmldoc(domdoc *This, xmlDocPtr xml )
|
||||||
if(This->node.node)
|
if(This->node.node)
|
||||||
{
|
{
|
||||||
xmldoc_add_ref(get_doc(This));
|
xmldoc_add_ref(get_doc(This));
|
||||||
priv_from_xmlDocPtr(get_doc(This))->properties = This->properties;
|
/* Only attach new xmlDocPtr objects, i.e. ones for which properties
|
||||||
|
* is still NULL.
|
||||||
|
*/
|
||||||
|
priv_from_xmlDocPtr(get_doc(This))->properties = properties_add_ref(This->properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -975,6 +1009,7 @@ static ULONG WINAPI domdoc_Release( IXMLDOMDocument3 *iface )
|
||||||
for (eid = 0; eid < EVENTID_LAST; eid++)
|
for (eid = 0; eid < EVENTID_LAST; eid++)
|
||||||
if (This->events[eid]) IDispatch_Release(This->events[eid]);
|
if (This->events[eid]) IDispatch_Release(This->events[eid]);
|
||||||
|
|
||||||
|
properties_release(This->properties);
|
||||||
release_namespaces(This);
|
release_namespaces(This);
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
}
|
}
|
||||||
|
@ -3675,7 +3710,7 @@ HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document)
|
||||||
doc->async = VARIANT_TRUE;
|
doc->async = VARIANT_TRUE;
|
||||||
doc->validating = 0;
|
doc->validating = 0;
|
||||||
doc->resolving = 0;
|
doc->resolving = 0;
|
||||||
doc->properties = properties_from_xmlDocPtr(xmldoc);
|
doc->properties = properties_add_ref(properties_from_xmlDocPtr(xmldoc));
|
||||||
doc->error = S_OK;
|
doc->error = S_OK;
|
||||||
doc->site = NULL;
|
doc->site = NULL;
|
||||||
doc->base_uri = NULL;
|
doc->base_uri = NULL;
|
||||||
|
@ -3714,7 +3749,7 @@ HRESULT DOMDocument_create(MSXML_VERSION version, void **ppObj)
|
||||||
hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
|
hr = get_domdoc_from_xmldoc(xmldoc, (IXMLDOMDocument3**)ppObj);
|
||||||
if(FAILED(hr))
|
if(FAILED(hr))
|
||||||
{
|
{
|
||||||
free_properties(properties_from_xmlDocPtr(xmldoc));
|
properties_release(properties_from_xmlDocPtr(xmldoc));
|
||||||
heap_free(xmldoc->_private);
|
heap_free(xmldoc->_private);
|
||||||
xmlFreeDoc(xmldoc);
|
xmlFreeDoc(xmldoc);
|
||||||
return hr;
|
return hr;
|
||||||
|
|
Loading…
Reference in New Issue