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