Commit a3a1f4e3 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msxml3: Add stub IEnumVARIANT support for IXMLDOMSelection.

parent ae6ea94b
......@@ -58,6 +58,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
int registerNamespaces(xmlXPathContextPtr ctxt);
xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str);
typedef struct _enumvariant
{
IEnumVARIANT IEnumVARIANT_iface;
LONG ref;
IXMLDOMSelection *selection;
BOOL own;
} enumvariant;
typedef struct _domselection
{
DispatchEx dispex;
......@@ -66,6 +75,7 @@ typedef struct _domselection
xmlNodePtr node;
xmlXPathObjectPtr result;
int resultPos;
IEnumVARIANT *enumvariant;
} domselection;
static inline domselection *impl_from_IXMLDOMSelection( IXMLDOMSelection *iface )
......@@ -73,6 +83,13 @@ static inline domselection *impl_from_IXMLDOMSelection( IXMLDOMSelection *iface
return CONTAINING_RECORD(iface, domselection, IXMLDOMSelection_iface);
}
static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
{
return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface);
}
static HRESULT create_enumvariant(IXMLDOMSelection*, BOOL, IUnknown**);
static HRESULT WINAPI domselection_QueryInterface(
IXMLDOMSelection *iface,
REFIID riid,
......@@ -91,7 +108,17 @@ static HRESULT WINAPI domselection_QueryInterface(
{
*ppvObject = &This->IXMLDOMSelection_iface;
}
else if(dispex_query_interface(&This->dispex, riid, ppvObject))
else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
{
if (!This->enumvariant)
{
HRESULT hr = create_enumvariant(iface, FALSE, (IUnknown**)&This->enumvariant);
if (FAILED(hr)) return hr;
}
return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
}
else if (dispex_query_interface(&This->dispex, riid, ppvObject))
{
return *ppvObject ? S_OK : E_NOINTERFACE;
}
......@@ -127,6 +154,7 @@ static ULONG WINAPI domselection_Release(
{
xmlXPathFreeObject(This->result);
xmldoc_release(This->node->doc);
if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
heap_free(This);
}
......@@ -293,8 +321,10 @@ static HRESULT WINAPI domselection_get__newEnum(
IUnknown** ppUnk)
{
domselection *This = impl_from_IXMLDOMSelection( iface );
FIXME("(%p)->(%p)\n", This, ppUnk);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, ppUnk);
return create_enumvariant(iface, TRUE, ppUnk);
}
static HRESULT WINAPI domselection_get_expr(
......@@ -425,6 +455,118 @@ static const struct IXMLDOMSelectionVtbl domselection_vtbl =
domselection_setProperty
};
/* IEnumVARIANT support */
static HRESULT WINAPI enumvariant_QueryInterface(
IEnumVARIANT *iface,
REFIID riid,
void** ppvObject )
{
enumvariant *This = impl_from_IEnumVARIANT( iface );
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
*ppvObject = NULL;
if ( IsEqualGUID( riid, &IID_IUnknown ) ||
IsEqualGUID( riid, &IID_IEnumVARIANT ))
{
*ppvObject = &This->IEnumVARIANT_iface;
}
else
return IXMLDOMSelection_QueryInterface(This->selection, riid, ppvObject);
IEnumVARIANT_AddRef( iface );
return S_OK;
}
static ULONG WINAPI enumvariant_AddRef(IEnumVARIANT *iface )
{
enumvariant *This = impl_from_IEnumVARIANT( iface );
ULONG ref = InterlockedIncrement( &This->ref );
TRACE("(%p)->(%d)\n", This, ref);
return ref;
}
static ULONG WINAPI enumvariant_Release(IEnumVARIANT *iface )
{
enumvariant *This = impl_from_IEnumVARIANT( iface );
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->(%d)\n", This, ref);
if ( ref == 0 )
{
if (This->own) IXMLDOMSelection_Release(This->selection);
heap_free(This);
}
return ref;
}
static HRESULT WINAPI enumvariant_Next(
IEnumVARIANT *iface,
ULONG celt,
VARIANT *rgvar,
ULONG *pceltFetched)
{
enumvariant *This = impl_from_IEnumVARIANT( iface );
FIXME("(%p)->(%u %p %p): stub\n", This, celt, rgvar, pceltFetched);
return E_NOTIMPL;
}
static HRESULT WINAPI enumvariant_Skip(
IEnumVARIANT *iface,
ULONG celt)
{
enumvariant *This = impl_from_IEnumVARIANT( iface );
FIXME("(%p)->(%u): stub\n", This, celt);
return E_NOTIMPL;
}
static HRESULT WINAPI enumvariant_Reset(IEnumVARIANT *iface)
{
enumvariant *This = impl_from_IEnumVARIANT( iface );
FIXME("(%p): stub\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI enumvariant_Clone(
IEnumVARIANT *iface, IEnumVARIANT **ppenum)
{
enumvariant *This = impl_from_IEnumVARIANT( iface );
FIXME("(%p)->(%p): stub\n", This, ppenum);
return E_NOTIMPL;
}
static const struct IEnumVARIANTVtbl EnumVARIANTVtbl =
{
enumvariant_QueryInterface,
enumvariant_AddRef,
enumvariant_Release,
enumvariant_Next,
enumvariant_Skip,
enumvariant_Reset,
enumvariant_Clone
};
static HRESULT create_enumvariant(IXMLDOMSelection *selection, BOOL own, IUnknown **penum)
{
enumvariant *This;
This = heap_alloc(sizeof(enumvariant));
if (!This) return E_OUTOFMEMORY;
This->IEnumVARIANT_iface.lpVtbl = &EnumVARIANTVtbl;
This->ref = 0;
This->selection = selection;
This->own = own;
if (This->own)
IXMLDOMSelection_AddRef(selection);
return IEnumVARIANT_QueryInterface(&This->IEnumVARIANT_iface, &IID_IUnknown, (void**)penum);
}
static HRESULT domselection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
{
domselection *This = impl_from_IXMLDOMSelection( (IXMLDOMSelection*)iface );
......@@ -622,6 +764,7 @@ HRESULT create_selection(xmlNodePtr node, xmlChar* query, IXMLDOMNodeList **out)
This->ref = 1;
This->resultPos = 0;
This->node = node;
This->enumvariant = NULL;
xmldoc_add_ref(This->node->doc);
ctxt->error = query_serror;
......
......@@ -9964,7 +9964,9 @@ static void test_get_attributes(void)
static void test_selection(void)
{
IXMLDOMSelection *selection;
IXMLDOMSelection *selection, *selection2;
IEnumVARIANT *enum1, *enum2, *enum3;
IDispatch *disp;
IXMLDOMNodeList *list;
IXMLDOMDocument *doc;
VARIANT_BOOL b;
......@@ -9982,6 +9984,85 @@ static void test_selection(void)
EXPECT_HR(hr, S_OK);
IXMLDOMSelection_Release(selection);
/* IEnumVARIANT tests */
enum1 = NULL;
hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum1);
EXPECT_HR(hr, S_OK);
ok(enum1 != NULL, "got %p\n", enum1);
EXPECT_REF(enum1, 2);
enum3 = NULL;
hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum3);
EXPECT_HR(hr, S_OK);
ok(enum3 != NULL, "got %p\n", enum3);
ok(enum1 == enum3, "got %p and %p\n", enum1, enum3);
EXPECT_REF(enum1, 3);
IEnumVARIANT_Release(enum3);
EXPECT_REF(selection, 1);
EXPECT_REF(enum1, 2);
enum2 = NULL;
hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
EXPECT_HR(hr, S_OK);
ok(enum2 != NULL, "got %p\n", enum2);
EXPECT_REF(selection, 2);
EXPECT_REF(enum1, 2);
EXPECT_REF(enum2, 1);
ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
selection2 = NULL;
hr = IEnumVARIANT_QueryInterface(enum1, &IID_IXMLDOMSelection, (void**)&selection2);
EXPECT_HR(hr, S_OK);
ok(selection2 == selection, "got %p and %p\n", selection, selection2);
EXPECT_REF(selection, 3);
EXPECT_REF(enum1, 2);
IXMLDOMSelection_Release(selection2);
hr = IEnumVARIANT_QueryInterface(enum1, &IID_IDispatch, (void**)&disp);
EXPECT_HR(hr, S_OK);
EXPECT_REF(selection, 3);
IDispatch_Release(disp);
hr = IEnumVARIANT_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enum3);
EXPECT_HR(hr, S_OK);
ok(enum3 == enum1, "got %p and %p\n", enum3, enum1);
EXPECT_REF(selection, 2);
EXPECT_REF(enum1, 3);
IEnumVARIANT_Release(enum1);
IEnumVARIANT_Release(enum2);
enum1 = NULL;
hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
EXPECT_HR(hr, S_OK);
ok(enum1 != NULL, "got %p\n", enum1);
EXPECT_REF(enum1, 1);
EXPECT_REF(selection, 2);
enum2 = NULL;
hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
EXPECT_HR(hr, S_OK);
ok(enum2 != NULL, "got %p\n", enum2);
EXPECT_REF(enum2, 1);
EXPECT_REF(selection, 3);
ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
IEnumVARIANT_AddRef(enum1);
EXPECT_REF(selection, 3);
EXPECT_REF(enum1, 2);
EXPECT_REF(enum2, 1);
IEnumVARIANT_Release(enum1);
IEnumVARIANT_Release(enum1);
IEnumVARIANT_Release(enum2);
EXPECT_REF(selection, 1);
IXMLDOMNodeList_Release(list);
hr = IXMLDOMDocument_get_childNodes(doc, &list);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment