From 27eedd5f5eae5d62e5c8c13f3b47d5b2f9c59029 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sat, 30 Jun 2012 20:34:27 +0400 Subject: [PATCH] msxml3: Make it possible to use different outer objects with single IEnumVARIANT implementation. --- dlls/msxml3/selection.c | 71 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c index 3cbf4e9c93a..b41e323fc32 100644 --- a/dlls/msxml3/selection.c +++ b/dlls/msxml3/selection.c @@ -59,18 +59,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); int registerNamespaces(xmlXPathContextPtr ctxt); xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str); -typedef struct _enumvariant +struct enumvariant_funcs +{ + HRESULT (*get_item)(IUnknown*, LONG, IDispatch**); + HRESULT (*next)(IUnknown*); +}; + +typedef struct { IEnumVARIANT IEnumVARIANT_iface; LONG ref; - IXMLDOMSelection *selection; + IUnknown *outer; BOOL own; LONG pos; + + const struct enumvariant_funcs *funcs; } enumvariant; -typedef struct _domselection +typedef struct { DispatchEx dispex; IXMLDOMSelection IXMLDOMSelection_iface; @@ -81,6 +89,24 @@ typedef struct _domselection IEnumVARIANT *enumvariant; } domselection; +static HRESULT selection_get_item(IUnknown *iface, LONG index, IDispatch** item) +{ + return IXMLDOMSelection_get_item((IXMLDOMSelection*)iface, index, (IXMLDOMNode**)item); +} + +static HRESULT selection_next(IUnknown *iface) +{ + IXMLDOMNode *node; + HRESULT hr = IXMLDOMSelection_nextNode((IXMLDOMSelection*)iface, &node); + if (hr == S_OK) IXMLDOMNode_Release(node); + return hr; +} + +static const struct enumvariant_funcs selection_enumvariant = { + selection_get_item, + selection_next +}; + static inline domselection *impl_from_IXMLDOMSelection( IXMLDOMSelection *iface ) { return CONTAINING_RECORD(iface, domselection, IXMLDOMSelection_iface); @@ -91,7 +117,7 @@ static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface ) return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface); } -static HRESULT create_enumvariant(IXMLDOMSelection*, BOOL, IUnknown**); +static HRESULT create_enumvariant(IUnknown*, BOOL, IEnumVARIANT**); static HRESULT WINAPI domselection_QueryInterface( IXMLDOMSelection *iface, @@ -115,7 +141,7 @@ static HRESULT WINAPI domselection_QueryInterface( { if (!This->enumvariant) { - HRESULT hr = create_enumvariant(iface, FALSE, (IUnknown**)&This->enumvariant); + HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &This->enumvariant); if (FAILED(hr)) return hr; } @@ -284,13 +310,13 @@ static HRESULT WINAPI domselection_reset( static HRESULT WINAPI domselection_get__newEnum( IXMLDOMSelection* iface, - IUnknown** ppUnk) + IUnknown** enumv) { domselection *This = impl_from_IXMLDOMSelection( iface ); - TRACE("(%p)->(%p)\n", This, ppUnk); + TRACE("(%p)->(%p)\n", This, enumv); - return create_enumvariant(iface, TRUE, ppUnk); + return create_enumvariant((IUnknown*)iface, TRUE, (IEnumVARIANT**)enumv); } static HRESULT WINAPI domselection_get_expr( @@ -438,14 +464,14 @@ static HRESULT WINAPI enumvariant_QueryInterface( if (This->own) *ppvObject = &This->IEnumVARIANT_iface; else - return IXMLDOMSelection_QueryInterface(This->selection, riid, ppvObject); + return IUnknown_QueryInterface(This->outer, riid, ppvObject); } else if (IsEqualGUID( riid, &IID_IEnumVARIANT )) { *ppvObject = &This->IEnumVARIANT_iface; } else - return IXMLDOMSelection_QueryInterface(This->selection, riid, ppvObject); + return IUnknown_QueryInterface(This->outer, riid, ppvObject); IEnumVARIANT_AddRef( iface ); @@ -468,7 +494,7 @@ static ULONG WINAPI enumvariant_Release(IEnumVARIANT *iface ) TRACE("(%p)->(%d)\n", This, ref); if ( ref == 0 ) { - if (This->own) IXMLDOMSelection_Release(This->selection); + if (This->own) IUnknown_Release(This->outer); heap_free(This); } @@ -482,7 +508,6 @@ static HRESULT WINAPI enumvariant_Next( ULONG *fetched) { enumvariant *This = impl_from_IEnumVARIANT( iface ); - IXMLDOMNode *node; ULONG ret_count = 0; TRACE("(%p)->(%u %p %p)\n", This, celt, var, fetched); @@ -496,13 +521,9 @@ static HRESULT WINAPI enumvariant_Next( IDispatch *disp = NULL; HRESULT hr; - node = NULL; - hr = IXMLDOMSelection_get_item(This->selection, This->pos, &node); + hr = This->funcs->get_item(This->outer, This->pos, &disp); if (hr != S_OK) break; - IXMLDOMNode_QueryInterface(node, &IID_IDispatch, (void**)&disp); - IXMLDOMNode_Release(node); - V_VT(var) = VT_DISPATCH; V_DISPATCH(var) = disp; @@ -514,9 +535,8 @@ static HRESULT WINAPI enumvariant_Next( /* we need to advance one step more for some reason */ if (ret_count) { - node = NULL; - IXMLDOMSelection_nextNode(This->selection, &node); - if (node) IXMLDOMNode_Release(node); + if (This->funcs->next) + This->funcs->next(This->outer); } return celt == 0 ? S_OK : S_FALSE; @@ -557,7 +577,7 @@ static const struct IEnumVARIANTVtbl EnumVARIANTVtbl = enumvariant_Clone }; -static HRESULT create_enumvariant(IXMLDOMSelection *selection, BOOL own, IUnknown **penum) +static HRESULT create_enumvariant(IUnknown *outer, BOOL own, IEnumVARIANT **penum) { enumvariant *This; @@ -566,15 +586,16 @@ static HRESULT create_enumvariant(IXMLDOMSelection *selection, BOOL own, IUnknow This->IEnumVARIANT_iface.lpVtbl = &EnumVARIANTVtbl; This->ref = 0; - This->selection = selection; + This->outer = outer; This->own = own; This->pos = 0; + This->funcs = &selection_enumvariant; if (This->own) - IXMLDOMSelection_AddRef(selection); + IUnknown_AddRef(This->outer); - *penum = (IUnknown*)&This->IEnumVARIANT_iface; - IUnknown_AddRef(*penum); + *penum = &This->IEnumVARIANT_iface; + IEnumVARIANT_AddRef(*penum); return S_OK; } -- 2.11.4.GIT