[PATCH 3/5] Implement declarePrefix() and getDeclaredPrefix()

Nikolay Sivov nsivov at codeweavers.com
Sun Aug 21 12:47:09 CDT 2011


---
 dlls/msxml3/mxnamespace.c  |  139 ++++++++++++++++++++++++++++++++++++++++++--
 dlls/msxml3/tests/domdoc.c |   88 ++++++++++++++++++++++++++--
 2 files changed, 215 insertions(+), 12 deletions(-)

diff --git a/dlls/msxml3/mxnamespace.c b/dlls/msxml3/mxnamespace.c
index 8370469..1a8133f 100644
--- a/dlls/msxml3/mxnamespace.c
+++ b/dlls/msxml3/mxnamespace.c
@@ -39,14 +39,38 @@
 #include "msxml_private.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
 
+struct ns
+{
+    BSTR prefix;
+    BSTR uri;
+};
+
+struct nscontext
+{
+    struct list entry;
+
+    struct ns *ns;
+    int   count;
+    int   max_alloc;
+};
+
+#define DEFAULT_PREFIX_ALLOC_COUNT 16
+
+static const WCHAR xmlW[] = {'x','m','l',0};
+static const WCHAR xmluriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g',
+    '/','X','M','L','/','1','9','9','8','/','n','a','m','e','s','p','a','c','e',0};
+
 typedef struct
 {
     IMXNamespaceManager   IMXNamespaceManager_iface;
     IVBMXNamespaceManager IVBMXNamespaceManager_iface;
     LONG ref;
+
+    struct list ctxts;
 } namespacemanager;
 
 static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
@@ -59,6 +83,65 @@ static inline namespacemanager *impl_from_IVBMXNamespaceManager( IVBMXNamespaceM
     return CONTAINING_RECORD(iface, namespacemanager, IVBMXNamespaceManager_iface);
 }
 
+static HRESULT declare_prefix(struct nscontext *ctxt, const WCHAR *prefix, const WCHAR *uri)
+{
+    if (ctxt->count == ctxt->max_alloc)
+    {
+        ctxt->max_alloc *= 2;
+        ctxt->ns = heap_realloc(ctxt->ns, ctxt->max_alloc*sizeof(*ctxt->ns));
+    }
+
+    ctxt->ns[ctxt->count].prefix = SysAllocString(prefix);
+    ctxt->ns[ctxt->count].uri = SysAllocString(uri);
+    ctxt->count++;
+
+    return S_OK;
+}
+
+/* returned stored pointer, caller needs to copy it */
+static HRESULT get_declared_prefix_idx(const struct nscontext *ctxt, LONG index, BSTR *prefix)
+{
+    if (index >= ctxt->count || index < 0) return E_FAIL;
+
+    if (index > 0) index = ctxt->count - index;
+    *prefix = ctxt->ns[index].prefix;
+
+    return S_OK;
+}
+
+static struct nscontext* alloc_ns_context(void)
+{
+    struct nscontext *ctxt;
+
+    ctxt = heap_alloc(sizeof(*ctxt));
+    if (!ctxt) return NULL;
+
+    ctxt->count = 0;
+    ctxt->max_alloc = DEFAULT_PREFIX_ALLOC_COUNT;
+    ctxt->ns = heap_alloc(ctxt->max_alloc*sizeof(*ctxt->ns));
+
+    /* first allocated prefix is always 'xml' */
+    ctxt->ns[0].prefix = SysAllocString(xmlW);
+    ctxt->ns[0].uri = SysAllocString(xmluriW);
+    ctxt->count++;
+
+    return ctxt;
+}
+
+static void free_ns_context(struct nscontext *ctxt)
+{
+    int i;
+
+    for (i = 0; i < ctxt->count; i++)
+    {
+        SysFreeString(ctxt->ns[i].prefix);
+        SysFreeString(ctxt->ns[i].uri);
+    }
+
+    heap_free(ctxt->ns);
+    heap_free(ctxt);
+}
+
 static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
 {
     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
@@ -119,17 +202,47 @@ static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
 static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
     const WCHAR *prefix, const WCHAR *namespaceURI)
 {
+    static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
+
     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
-    FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
-    return E_NOTIMPL;
+    struct nscontext *ctxt;
+
+    TRACE("(%p)->(%s %s)\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
+
+    if (!prefix) return E_FAIL;
+
+    if (!strcmpW(prefix, xmlW) || !strcmpW(prefix, xmlnsW) || (prefix && !namespaceURI))
+        return E_INVALIDARG;
+
+    ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
+    return declare_prefix(ctxt, prefix, namespaceURI);
 }
 
 static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
     LONG index, WCHAR *prefix, int *prefix_len)
 {
     namespacemanager *This = impl_from_IMXNamespaceManager( iface );
-    FIXME("(%p)->(%d %p %p): stub\n", This, index, prefix, prefix_len);
-    return E_NOTIMPL;
+    struct nscontext *ctxt;
+    HRESULT hr;
+    BSTR prfx;
+
+    TRACE("(%p)->(%d %p %p)\n", This, index, prefix, prefix_len);
+
+    if (!prefix_len) return E_POINTER;
+
+    ctxt = LIST_ENTRY(list_head(&This->ctxts), struct nscontext, entry);
+    hr = get_declared_prefix_idx(ctxt, index, &prfx);
+    if (hr != S_OK) return hr;
+
+    if (prefix)
+    {
+        if (*prefix_len < (INT)SysStringLen(prfx)) return E_XML_BUFFERTOOSMALL;
+        strcpyW(prefix, prfx);
+    }
+
+    *prefix_len = SysStringLen(prfx);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
@@ -208,7 +321,17 @@ static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
     TRACE("(%p)->(%u)\n", This, ref );
 
     if ( ref == 0 )
+    {
+        struct nscontext *ctxt, *ctxt2;
+
+        LIST_FOR_EACH_ENTRY_SAFE(ctxt, ctxt2, &This->ctxts, struct nscontext, entry)
+        {
+            list_remove(&ctxt->entry);
+            free_ns_context(ctxt);
+        }
+
         heap_free( This );
+    }
 
     return ref;
 }
