msxml3 [1/4]: Add initial implementation of IXMLElement and
IXMLElementCollection [try2]
James Hawkins
truiken at gmail.com
Thu May 24 13:12:19 CDT 2007
Hi,
This version adds the necessary checks for libxml2.
Changelog:
* Add initial implementation of IXMLElement and IXMLElementCollection.
dlls/msxml3/Makefile.in | 3
dlls/msxml3/msxml_private.h | 2
dlls/msxml3/xmlelem.c | 726 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 730 insertions(+), 1 deletions(-)
--
James Hawkins
-------------- next part --------------
diff --git a/dlls/msxml3/Makefile.in b/dlls/msxml3/Makefile.in
index c888e23..870034d 100644
--- a/dlls/msxml3/Makefile.in
+++ b/dlls/msxml3/Makefile.in
@@ -24,7 +24,8 @@ C_SRCS = \
regsvr.c \
schema.c \
text.c \
- uuid.c
+ uuid.c \
+ xmlelem.c
RC_SRCS = version.rc
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 39aaa00..74f061a 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -63,5 +63,7 @@ extern IXMLDOMParseError *create_parseEr
LONG line, LONG linepos, LONG filepos );
extern HRESULT DOMDocument_create( IUnknown *pUnkOuter, LPVOID *ppObj );
extern HRESULT SchemaCache_create( IUnknown *pUnkOuter, LPVOID *ppObj );
+extern HRESULT XMLElement_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj );
+extern HRESULT XMLElementCollection_create( IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj );
#endif /* __MSXML_PRIVATE__ */
diff --git a/dlls/msxml3/xmlelem.c b/dlls/msxml3/xmlelem.c
new file mode 100644
index 0000000..4fc8865
--- /dev/null
+++ b/dlls/msxml3/xmlelem.c
@@ -0,0 +1,726 @@
+/*
+ * XML Element implementation
+ *
+ * Copyright 2007 James Hawkins
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include "config.h"
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "ole2.h"
+#include "msxml2.h"
+#include "ocidl.h"
+
+#include "wine/debug.h"
+
+#include "msxml_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(msxml);
+
+#ifdef HAVE_LIBXML2
+
+/**********************************************************************
+ * IXMLElement
+ */
+typedef struct _xmlelem
+{
+ const IXMLElementVtbl *lpVtbl;
+ LONG ref;
+ xmlNodePtr node;
+} xmlelem;
+
+static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface)
+{
+ return (xmlelem *)((char*)iface - FIELD_OFFSET(xmlelem, lpVtbl));
+}
+
+static HRESULT WINAPI xmlelem_QueryInterface(IXMLElement *iface, REFIID riid, void** ppvObject)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+
+ TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IXMLElement))
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ IXMLElement_AddRef(iface);
+
+ return S_OK;
+}
+
+static ULONG WINAPI xmlelem_AddRef(IXMLElement *iface)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ TRACE("%p\n", This);
+ return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI xmlelem_Release(IXMLElement *iface)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ LONG ref;
+
+ TRACE("%p\n", This);
+
+ ref = InterlockedDecrement(&This->ref);
+ if (ref == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI xmlelem_GetTypeInfoCount(IXMLElement *iface, UINT* pctinfo)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_GetTypeInfo(IXMLElement *iface, UINT iTInfo,
+ LCID lcid, ITypeInfo** ppTInfo)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_GetIDsOfNames(IXMLElement *iface, REFIID riid,
+ LPOLESTR* rgszNames, UINT cNames,
+ LCID lcid, DISPID* rgDispId)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_Invoke(IXMLElement *iface, DISPID dispIdMember,
+ REFIID riid, LCID lcid, WORD wFlags,
+ DISPPARAMS* pDispParams, VARIANT* pVarResult,
+ EXCEPINFO* pExcepInfo, UINT* puArgErr)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static inline BSTR str_dup_upper(BSTR str)
+{
+ INT len = (lstrlenW(str) + 1) * sizeof(WCHAR);
+ BSTR p = SysAllocStringLen(NULL, len);
+ if (p)
+ {
+ memcpy(p, str, len);
+ CharUpperW(p);
+ }
+ return p;
+}
+
+static HRESULT WINAPI xmlelem_get_tagName(IXMLElement *iface, BSTR *p)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ BSTR temp;
+
+ TRACE("(%p, %p)\n", iface, p);
+
+ if (!p)
+ return E_INVALIDARG;
+
+ temp = bstr_from_xmlChar(This->node->name);
+ *p = str_dup_upper(temp);
+ SysFreeString(temp);
+
+ TRACE("returning %s\n", debugstr_w(*p));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI xmlelem_put_tagName(IXMLElement *iface, BSTR p)
+{
+ FIXME("(%p, %p): stub\n", iface, p);
+
+ if (!p)
+ return E_INVALIDARG;
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **parent)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+
+ TRACE("(%p, %p)\n", iface, parent);
+
+ if (!parent)
+ return E_INVALIDARG;
+
+ *parent = NULL;
+
+ if (!This->node->parent)
+ return S_FALSE;
+
+ return XMLElement_create((IUnknown *)iface, This->node->parent, (LPVOID *)parent);
+}
+
+static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName,
+ VARIANT PropertyValue)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ xmlChar *name, *value;
+ xmlAttrPtr attr;
+
+ TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
+
+ if (!strPropertyName || V_VT(&PropertyValue) != VT_BSTR)
+ return E_INVALIDARG;
+
+ name = xmlChar_from_wchar(strPropertyName);
+ value = xmlChar_from_wchar(V_BSTR(&PropertyValue));
+ attr = xmlSetProp(This->node, name, value);
+
+ HeapFree(GetProcessHeap(), 0, name);
+ HeapFree(GetProcessHeap(), 0, value);
+ return (attr) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI xmlelem_getAttribute(IXMLElement *iface, BSTR strPropertyName,
+ VARIANT *PropertyValue)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ xmlChar *val = NULL, *name;
+ xmlAttrPtr ptr;
+
+ TRACE("(%p, %s, %p)\n", iface, debugstr_w(strPropertyName), PropertyValue);
+
+ if (!PropertyValue)
+ return E_INVALIDARG;
+
+ VariantClear(PropertyValue);
+ V_BSTR(PropertyValue) = NULL;
+
+ if (!strPropertyName)
+ return E_INVALIDARG;
+
+ name = xmlChar_from_wchar(strPropertyName);
+ ptr = This->node->properties;
+ while (ptr)
+ {
+ if (!lstrcmpiA((LPSTR)name, (LPSTR)ptr->name))
+ {
+ val = xmlNodeListGetString(ptr->doc, ptr->children, 1);
+ break;
+ }
+
+ ptr = ptr->next;
+ }
+
+ if (val)
+ {
+ V_VT(PropertyValue) = VT_BSTR;
+ V_BSTR(PropertyValue) = bstr_from_xmlChar(val);
+ }
+
+ HeapFree(GetProcessHeap(), 0, name);
+ xmlFree(val);
+ TRACE("returning %s\n", debugstr_w(V_BSTR(PropertyValue)));
+ return (val) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI xmlelem_removeAttribute(IXMLElement *iface, BSTR strPropertyName)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ xmlChar *name;
+ xmlAttrPtr attr;
+ int res;
+ HRESULT hr = S_FALSE;
+
+ TRACE("(%p, %s)\n", iface, debugstr_w(strPropertyName));
+
+ if (!strPropertyName)
+ return E_INVALIDARG;
+
+ name = xmlChar_from_wchar(strPropertyName);
+ attr = xmlHasProp(This->node, name);
+ if (!attr)
+ goto done;
+
+ res = xmlRemoveProp(attr);
+
+ if (res == 0)
+ hr = S_OK;
+
+done:
+ HeapFree(GetProcessHeap(), 0, name);
+ return hr;
+}
+
+static HRESULT WINAPI xmlelem_get_children(IXMLElement *iface, IXMLElementCollection **p)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+
+ TRACE("(%p, %p)\n", iface, p);
+
+ if (!p)
+ return E_INVALIDARG;
+
+ return XMLElementCollection_create((IUnknown *)iface, This->node->children, (LPVOID *)p);
+}
+
+static long type_libxml_to_msxml(xmlElementType type)
+{
+ switch (type)
+ {
+ case XML_ELEMENT_NODE:
+ return XMLELEMTYPE_ELEMENT;
+ case XML_TEXT_NODE:
+ return XMLELEMTYPE_TEXT;
+ case XML_COMMENT_NODE:
+ return XMLELEMTYPE_COMMENT;
+ case XML_DOCUMENT_NODE:
+ return XMLELEMTYPE_DOCUMENT;
+ case XML_DTD_NODE:
+ return XMLELEMTYPE_DTD;
+ case XML_PI_NODE:
+ return XMLELEMTYPE_PI;
+ default:
+ break;
+ }
+
+ return XMLELEMTYPE_OTHER;
+}
+
+static HRESULT WINAPI xmlelem_get_type(IXMLElement *iface, long *p)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+
+ TRACE("(%p, %p)\n", This, p);
+
+ if (!p)
+ return E_INVALIDARG;
+
+ *p = type_libxml_to_msxml(This->node->type);
+ TRACE("returning %ld\n", *p);
+ return S_OK;
+}
+
+static HRESULT WINAPI xmlelem_get_text(IXMLElement *iface, BSTR *p)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ xmlChar *content;
+
+ TRACE("(%p, %p)\n", iface, p);
+
+ if (!p)
+ return E_INVALIDARG;
+
+ content = xmlNodeGetContent(This->node);
+ *p = bstr_from_xmlChar(content);
+ TRACE("returning %s\n", debugstr_w(*p));
+ return S_OK;
+}
+
+static HRESULT WINAPI xmlelem_put_text(IXMLElement *iface, BSTR p)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ xmlChar *content;
+
+ TRACE("(%p, %s)\n", iface, debugstr_w(p));
+
+ /* FIXME: test which types can be used */
+ if (This->node->type == XML_ELEMENT_NODE)
+ return E_NOTIMPL;
+
+ content = xmlChar_from_wchar(p);
+ xmlNodeSetContent(This->node, content);
+ return S_OK;
+}
+
+static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildElem,
+ long lIndex, long lreserved)
+{
+ xmlelem *This = impl_from_IXMLElement(iface);
+ xmlelem *childElem = impl_from_IXMLElement(pChildElem);
+ xmlNodePtr child;
+
+ TRACE("(%p, %p, %ld, %ld)\n", iface, pChildElem, lIndex, lreserved);
+
+ if (lIndex == 0)
+ child = xmlAddChild(This->node, childElem->node);
+ else
+ child = xmlAddNextSibling(This->node, childElem->node->last);
+
+ return (child) ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChildElem)
+{
+ FIXME("(%p, %p): stub\n", iface, pChildElem);
+ return E_NOTIMPL;
+}
+
+static const struct IXMLElementVtbl xmlelem_vtbl =
+{
+ xmlelem_QueryInterface,
+ xmlelem_AddRef,
+ xmlelem_Release,
+ xmlelem_GetTypeInfoCount,
+ xmlelem_GetTypeInfo,
+ xmlelem_GetIDsOfNames,
+ xmlelem_Invoke,
+ xmlelem_get_tagName,
+ xmlelem_put_tagName,
+ xmlelem_get_parent,
+ xmlelem_setAttribute,
+ xmlelem_getAttribute,
+ xmlelem_removeAttribute,
+ xmlelem_get_children,
+ xmlelem_get_type,
+ xmlelem_get_text,
+ xmlelem_put_text,
+ xmlelem_addChild,
+ xmlelem_removeChild
+};
+
+HRESULT XMLElement_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
+{
+ xmlelem *elem;
+
+ TRACE("(%p,%p)\n", pUnkOuter, ppObj);
+
+ if (!ppObj)
+ return E_INVALIDARG;
+
+ *ppObj = NULL;
+
+ elem = HeapAlloc(GetProcessHeap(), 0, sizeof (*elem));
+ if(!elem)
+ return E_OUTOFMEMORY;
+
+ elem->lpVtbl = &xmlelem_vtbl;
+ elem->ref = 1;
+ elem->node = node;
+
+ *ppObj = &elem->lpVtbl;
+
+ TRACE("returning iface %p\n", *ppObj);
+ return S_OK;
+}
+
+/************************************************************************
+ * IXMLElementCollection
+ */
+typedef struct _xmlelem_collection
+{
+ const IXMLElementCollectionVtbl *lpVtbl;
+ const IEnumVARIANTVtbl *lpvtblIEnumVARIANT;
+ LONG ref;
+ LONG length;
+ xmlNodePtr node;
+
+ /* IEnumVARIANT members */
+ xmlNodePtr current;
+} xmlelem_collection;
+
+static inline xmlelem_collection *impl_from_IXMLElementCollection(IXMLElementCollection *iface)
+{
+ return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpVtbl));
+}
+
+static inline xmlelem_collection *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
+{
+ return (xmlelem_collection *)((char*)iface - FIELD_OFFSET(xmlelem_collection, lpvtblIEnumVARIANT));
+}
+
+static HRESULT WINAPI xmlelem_collection_QueryInterface(IXMLElementCollection *iface, REFIID riid, void** ppvObject)
+{
+ xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
+
+ TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IXMLElementCollection))
+ {
+ *ppvObject = iface;
+ }
+ else if (IsEqualGUID(riid, &IID_IEnumVARIANT))
+ {
+ *ppvObject = (IEnumVARIANT *)&(This->lpvtblIEnumVARIANT);
+ }
+ else
+ {
+ FIXME("interface %s not implemented\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ IXMLElementCollection_AddRef(iface);
+
+ return S_OK;
+}
+
+static ULONG WINAPI xmlelem_collection_AddRef(IXMLElementCollection *iface)
+{
+ xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
+ TRACE("%p\n", This);
+ return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI xmlelem_collection_Release(IXMLElementCollection *iface)
+{
+ xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
+ LONG ref;
+
+ TRACE("%p\n", This);
+
+ ref = InterlockedDecrement(&This->ref);
+ if (ref == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI xmlelem_collection_GetTypeInfoCount(IXMLElementCollection *iface, UINT* pctinfo)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_collection_GetTypeInfo(IXMLElementCollection *iface, UINT iTInfo,
+ LCID lcid, ITypeInfo** ppTInfo)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_collection_GetIDsOfNames(IXMLElementCollection *iface, REFIID riid,
+ LPOLESTR* rgszNames, UINT cNames,
+ LCID lcid, DISPID* rgDispId)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_collection_Invoke(IXMLElementCollection *iface, DISPID dispIdMember,
+ REFIID riid, LCID lcid, WORD wFlags,
+ DISPPARAMS* pDispParams, VARIANT* pVarResult,
+ EXCEPINFO* pExcepInfo, UINT* puArgErr)
+{
+ FIXME("\n");
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_collection_put_length(IXMLElementCollection *iface, long v)
+{
+ TRACE("(%p, %ld)\n", iface, v);
+ return E_FAIL;
+}
+
+static HRESULT WINAPI xmlelem_collection_get_length(IXMLElementCollection *iface, long *p)
+{
+ xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
+
+ TRACE("(%p, %p)\n", iface, p);
+
+ if (!p)
+ return E_INVALIDARG;
+
+ *p = This->length;
+ return S_OK;
+}
+
+static HRESULT WINAPI xmlelem_collection_get__newEnum(IXMLElementCollection *iface, IUnknown **ppUnk)
+{
+ xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
+
+ TRACE("(%p, %p)\n", iface, ppUnk);
+
+ if (!ppUnk)
+ return E_INVALIDARG;
+
+ *ppUnk = (IUnknown *)This;
+ IUnknown_AddRef(*ppUnk);
+ return S_OK;
+}
+
+static HRESULT WINAPI xmlelem_collection_item(IXMLElementCollection *iface, VARIANT var1,
+ VARIANT var2, IDispatch **ppDisp)
+{
+ xmlelem_collection *This = impl_from_IXMLElementCollection(iface);
+ xmlNodePtr ptr = This->node;
+ int index, i;
+
+ TRACE("(%p, %p)\n", iface, ppDisp);
+
+ if (!ppDisp)
+ return E_INVALIDARG;
+
+ *ppDisp = NULL;
+
+ index = V_I4(&var1);
+ if (index < 0)
+ return E_INVALIDARG;
+ if (index >= This->length)
+ return E_FAIL;
+
+ for (i = 0; i < index; i++)
+ ptr = ptr->next;
+
+ return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)ppDisp);
+}
+
+static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl =
+{
+ xmlelem_collection_QueryInterface,
+ xmlelem_collection_AddRef,
+ xmlelem_collection_Release,
+ xmlelem_collection_GetTypeInfoCount,
+ xmlelem_collection_GetTypeInfo,
+ xmlelem_collection_GetIDsOfNames,
+ xmlelem_collection_Invoke,
+ xmlelem_collection_put_length,
+ xmlelem_collection_get_length,
+ xmlelem_collection_get__newEnum,
+ xmlelem_collection_item
+};
+
+/************************************************************************
+ * xmlelem_collection implementation of IEnumVARIANT.
+ */
+static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_QueryInterface(
+ IEnumVARIANT *iface, REFIID riid, LPVOID *ppvObj)
+{
+ xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
+ return IXMLDocument_QueryInterface((IXMLDocument *)this, riid, ppvObj);
+}
+
+static ULONG WINAPI xmlelem_collection_IEnumVARIANT_AddRef(
+ IEnumVARIANT *iface)
+{
+ xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
+ return IXMLDocument_AddRef((IXMLDocument *)this);
+}
+
+static ULONG WINAPI xmlelem_collection_IEnumVARIANT_Release(
+ IEnumVARIANT *iface)
+{
+ xmlelem_collection *this = impl_from_IEnumVARIANT(iface);
+ return IXMLDocument_Release((IXMLDocument *)this);
+}
+
+static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next(
+ IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
+{
+ xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
+ xmlNodePtr ptr = This->current;
+
+ TRACE("(%p, %d, %p, %p)\n", iface, celt, rgVar, pCeltFetched);
+
+ if (!rgVar)
+ return E_INVALIDARG;
+
+ /* FIXME: handle celt */
+ if (pCeltFetched)
+ *pCeltFetched = 1;
+
+ This->current = This->current->next;
+
+ V_VT(rgVar) = VT_DISPATCH;
+ return XMLElement_create((IUnknown *)iface, ptr, (LPVOID *)&V_DISPATCH(rgVar));
+}
+
+static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip(
+ IEnumVARIANT *iface, ULONG celt)
+{
+ FIXME("(%p, %d): stub\n", iface, celt);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Reset(
+ IEnumVARIANT *iface)
+{
+ xmlelem_collection *This = impl_from_IEnumVARIANT(iface);
+ This->current = This->node;
+ return S_OK;
+}
+
+static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Clone(
+ IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
+{
+ FIXME("(%p, %p): stub\n", iface, ppEnum);
+ return E_NOTIMPL;
+}
+
+static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl =
+{
+ xmlelem_collection_IEnumVARIANT_QueryInterface,
+ xmlelem_collection_IEnumVARIANT_AddRef,
+ xmlelem_collection_IEnumVARIANT_Release,
+ xmlelem_collection_IEnumVARIANT_Next,
+ xmlelem_collection_IEnumVARIANT_Skip,
+ xmlelem_collection_IEnumVARIANT_Reset,
+ xmlelem_collection_IEnumVARIANT_Clone
+};
+
+HRESULT XMLElementCollection_create(IUnknown *pUnkOuter, xmlNodePtr node, LPVOID *ppObj)
+{
+ xmlelem_collection *collection;
+ xmlNodePtr ptr;
+
+ TRACE("(%p,%p)\n", pUnkOuter, ppObj);
+
+ *ppObj = NULL;
+
+ if (!node)
+ return S_FALSE;
+
+ collection = HeapAlloc(GetProcessHeap(), 0, sizeof (*collection));
+ if(!collection)
+ return E_OUTOFMEMORY;
+
+ collection->lpVtbl = &xmlelem_collection_vtbl;
+ collection->lpvtblIEnumVARIANT = &xmlelem_collection_IEnumVARIANTvtbl;
+ collection->ref = 1;
+ collection->length = 0;
+ collection->node = node;
+ collection->current = node;
+
+ ptr = node;
+ while (ptr)
+ {
+ collection->length++;
+ ptr = ptr->next;
+ }
+
+ *ppObj = &collection->lpVtbl;
+
+ TRACE("returning iface %p\n", *ppObj);
+ return S_OK;
+}
+
+#endif
+
--
1.4.1
More information about the wine-patches
mailing list