Signed-off-by: Daniel Lehman dlehman25@gmail.com --- dlls/msxml3/nodemap.c | 123 ++++++++++++++++++++++++++++++++++++- dlls/msxml3/tests/domdoc.c | 2 +- 2 files changed, 122 insertions(+), 3 deletions(-)
diff --git a/dlls/msxml3/nodemap.c b/dlls/msxml3/nodemap.c index a9fef4769d..b35fd34103 100644 --- a/dlls/msxml3/nodemap.c +++ b/dlls/msxml3/nodemap.c @@ -39,6 +39,7 @@ #include "msxml_private.h"
#include "wine/debug.h" +#include "wine/list.h"
#ifdef HAVE_LIBXML2
@@ -54,10 +55,17 @@ typedef struct xmlNodePtr node; LONG iterator; IEnumVARIANT *enumvariant; + struct list nsattrs;
const struct nodemap_funcs *funcs; } xmlnodemap;
+typedef struct +{ + struct list entry; + xmlAttrPtr attr; +} nsattr_entry; + static HRESULT nodemap_get_item(IUnknown *iface, LONG index, VARIANT *item) { V_VT(item) = VT_DISPATCH; @@ -140,9 +148,20 @@ static ULONG WINAPI xmlnodemap_Release( TRACE("(%p)->(%d)\n", This, ref); if ( ref == 0 ) { + nsattr_entry *nsattr; + struct list *head; + xmlnode_release( This->node ); xmldoc_release( This->node->doc ); if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant); + while ((head = list_head( &This->nsattrs ))) + { + list_remove( head ); + nsattr = LIST_ENTRY( head, nsattr_entry, entry ); + xmlFreeNs( nsattr->attr->ns ); + xmlFreeProp( nsattr->attr ); + heap_free( nsattr ); + } heap_free( This ); }
@@ -224,16 +243,102 @@ static HRESULT WINAPI xmlnodemap_removeNamedItem( return This->funcs->remove_named_item(This->node, name, namedItem); }
+static HRESULT copy_ns_as_attrs(xmlnodemap *This) +{ + xmlNsPtr ns; + xmlNsPtr cur; + xmlAttrPtr prop; + nsattr_entry *entry; + + cur = This->node->nsDef; + while (cur) + { + entry = heap_alloc(sizeof(*entry)); + if (!entry) + return E_OUTOFMEMORY; + + ns = xmlNewNs(NULL, BAD_CAST "http://www.w3.org/2000/xmlns/", BAD_CAST "xmlns"); + if (!ns) + { + heap_free(entry); + return E_OUTOFMEMORY; + } + + prop = xmlNewNsProp(NULL, ns, cur->prefix, cur->href); + if (!prop) + { + xmlFreeNs(ns); + heap_free(entry); + return E_OUTOFMEMORY; + } + + prop->doc = This->node->doc; + entry->attr = prop; + list_add_tail(&This->nsattrs, &entry->entry); + + cur = cur->next; + } + + return S_OK; +} + static HRESULT WINAPI xmlnodemap_get_item( IXMLDOMNamedNodeMap *iface, LONG index, IXMLDOMNode** item) { + HRESULT hr; + xmlAttrPtr cur; + struct list *ptr; + nsattr_entry *nsattr; xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
TRACE("(%p)->(%d %p)\n", This, index, item);
- return This->funcs->get_item(This->node, index, item); + hr = This->funcs->get_item(This->node, index, item); + if (hr != S_FALSE) + return hr; + + ptr = list_head(&This->nsattrs); + if (!ptr) + { + if (!This->node->nsDef) + return S_FALSE; + + if (This->node->nsDef) + { + hr = copy_ns_as_attrs(This); + if (FAILED(hr)) + return hr; + } + + ptr = list_head(&This->nsattrs); + if (!ptr) + return FALSE; + } + + if (This->node->properties) + { + --index; + cur = This->node->properties; + while (cur->next) + { + --index; + cur = cur->next; + } + } + + if (index < 0) + return S_FALSE; + + while (index--) + ptr = list_next(ptr, ptr); + + nsattr = LIST_ENTRY(ptr, nsattr_entry, entry); + cur = nsattr->attr; + *item = create_node((xmlNodePtr) cur); + + return S_OK; }
static HRESULT WINAPI xmlnodemap_get_length( @@ -241,10 +346,23 @@ static HRESULT WINAPI xmlnodemap_get_length( LONG *length) { xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface ); + xmlNsPtr cur; + HRESULT hr;
TRACE("(%p)->(%p)\n", This, length);
- return This->funcs->get_length(This->node, length); + hr = This->funcs->get_length(This->node, length); + if (FAILED(hr)) + return hr; + + cur = This->node->nsDef; + while (cur) + { + ++*length; + cur = cur->next; + } + + return S_OK; }
static HRESULT WINAPI xmlnodemap_getQualifiedItem( @@ -447,6 +565,7 @@ IXMLDOMNamedNodeMap *create_nodemap(xmlNodePtr node, const struct nodemap_funcs This->ref = 1; This->iterator = 0; This->enumvariant = NULL; + list_init(&This->nsattrs); This->funcs = funcs;
init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex); diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index ffb9e1462d..667feaa244 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -12894,7 +12894,7 @@ void test_namespaces_as_attributes(void) len = -1; hr = IXMLDOMNamedNodeMap_get_length(map, &len); EXPECT_HR(hr, S_OK); - todo_wine ok(len == 3, "got %d\n", len); + ok(len == 3, "got %d\n", len);
for (i = 0; i < len; i++) {