>From b564710f192e61256aa4f3ecb322a0ab583fec70 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Sat, 12 Nov 2011 17:14:11 +0300
Subject: [PATCH 2/3] Fix getNamedItem() for qualified node names

---
 dlls/msxml3/nodemap.c      |   42 +++++++++++++++-
 dlls/msxml3/tests/domdoc.c |  110 +++++++++++++++++++++++++++++++++++++------
 2 files changed, 133 insertions(+), 19 deletions(-)

diff --git a/dlls/msxml3/nodemap.c b/dlls/msxml3/nodemap.c
index ebc2bd5..47adcd9 100644
--- a/dlls/msxml3/nodemap.c
+++ b/dlls/msxml3/nodemap.c
@@ -199,11 +199,47 @@ static HRESULT WINAPI xmlnodemap_Invoke(
 static HRESULT WINAPI xmlnodemap_getNamedItem(
     IXMLDOMNamedNodeMap *iface,
     BSTR name,
-    IXMLDOMNode** namedItem)
+    IXMLDOMNode** item)
 {
     xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
-    TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), namedItem );
-    return IXMLDOMNamedNodeMap_getQualifiedItem(iface, name, NULL, namedItem);
+    xmlChar *nameA, *local, *prefix;
+    BSTR uriW, localW;
+    xmlNsPtr ns;
+    HRESULT hr;
+
+    TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), item );
+
+    nameA = xmlchar_from_wchar(name);
+    local = xmlSplitQName2(nameA, &prefix);
+    heap_free(nameA);
+
+    if (!local)
+        return IXMLDOMNamedNodeMap_getQualifiedItem(iface, name, NULL, item);
+
+    /* try to get namespace uri for supplied qualified name */
+    ns = xmlSearchNs(This->node->doc, This->node, prefix);
+
+    xmlFree(prefix);
+
+    if (!ns)
+    {
+        xmlFree(local);
+        if (item) *item = NULL;
+        return item ? S_FALSE : E_INVALIDARG;
+    }
+
+    uriW = bstr_from_xmlChar(ns->href);
+    localW = bstr_from_xmlChar(local);
+    xmlFree(local);
+
+    TRACE("got qualified node %s, uri=%s\n", debugstr_w(localW), debugstr_w(uriW));
+
+    hr = IXMLDOMNamedNodeMap_getQualifiedItem(iface, localW, uriW, item);
+
+    SysFreeString(localW);
+    SysFreeString(uriW);
+
+    return hr;
 }
 
 static HRESULT WINAPI xmlnodemap_setNamedItem(
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index affdfaa..a79da43 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -1746,6 +1746,12 @@ static const char* leading_spaces[] = {
     0
 };
 
+static const char default_ns_doc[] = {
+    "<?xml version=\"1.0\"?>"
+    "<a xmlns:ns=\"nshref\" xml:lang=\"ru\" ns:b=\"b attr\" xml:c=\"c attr\" "
+    "    d=\"d attr\" />"
+};
+
 static const WCHAR szNonExistentFile[] = {
     'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
 };
@@ -7973,63 +7979,135 @@ static void test_splitText(void)
     free_bstrs();
 }
 
