Nikolay Sivov : msxml3: Add stub IEnumVARIANT support for IXMLDOMSelection.
Alexandre Julliard
julliard at winehq.org
Mon Oct 24 13:43:54 CDT 2011
Module: wine
Branch: master
Commit: a3a1f4e3fb62178bcb67a0016cb50079b4d31ad4
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a3a1f4e3fb62178bcb67a0016cb50079b4d31ad4
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Sun Oct 23 22:54:20 2011 +0400
msxml3: Add stub IEnumVARIANT support for IXMLDOMSelection.
---
dlls/msxml3/selection.c | 149 +++++++++++++++++++++++++++++++++++++++++++-
dlls/msxml3/tests/domdoc.c | 83 ++++++++++++++++++++++++-
2 files changed, 228 insertions(+), 4 deletions(-)
diff --git a/dlls/msxml3/selection.c b/dlls/msxml3/selection.c
index e0f30c3..c90c8c2 100644
--- a/dlls/msxml3/selection.c
+++ b/dlls/msxml3/selection.c
@@ -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;
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index c12aa5c..0acfa25 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -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);
More information about the wine-cvs
mailing list