@@ -327,8 +450,7 @@ static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *if
     BSTR prefix, BSTR namespaceURI)
 {
     namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
-    FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
-    return E_NOTIMPL;
+    return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
 }
 
 static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
@@ -388,6 +510,7 @@ static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
 HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
 {
     namespacemanager *ns;
+    struct nscontext *ctxt;
 
     TRACE("(%p, %p)\n", outer, obj);
 
@@ -399,6 +522,10 @@ HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
     ns->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
     ns->ref = 1;
 
+    list_init(&ns->ctxts);
+    ctxt = alloc_ns_context();
+    list_add_head(&ns->ctxts, &ctxt->entry);
+
     *obj = &ns->IMXNamespaceManager_iface;
 
     TRACE("returning iface %p\n", *obj);
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 9d71483..ef8c014 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -10148,7 +10148,7 @@ todo_wine {
     /* prefix already added */
     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
     EXPECT_HR(hr, S_FALSE);
-
+}
     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), NULL);
     EXPECT_HR(hr, E_INVALIDARG);
 
@@ -10158,10 +10158,10 @@ todo_wine {
 
     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xmlns"), _bstr_("uri1"));
     EXPECT_HR(hr, E_INVALIDARG);
-
+todo_wine {
     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, -1, NULL, NULL);
     EXPECT_HR(hr, E_FAIL);
-
+}
     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, NULL);
     EXPECT_HR(hr, E_POINTER);
 
@@ -10169,23 +10169,98 @@ todo_wine {
     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, &len);
     EXPECT_HR(hr, S_OK);
     ok(len == 3, "got %d\n", len);
-}
 
     len = -1;
     buffW[0] = 0x1;
     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
-    todo_wine EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
+    EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
     ok(len == -1, "got %d\n", len);
     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
 
     len = 10;
     buffW[0] = 0x1;
     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
-todo_wine {
     EXPECT_HR(hr, S_OK);
     ok(len == 3, "got %d\n", len);
     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
+
+    IMXNamespaceManager_Release(nsmgr);
+
+    free_bstrs();
 }
+
+static void test_nsnamespacemanager_override(void)
+{
+    IMXNamespaceManager *nsmgr;
+    WCHAR buffW[250];
+    HRESULT hr;
+    INT len;
+
+    hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
+        &IID_IMXNamespaceManager, (void**)&nsmgr);
+    if (hr != S_OK)
+    {
+        win_skip("MXNamespaceManager is not available\n");
+        return;
+    }
+
+    len = sizeof(buffW)/sizeof(WCHAR);
+    buffW[0] = 0;
+    hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
+
+    len = sizeof(buffW)/sizeof(WCHAR);
+    buffW[0] = 0;
+    hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
+    EXPECT_HR(hr, E_FAIL);
+
+    hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_FALSE);
+    todo_wine EXPECT_HR(hr, S_OK);
+
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
+    todo_wine EXPECT_HR(hr, S_OK);
+
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), _bstr_("ns0 uri"));
+    EXPECT_HR(hr, S_OK);
+
+    len = sizeof(buffW)/sizeof(WCHAR);
+    buffW[0] = 0;
+    hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
+
+    len = sizeof(buffW)/sizeof(WCHAR);
+    buffW[0] = 0;
+    hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("ns0")), "got prefix %s\n", wine_dbgstr_w(buffW));
+
+    len = sizeof(buffW)/sizeof(WCHAR);
+    buffW[0] = 0;
+    hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 2, buffW, &len);
+    todo_wine EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
+
+    /* new prefix placed at index 1 always */
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
+    EXPECT_HR(hr, S_OK);
+
+    len = sizeof(buffW)/sizeof(WCHAR);
+    buffW[0] = 0;
+    hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(buffW, _bstr_("ns1")), "got prefix %s\n", wine_dbgstr_w(buffW));
+
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_(""), NULL);
+    todo_wine EXPECT_HR(hr, E_FAIL);
+
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
+    EXPECT_HR(hr, E_FAIL);
+
+    hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
+    EXPECT_HR(hr, E_FAIL);
+
     IMXNamespaceManager_Release(nsmgr);
 
     free_bstrs();
@@ -10266,6 +10341,7 @@ START_TEST(domdoc)
     test_xsltemplate();
 
     test_nsnamespacemanager();
+    test_nsnamespacemanager_override();
 
     CoUninitialize();
 }
-- 
1.5.6.5



--------------070503050006000908040304--



More information about the wine-patches mailing list