Robert Shearman : msxml:
Allow the element implementation to be aggregatable.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Jun 14 06:51:53 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 09ddab14812613da2811d4771dfd286e606a5d94
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=09ddab14812613da2811d4771dfd286e606a5d94
Author: Robert Shearman <rob at codeweavers.com>
Date: Wed Jun 14 02:37:54 2006 +0100
msxml: Allow the element implementation to be aggregatable.
---
dlls/msxml3/element.c | 109 ++++++++++++++++++++++++++++++-------------
dlls/msxml3/msxml_private.h | 2 -
dlls/msxml3/node.c | 2 -
3 files changed, 79 insertions(+), 34 deletions(-)
diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c
index 89b35d4..7997b2f 100644
--- a/dlls/msxml3/element.c
+++ b/dlls/msxml3/element.c
@@ -41,6 +41,8 @@ #ifdef HAVE_LIBXML2
typedef struct _domelem
{
const struct IXMLDOMElementVtbl *lpVtbl;
+ const struct IUnknownVtbl *lpInternalUnkVtbl;
+ IUnknown *pUnkOuter;
LONG ref;
IUnknown *node_unk;
IXMLDOMNode *node;
@@ -51,6 +53,11 @@ static inline domelem *impl_from_IXMLDOM
return (domelem *)((char*)iface - FIELD_OFFSET(domelem, lpVtbl));
}
+static inline domelem *impl_from_InternalUnknown( IUnknown *iface )
+{
+ return (domelem *)((char*)iface - FIELD_OFFSET(domelem, lpInternalUnkVtbl));
+}
+
static inline xmlNodePtr get_element( domelem *This )
{
return xmlNodePtr_from_domnode( This->node, XML_ELEMENT_NODE );
@@ -64,48 +71,21 @@ static HRESULT WINAPI domelem_QueryInter
domelem *This = impl_from_IXMLDOMElement( iface );
TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
- if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
- IsEqualGUID( riid, &IID_IUnknown ) )
- {
- *ppvObject = iface;
- }
- else if ( IsEqualGUID( riid, &IID_IDispatch ) ||
- IsEqualGUID( riid, &IID_IXMLDOMNode ) )
- {
- return IUnknown_QueryInterface(This->node_unk, riid, ppvObject);
- }
- else
- {
- FIXME("interface %s not implemented\n", debugstr_guid(riid));
- return E_NOINTERFACE;
- }
-
- IXMLDOMElement_AddRef( iface );
-
- return S_OK;
+ return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
}
static ULONG WINAPI domelem_AddRef(
IXMLDOMElement *iface )
{
domelem *This = impl_from_IXMLDOMElement( iface );
- return InterlockedIncrement( &This->ref );
+ return IUnknown_AddRef(This->pUnkOuter);
}
static ULONG WINAPI domelem_Release(
IXMLDOMElement *iface )
{
domelem *This = impl_from_IXMLDOMElement( iface );
- ULONG ref;
-
- ref = InterlockedDecrement( &This->ref );
- if ( ref == 0 )
- {
- IUnknown_Release( This->node_unk );
- HeapFree( GetProcessHeap(), 0, This );
- }
-
- return ref;
+ return IUnknown_Release(This->pUnkOuter);
}
static HRESULT WINAPI domelem_GetTypeInfoCount(
@@ -644,7 +624,66 @@ static const struct IXMLDOMElementVtbl d
domelem_normalize,
};
-IUnknown* create_element( xmlNodePtr element )
+static HRESULT WINAPI Internal_QueryInterface(
+ IUnknown *iface,
+ REFIID riid,
+ void** ppvObject )
+{
+ domelem *This = impl_from_InternalUnknown( iface );
+ TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = &This->lpVtbl;
+ }
+ else if ( IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IXMLDOMNode ) )
+ {
+ return IUnknown_QueryInterface(This->node_unk, riid, ppvObject);
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef( (IUnknown*)*ppvObject );
+
+ return S_OK;
+}
+
+static ULONG WINAPI Internal_AddRef(
+ IUnknown *iface )
+{
+ domelem *This = impl_from_InternalUnknown( iface );
+ return InterlockedIncrement( &This->ref );
+}
+
+static ULONG WINAPI Internal_Release(
+ IUnknown *iface )
+{
+ domelem *This = impl_from_InternalUnknown( iface );
+ ULONG ref;
+
+ ref = InterlockedDecrement( &This->ref );
+ if ( ref == 0 )
+ {
+ IUnknown_Release( This->node_unk );
+ HeapFree( GetProcessHeap(), 0, This );
+ }
+
+ return ref;
+}
+
+static const struct IUnknownVtbl internal_unk_vtbl =
+{
+ Internal_QueryInterface,
+ Internal_AddRef,
+ Internal_Release
+};
+
+IUnknown* create_element( xmlNodePtr element, IUnknown *pUnkOuter )
{
domelem *This;
HRESULT hr;
@@ -655,6 +694,12 @@ IUnknown* create_element( xmlNodePtr ele
This->lpVtbl = &domelem_vtbl;
This->ref = 1;
+ This->lpInternalUnkVtbl = &internal_unk_vtbl;
+
+ if(pUnkOuter)
+ This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */
+ else
+ This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl;
This->node_unk = create_basic_node( element, (IUnknown*)&This->lpVtbl );
if(!This->node_unk)
@@ -673,7 +718,7 @@ IUnknown* create_element( xmlNodePtr ele
/* The ref on This->node is actually looped back into this object, so release it */
IXMLDOMNode_Release(This->node);
- return (IUnknown*) &This->lpVtbl;
+ return (IUnknown*) &This->lpInternalUnkVtbl;
}
#endif
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 2084b22..5516361 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -32,7 +32,7 @@ extern IUnknown *create_domdoc(
extern IUnknown *create_xmldoc( void );
extern IXMLDOMNode *create_node( xmlNodePtr node );
extern IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter );
-extern IUnknown *create_element( xmlNodePtr element );
+extern IUnknown *create_element( xmlNodePtr element, IUnknown *pUnkOuter );
extern IUnknown *create_attribute( xmlNodePtr attribute );
extern IUnknown *create_text( xmlNodePtr text );
extern IUnknown *create_comment( xmlNodePtr comment );
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index 0ec8ec9..312edae 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -868,7 +868,7 @@ IXMLDOMNode *create_node( xmlNodePtr nod
switch(node->type)
{
case XML_ELEMENT_NODE:
- pUnk = create_element( node );
+ pUnk = create_element( node, NULL );
break;
case XML_ATTRIBUTE_NODE:
pUnk = create_attribute( node );
More information about the wine-cvs
mailing list