msxml3/mxnamespace: Implement declarePrefix() and getDeclaredPrefix().
This commit is contained in:
parent
7f47d97e12
commit
42f65e1358
|
@ -39,14 +39,38 @@
|
||||||
#include "msxml_private.h"
|
#include "msxml_private.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(msxml);
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
IMXNamespaceManager IMXNamespaceManager_iface;
|
IMXNamespaceManager IMXNamespaceManager_iface;
|
||||||
IVBMXNamespaceManager IVBMXNamespaceManager_iface;
|
IVBMXNamespaceManager IVBMXNamespaceManager_iface;
|
||||||
LONG ref;
|
LONG ref;
|
||||||
|
|
||||||
|
struct list ctxts;
|
||||||
} namespacemanager;
|
} namespacemanager;
|
||||||
|
|
||||||
static inline namespacemanager *impl_from_IMXNamespaceManager( IMXNamespaceManager *iface )
|
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);
|
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)
|
static HRESULT WINAPI namespacemanager_QueryInterface(IMXNamespaceManager *iface, REFIID riid, void **ppvObject)
|
||||||
{
|
{
|
||||||
namespacemanager *This = impl_from_IMXNamespaceManager( iface );
|
namespacemanager *This = impl_from_IMXNamespaceManager( iface );
|
||||||
|
@ -119,17 +202,47 @@ static HRESULT WINAPI namespacemanager_popContext(IMXNamespaceManager *iface)
|
||||||
static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
|
static HRESULT WINAPI namespacemanager_declarePrefix(IMXNamespaceManager *iface,
|
||||||
const WCHAR *prefix, const WCHAR *namespaceURI)
|
const WCHAR *prefix, const WCHAR *namespaceURI)
|
||||||
{
|
{
|
||||||
|
static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
|
||||||
|
|
||||||
namespacemanager *This = impl_from_IMXNamespaceManager( iface );
|
namespacemanager *This = impl_from_IMXNamespaceManager( iface );
|
||||||
FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
|
struct nscontext *ctxt;
|
||||||
return E_NOTIMPL;
|
|
||||||
|
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,
|
static HRESULT WINAPI namespacemanager_getDeclaredPrefix(IMXNamespaceManager *iface,
|
||||||
LONG index, WCHAR *prefix, int *prefix_len)
|
LONG index, WCHAR *prefix, int *prefix_len)
|
||||||
{
|
{
|
||||||
namespacemanager *This = impl_from_IMXNamespaceManager( iface );
|
namespacemanager *This = impl_from_IMXNamespaceManager( iface );
|
||||||
FIXME("(%p)->(%d %p %p): stub\n", This, index, prefix, prefix_len);
|
struct nscontext *ctxt;
|
||||||
return E_NOTIMPL;
|
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,
|
static HRESULT WINAPI namespacemanager_getPrefix(IMXNamespaceManager *iface,
|
||||||
|
@ -208,7 +321,17 @@ static ULONG WINAPI vbnamespacemanager_Release(IVBMXNamespaceManager *iface)
|
||||||
TRACE("(%p)->(%u)\n", This, ref );
|
TRACE("(%p)->(%u)\n", This, ref );
|
||||||
|
|
||||||
if ( ref == 0 )
|
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 );
|
heap_free( This );
|
||||||
|
}
|
||||||
|
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
@ -327,8 +450,7 @@ static HRESULT WINAPI vbnamespacemanager_declarePrefix(IVBMXNamespaceManager *if
|
||||||
BSTR prefix, BSTR namespaceURI)
|
BSTR prefix, BSTR namespaceURI)
|
||||||
{
|
{
|
||||||
namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
|
namespacemanager *This = impl_from_IVBMXNamespaceManager( iface );
|
||||||
FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prefix), debugstr_w(namespaceURI));
|
return IMXNamespaceManager_declarePrefix(&This->IMXNamespaceManager_iface, prefix, namespaceURI);
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
|
static HRESULT WINAPI vbnamespacemanager_getDeclaredPrefixes(IVBMXNamespaceManager *iface,
|
||||||
|
@ -388,6 +510,7 @@ static const struct IVBMXNamespaceManagerVtbl VBMXNamespaceManagerVtbl =
|
||||||
HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
|
HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
|
||||||
{
|
{
|
||||||
namespacemanager *ns;
|
namespacemanager *ns;
|
||||||
|
struct nscontext *ctxt;
|
||||||
|
|
||||||
TRACE("(%p, %p)\n", outer, obj);
|
TRACE("(%p, %p)\n", outer, obj);
|
||||||
|
|
||||||
|
@ -399,6 +522,10 @@ HRESULT MXNamespaceManager_create(IUnknown *outer, void **obj)
|
||||||
ns->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
|
ns->IVBMXNamespaceManager_iface.lpVtbl = &VBMXNamespaceManagerVtbl;
|
||||||
ns->ref = 1;
|
ns->ref = 1;
|
||||||
|
|
||||||
|
list_init(&ns->ctxts);
|
||||||
|
ctxt = alloc_ns_context();
|
||||||
|
list_add_head(&ns->ctxts, &ctxt->entry);
|
||||||
|
|
||||||
*obj = &ns->IMXNamespaceManager_iface;
|
*obj = &ns->IMXNamespaceManager_iface;
|
||||||
|
|
||||||
TRACE("returning iface %p\n", *obj);
|
TRACE("returning iface %p\n", *obj);
|
||||||
|
|
|
@ -10148,7 +10148,7 @@ todo_wine {
|
||||||
/* prefix already added */
|
/* prefix already added */
|
||||||
hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
|
hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
|
||||||
EXPECT_HR(hr, S_FALSE);
|
EXPECT_HR(hr, S_FALSE);
|
||||||
|
}
|
||||||
hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), NULL);
|
hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), NULL);
|
||||||
EXPECT_HR(hr, E_INVALIDARG);
|
EXPECT_HR(hr, E_INVALIDARG);
|
||||||
|
|
||||||
|
@ -10158,10 +10158,10 @@ todo_wine {
|
||||||
|
|
||||||
hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xmlns"), _bstr_("uri1"));
|
hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xmlns"), _bstr_("uri1"));
|
||||||
EXPECT_HR(hr, E_INVALIDARG);
|
EXPECT_HR(hr, E_INVALIDARG);
|
||||||
|
todo_wine {
|
||||||
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, -1, NULL, NULL);
|
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, -1, NULL, NULL);
|
||||||
EXPECT_HR(hr, E_FAIL);
|
EXPECT_HR(hr, E_FAIL);
|
||||||
|
}
|
||||||
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, NULL);
|
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, NULL);
|
||||||
EXPECT_HR(hr, E_POINTER);
|
EXPECT_HR(hr, E_POINTER);
|
||||||
|
|
||||||
|
@ -10169,23 +10169,98 @@ todo_wine {
|
||||||
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, &len);
|
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, &len);
|
||||||
EXPECT_HR(hr, S_OK);
|
EXPECT_HR(hr, S_OK);
|
||||||
ok(len == 3, "got %d\n", len);
|
ok(len == 3, "got %d\n", len);
|
||||||
}
|
|
||||||
|
|
||||||
len = -1;
|
len = -1;
|
||||||
buffW[0] = 0x1;
|
buffW[0] = 0x1;
|
||||||
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
|
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(len == -1, "got %d\n", len);
|
||||||
ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
|
ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
|
||||||
|
|
||||||
len = 10;
|
len = 10;
|
||||||
buffW[0] = 0x1;
|
buffW[0] = 0x1;
|
||||||
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
|
hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
|
||||||
todo_wine {
|
|
||||||
EXPECT_HR(hr, S_OK);
|
EXPECT_HR(hr, S_OK);
|
||||||
ok(len == 3, "got %d\n", len);
|
ok(len == 3, "got %d\n", len);
|
||||||
ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
|
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);
|
IMXNamespaceManager_Release(nsmgr);
|
||||||
|
|
||||||
free_bstrs();
|
free_bstrs();
|
||||||
|
@ -10266,6 +10341,7 @@ START_TEST(domdoc)
|
||||||
test_xsltemplate();
|
test_xsltemplate();
|
||||||
|
|
||||||
test_nsnamespacemanager();
|
test_nsnamespacemanager();
|
||||||
|
test_nsnamespacemanager_override();
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue