msxml: Allow the element implementation to be aggregatable.

This commit is contained in:
Robert Shearman 2006-06-14 02:37:54 +01:00 committed by Alexandre Julliard
parent 569a452d3a
commit 09ddab1481
3 changed files with 79 additions and 34 deletions

View File

@ -41,6 +41,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
typedef struct _domelem typedef struct _domelem
{ {
const struct IXMLDOMElementVtbl *lpVtbl; const struct IXMLDOMElementVtbl *lpVtbl;
const struct IUnknownVtbl *lpInternalUnkVtbl;
IUnknown *pUnkOuter;
LONG ref; LONG ref;
IUnknown *node_unk; IUnknown *node_unk;
IXMLDOMNode *node; IXMLDOMNode *node;
@ -51,6 +53,11 @@ static inline domelem *impl_from_IXMLDOMElement( IXMLDOMElement *iface )
return (domelem *)((char*)iface - FIELD_OFFSET(domelem, lpVtbl)); 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 ) static inline xmlNodePtr get_element( domelem *This )
{ {
return xmlNodePtr_from_domnode( This->node, XML_ELEMENT_NODE ); return xmlNodePtr_from_domnode( This->node, XML_ELEMENT_NODE );
@ -64,48 +71,21 @@ static HRESULT WINAPI domelem_QueryInterface(
domelem *This = impl_from_IXMLDOMElement( iface ); domelem *This = impl_from_IXMLDOMElement( iface );
TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
if ( IsEqualGUID( riid, &IID_IXMLDOMElement ) || return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject);
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;
} }
static ULONG WINAPI domelem_AddRef( static ULONG WINAPI domelem_AddRef(
IXMLDOMElement *iface ) IXMLDOMElement *iface )
{ {
domelem *This = impl_from_IXMLDOMElement( iface ); domelem *This = impl_from_IXMLDOMElement( iface );
return InterlockedIncrement( &This->ref ); return IUnknown_AddRef(This->pUnkOuter);
} }
static ULONG WINAPI domelem_Release( static ULONG WINAPI domelem_Release(
IXMLDOMElement *iface ) IXMLDOMElement *iface )
{ {
domelem *This = impl_from_IXMLDOMElement( iface ); domelem *This = impl_from_IXMLDOMElement( iface );
ULONG ref; return IUnknown_Release(This->pUnkOuter);
ref = InterlockedDecrement( &This->ref );
if ( ref == 0 )
{
IUnknown_Release( This->node_unk );
HeapFree( GetProcessHeap(), 0, This );
}
return ref;
} }
static HRESULT WINAPI domelem_GetTypeInfoCount( static HRESULT WINAPI domelem_GetTypeInfoCount(
@ -644,7 +624,66 @@ static const struct IXMLDOMElementVtbl domelem_vtbl =
domelem_normalize, 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; domelem *This;
HRESULT hr; HRESULT hr;
@ -655,6 +694,12 @@ IUnknown* create_element( xmlNodePtr element )
This->lpVtbl = &domelem_vtbl; This->lpVtbl = &domelem_vtbl;
This->ref = 1; 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 ); This->node_unk = create_basic_node( element, (IUnknown*)&This->lpVtbl );
if(!This->node_unk) if(!This->node_unk)
@ -673,7 +718,7 @@ IUnknown* create_element( xmlNodePtr element )
/* The ref on This->node is actually looped back into this object, so release it */ /* The ref on This->node is actually looped back into this object, so release it */
IXMLDOMNode_Release(This->node); IXMLDOMNode_Release(This->node);
return (IUnknown*) &This->lpVtbl; return (IUnknown*) &This->lpInternalUnkVtbl;
} }
#endif #endif

View File

@ -32,7 +32,7 @@ extern IUnknown *create_domdoc( void );
extern IUnknown *create_xmldoc( void ); extern IUnknown *create_xmldoc( void );
extern IXMLDOMNode *create_node( xmlNodePtr node ); extern IXMLDOMNode *create_node( xmlNodePtr node );
extern IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter ); 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_attribute( xmlNodePtr attribute );
extern IUnknown *create_text( xmlNodePtr text ); extern IUnknown *create_text( xmlNodePtr text );
extern IUnknown *create_comment( xmlNodePtr comment ); extern IUnknown *create_comment( xmlNodePtr comment );

View File

@ -868,7 +868,7 @@ IXMLDOMNode *create_node( xmlNodePtr node )
switch(node->type) switch(node->type)
{ {
case XML_ELEMENT_NODE: case XML_ELEMENT_NODE:
pUnk = create_element( node ); pUnk = create_element( node, NULL );
break; break;
case XML_ATTRIBUTE_NODE: case XML_ATTRIBUTE_NODE:
pUnk = create_attribute( node ); pUnk = create_attribute( node );