>From 29d170c671abe34f098cd3a196eec87b1f62b841 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Mon, 23 Jan 2012 07:45:44 +0300
Subject: [PATCH 4/4] Initial implementation of ::getPrefix()

---
 dlls/msxml3/mxnamespace.c  |   47 +++++++++++++-
 dlls/msxml3/tests/domdoc.c |  146 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 186 insertions(+), 7 deletions(-)

diff --git a/dlls/msxml3/mxnamespace.c b/dlls/msxml3/mxnamespace.c
index dbfbdc6..f21c758 100644
--- a/dlls/msxml3/mxnamespace.c
+++ b/dlls/msxml3/mxnamespace.c
@@ -1,7 +1,7 @@
 /*
  *    IMXNamespaceManager implementation
  *
- * Copyright 2011 Nikolay Sivov for CodeWeavers
+ * Copyright 2011-2012 Nikolay Sivov for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -143,6 +143,22 @@ static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index,
     return S_OK;
 }
 
+/* returned stored pointer, caller needs to copy it */
+static HRESULT get_declared_prefix_uri(const struct nscontext *ctxt, const WCHAR *uri, BSTR *prefix)
+{
+    int i;
+
+    for (i = 0; i < ctxt->count; i++)
+        if (!strcmpW(ctxt->ns[i].uri, uri))
+        {
+            *prefix = ctxt->ns[i].prefix;
+            return S_OK;
+        }
+
+    *prefix = NULL;
+    return E_FAIL;
+}
+
 static HRESULT get_uri_from_prefix(const struct nscontext *ctxt, const WCHAR *prefix, BSTR *uri)
 {
     int i;
@@ -294,8 +310,33 @@ static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
     const WCHAR *uri, LONG index, WCHAR *prefix, int *prefix_len)
 {
     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
-    FIXME("(%p)->(%s %d %p %p): stub\n", This, debugstr_w(uri), index, prefix, prefix_len);
-    return E_NOTIMPL;
+    struct nscontext *ctxt;
+    HRESULT hr;
+    BSTR prfx;
+
+    TRACE("(%p)->(%s %d %p %p)\n", This, debugstr_w(uri), index, prefix, prefix_len);
+
+    if (!uri || !*uri || !prefix_len) return E_INVALIDARG;
+
+    ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
+
+    hr = get_declared_prefix_uri(ctxt, uri, &prfx);
+    if (hr == S_OK)
+    {
+        /* TODO: figure out what index argument is for */
+        if (index) return E_FAIL;
+
+        if (prefix)
+        {
+            if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
+            strcpyW(prefix, prfx);
+        }
+
+        *prefix_len = SysStringLen(prfx);
+        TRACE("prefix=%s\n", debugstr_w(prfx));
+    }
+
+    return hr;
 }
 
 static HRESULT WINAPI namespacemanager_getURI(IMXNamespaceManager *iface,
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 7c8bd9c..a00f24a 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -10403,7 +10403,7 @@ static void test_domobj_dispex(IUnknown *obj)
     IDispatchEx_Release(dispex);
 }
 
-static void test_nsnamespacemanager(void)
+static void test_mxnamespacemanager(void)
 {
     static const char xmluriA[] = "http://www.w3.org/XML/1998/namespace";
     IVBMXNamespaceManager *mgr2;
@@ -10521,10 +10521,148 @@ todo_wine {
 
     IMXNamespaceManager_Release(nsmgr);
 
+    /* ::getPrefix() */
+    hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
+        &IID_IMXNamespaceManager, (void**)&nsmgr);
+    EXPECT_HR(hr, S_OK);
+
+    hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, NULL);
+    EXPECT_HR(hr, E_INVALIDARG);
+
+    len = -1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, &len);
+    EXPECT_HR(hr, E_INVALIDARG);
+    ok(len == -1, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
+    EXPECT_HR(hr, E_FAIL);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 0;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
+    EXPECT_HR(hr, E_FAIL);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 0, "got %d\n", len);
+
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
+    EXPECT_HR(hr, S_OK);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
+    ok(len == 3, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("xml")), "got %s\n", wine_dbgstr_w(buffW));
+    ok(len == 3, "got %d\n", len);
+
+    /* with null buffer it's possible to get required length */
+    len = 100;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(len == 3, "got %d\n", len);
+
+    len = 0;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(len == 3, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 1, buffW, &len);
+    EXPECT_HR(hr, E_FAIL);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 2, buffW, &len);
+    EXPECT_HR(hr, E_FAIL);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 0, buffW, &len);
+    EXPECT_HR(hr, E_INVALIDARG);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
+    EXPECT_HR(hr, E_INVALIDARG);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, buffW, &len);
+    EXPECT_HR(hr, E_INVALIDARG);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 1, buffW, &len);
+    EXPECT_HR(hr, E_FAIL);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
+    EXPECT_HR(hr, E_INVALIDARG);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    /* declare another one, indices are shifted */
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
+    EXPECT_HR(hr, S_OK);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
+    ok(len == 3, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
+    ok(len == 3, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 1, buffW, &len);
+    EXPECT_HR(hr, E_FAIL);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    len = 100;
+    buffW[0] = 0x1;
+    hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
+    EXPECT_HR(hr, E_INVALIDARG);
+    ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
+    ok(len == 100, "got %d\n", len);
+
+    IMXNamespaceManager_Release(nsmgr);
+
     free_bstrs();
 }
 
-static void test_nsnamespacemanager_override(void)
+static void test_mxnamespacemanager_override(void)
 {
     IMXNamespaceManager *nsmgr;
     WCHAR buffW[250];
@@ -11478,8 +11616,8 @@ START_TEST(domdoc)
         &IID_IMXNamespaceManager, (void**)&unk);
     if (hr == S_OK)
     {
-        test_nsnamespacemanager();
-        test_nsnamespacemanager_override();
+        test_mxnamespacemanager();
+        test_mxnamespacemanager_override();
 
         IUnknown_Release(unk);
     }
-- 
1.5.6.5