+typedef struct {
+    const char *name;
+    const char *uri;
+    HRESULT hr;
+} ns_item_t;
+
+/* default_ns_doc used */
+static const ns_item_t qualified_item_tests[] = {
+    { "xml:lang", NULL, S_FALSE },
+    { "xml:lang", "http://www.w3.org/XML/1998/namespace", S_FALSE },
+    { "lang", "http://www.w3.org/XML/1998/namespace", S_OK },
+    { "ns:b", NULL, S_FALSE },
+    { "ns:b", "nshref", S_FALSE },
+    { "b", "nshref", S_OK },
+    { "d", NULL, S_OK },
+    { NULL }
+};
+
+static const ns_item_t named_item_tests[] = {
+    { "xml:lang", NULL, S_OK },
+    { "lang", NULL, S_FALSE },
+    { "ns:b", NULL, S_OK },
+    { "b", NULL, S_FALSE },
+    { "d", NULL, S_OK },
+    { NULL }
+};
+
 static void test_getQualifiedItem(void)
 {
-    IXMLDOMDocument *doc;
-    IXMLDOMElement *element;
     IXMLDOMNode *pr_node, *node;
     IXMLDOMNodeList *root_list;
     IXMLDOMNamedNodeMap *map;
+    IXMLDOMElement *element;
+    const ns_item_t* ptr;
+    IXMLDOMDocument *doc;
     VARIANT_BOOL b;
+    HRESULT hr;
     BSTR str;
     LONG len;
-    HRESULT hr;
 
     doc = create_document(&IID_IXMLDOMDocument);
     if (!doc) return;
 
     str = SysAllocString( szComplete4 );
     hr = IXMLDOMDocument_loadXML( doc, str, &b );
-    ok( hr == S_OK, "loadXML failed\n");
+    EXPECT_HR(hr, S_OK);
     ok( b == VARIANT_TRUE, "failed to load XML string\n");
     SysFreeString( str );
 
     hr = IXMLDOMDocument_get_documentElement(doc, &element);
-    ok( hr == S_OK, "ret %08x\n", hr);
+    EXPECT_HR(hr, S_OK);
 
     hr = IXMLDOMElement_get_childNodes(element, &root_list);
-    ok( hr == S_OK, "ret %08x\n", hr);
+    EXPECT_HR(hr, S_OK);
 
     hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
-    ok( hr == S_OK, "ret %08x\n", hr);
+    EXPECT_HR(hr, S_OK);
     IXMLDOMNodeList_Release(root_list);
 
     hr = IXMLDOMNode_get_attributes(pr_node, &map);
-    ok( hr == S_OK, "ret %08x\n", hr);
+    EXPECT_HR(hr, S_OK);
     IXMLDOMNode_Release(pr_node);
 
+    len = 0;
     hr = IXMLDOMNamedNodeMap_get_length(map, &len);
-    ok( hr == S_OK, "ret %08x\n", hr);
+    EXPECT_HR(hr, S_OK);
     ok( len == 3, "length %d\n", len);
 
     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, NULL);
-    ok( hr == E_INVALIDARG, "ret %08x\n", hr);
+    EXPECT_HR(hr, E_INVALIDARG);
 
     node = (void*)0xdeadbeef;
     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, &node);
-    ok( hr == E_INVALIDARG, "ret %08x\n", hr);
+    EXPECT_HR(hr, E_INVALIDARG);
     ok( node == (void*)0xdeadbeef, "got %p\n", node);
 
     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, NULL);
-    ok( hr == E_INVALIDARG, "ret %08x\n", hr);
+    EXPECT_HR(hr, E_INVALIDARG);
 
     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, &node);
-    ok( hr == S_OK, "ret %08x\n", hr);
+    EXPECT_HR(hr, S_OK);
+
     IXMLDOMNode_Release(node);
+    IXMLDOMNamedNodeMap_Release(map);
+    IXMLDOMElement_Release(element);
 
-    IXMLDOMNamedNodeMap_Release( map );
-    IXMLDOMElement_Release( element );
-    IXMLDOMDocument_Release( doc );
+    hr = IXMLDOMDocument_loadXML(doc, _bstr_(default_ns_doc), &b);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
+    EXPECT_HR(hr, S_OK);
+    IXMLDOMNode_Release(node);
+
+    hr = IXMLDOMElement_get_attributes(element, &map);
+    EXPECT_HR(hr, S_OK);
+
+    ptr = qualified_item_tests;
+    while (ptr->name)
+    {
+       node = (void*)0xdeadbeef;
+       hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
+       ok(hr == ptr->hr, "%s, %s: got 0x%08x, expected 0x%08x\n", ptr->name, ptr->uri, hr, ptr->hr);
+       if (hr == S_OK)
+           IXMLDOMNode_Release(node);
+       else
+           ok(node == NULL, "%s, %s: got %p\n", ptr->name, ptr->uri, node);
+       ptr++;
+    }
+
+    ptr = named_item_tests;
+    while (ptr->name)
+    {
+       node = (void*)0xdeadbeef;
+       hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_(ptr->name), &node);
+       ok(hr == ptr->hr, "%s: got 0x%08x, expected 0x%08x\n", ptr->name, hr, ptr->hr);
+       if (hr == S_OK)
+           IXMLDOMNode_Release(node);
+       else
+           ok(node == NULL, "%s: got %p\n", ptr->name, node);
+       ptr++;
+    }
+
+    IXMLDOMNamedNodeMap_Release(map);
+
+    IXMLDOMElement_Release(element);
+    IXMLDOMDocument_Release(doc);
     free_bstrs();
 }
 
-- 
1.5.6.5

