wsdapi: Implement AddNamespace.
Signed-off-by: Owen Rudge <orudge@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9a134711e6
commit
bf20953260
|
@ -1,6 +1,6 @@
|
|||
MODULE = wsdapi.dll
|
||||
IMPORTLIB = wsdapi
|
||||
IMPORTS = kernel32
|
||||
IMPORTS = user32
|
||||
|
||||
C_SRCS = \
|
||||
discovery.c \
|
||||
|
|
|
@ -64,7 +64,7 @@ static void BuildAnyForSingleElement_tests(void)
|
|||
ok(hr == S_OK, "BuildAnyForSingleElement failed with %08x\n", hr);
|
||||
|
||||
ok(element->Name != &name, "element->Name has not been duplicated\n");
|
||||
todo_wine ok(element->Name->Space != name.Space, "element->Name->Space has not been duplicated\n");
|
||||
ok(element->Name->Space != name.Space, "element->Name->Space has not been duplicated\n");
|
||||
ok(element->Name->LocalName != name.LocalName, "element->LocalName has not been duplicated\n");
|
||||
ok(lstrcmpW(element->Name->LocalName, name.LocalName) == 0, "element->LocalName = %s, expected %s\n",
|
||||
wine_dbgstr_w(element->Name->LocalName), wine_dbgstr_w(name.LocalName));
|
||||
|
@ -80,7 +80,7 @@ static void BuildAnyForSingleElement_tests(void)
|
|||
ok(hr == S_OK, "BuildAnyForSingleElement failed with %08x\n", hr);
|
||||
|
||||
ok(element->Name != &name, "element->Name has not been duplicated\n");
|
||||
todo_wine ok(element->Name->Space != name.Space, "element->Name->Space has not been duplicated\n");
|
||||
ok(element->Name->Space != name.Space, "element->Name->Space has not been duplicated\n");
|
||||
ok(element->Name->LocalName != name.LocalName, "element->LocalName has not been duplicated\n");
|
||||
ok(lstrcmpW(element->Name->LocalName, name.LocalName) == 0, "element->LocalName = %s, expected %s\n",
|
||||
wine_dbgstr_w(element->Name->LocalName), wine_dbgstr_w(name.LocalName));
|
||||
|
@ -290,24 +290,24 @@ static void XMLContext_AddNamespace_tests(void)
|
|||
|
||||
/* Test calling AddNamespace with invalid arguments */
|
||||
hr = IWSDXMLContext_AddNamespace(context, NULL, NULL, NULL);
|
||||
todo_wine ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns1Uri, NULL, NULL);
|
||||
todo_wine ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
hr = IWSDXMLContext_AddNamespace(context, NULL, prefix1, NULL);
|
||||
todo_wine ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Test calling AddNamespace without the ppNamespace parameter */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns1Uri, prefix1, NULL);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Now retrieve the created namespace */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns1Uri, prefix1, &ns1);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Check the returned structure */
|
||||
todo_wine ok(ns1 != NULL, "ns1 == NULL\n");
|
||||
ok(ns1 != NULL, "ns1 == NULL\n");
|
||||
|
||||
if (ns1 != NULL)
|
||||
{
|
||||
|
@ -321,20 +321,20 @@ static void XMLContext_AddNamespace_tests(void)
|
|||
|
||||
/* Test calling AddNamespace with parameters that are too large */
|
||||
hr = IWSDXMLContext_AddNamespace(context, largeText, prefix2, &ns2);
|
||||
todo_wine ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns2Uri, largeText, &ns2);
|
||||
todo_wine ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
hr = IWSDXMLContext_AddNamespace(context, largeText, largeText, &ns2);
|
||||
todo_wine ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == E_INVALIDARG, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Test calling AddNamespace with a conflicting prefix */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns2Uri, prefix1, &ns2);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Check the returned structure */
|
||||
todo_wine ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
|
||||
if (ns2 != NULL)
|
||||
{
|
||||
|
@ -351,10 +351,10 @@ static void XMLContext_AddNamespace_tests(void)
|
|||
|
||||
/* Try explicitly creating a prefix called 'un1' */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns4Uri, unPrefix1, &ns2);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Check the returned structure */
|
||||
todo_wine ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
|
||||
if (ns2 != NULL)
|
||||
{
|
||||
|
@ -365,10 +365,10 @@ static void XMLContext_AddNamespace_tests(void)
|
|||
|
||||
/* Test with one more conflicting prefix */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns3Uri, prefix1, &ns2);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Check the returned structure */
|
||||
todo_wine ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
|
||||
if (ns2 != NULL)
|
||||
{
|
||||
|
@ -379,10 +379,10 @@ static void XMLContext_AddNamespace_tests(void)
|
|||
|
||||
/* Try renaming a prefix */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns3Uri, prefix2, &ns2);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Check the returned structure */
|
||||
todo_wine ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
|
||||
if (ns2 != NULL)
|
||||
{
|
||||
|
@ -454,7 +454,7 @@ static void XMLContext_AddNameToNamespace_tests(void)
|
|||
|
||||
/* Try creating a namespace explicitly */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns2Uri, prefix2, &ns2);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Now add a name to it */
|
||||
hr = IWSDXMLContext_AddNameToNamespace(context, ns2Uri, name2Text, &name2);
|
||||
|
@ -483,10 +483,10 @@ static void XMLContext_AddNameToNamespace_tests(void)
|
|||
|
||||
/* Now re-retrieve ns2 */
|
||||
hr = IWSDXMLContext_AddNamespace(context, ns2Uri, prefix2, &ns2);
|
||||
todo_wine ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
ok(hr == S_OK, "AddNamespace failed with %08x\n", hr);
|
||||
|
||||
/* Check the returned structure */
|
||||
todo_wine ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
ok(ns2 != NULL, "ns2 == NULL\n");
|
||||
|
||||
if (ns2 != NULL)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/list.h"
|
||||
#include "wsdapi.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(wsdapi);
|
||||
|
@ -44,6 +45,29 @@ static LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value)
|
|||
return dup;
|
||||
}
|
||||
|
||||
static WSDXML_NAMESPACE *duplicate_namespace(void *parentMemoryBlock, WSDXML_NAMESPACE *ns)
|
||||
{
|
||||
WSDXML_NAMESPACE *newNs;
|
||||
|
||||
newNs = WSDAllocateLinkedMemory(parentMemoryBlock, sizeof(WSDXML_NAMESPACE));
|
||||
|
||||
if (newNs == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
newNs->Encoding = ns->Encoding;
|
||||
|
||||
/* On Windows, both Names and NamesCount are set to null even if there are names present */
|
||||
newNs->NamesCount = 0;
|
||||
newNs->Names = NULL;
|
||||
|
||||
newNs->PreferredPrefix = duplicate_string(newNs, ns->PreferredPrefix);
|
||||
newNs->Uri = duplicate_string(newNs, ns->Uri);
|
||||
|
||||
return newNs;
|
||||
}
|
||||
|
||||
static WSDXML_NAME *duplicate_name(void *parentMemoryBlock, WSDXML_NAME *name)
|
||||
{
|
||||
WSDXML_NAME *dup;
|
||||
|
@ -55,7 +79,7 @@ static WSDXML_NAME *duplicate_name(void *parentMemoryBlock, WSDXML_NAME *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
dup->Space = name->Space;
|
||||
dup->Space = duplicate_namespace(dup, name->Space);
|
||||
dup->LocalName = duplicate_string(dup, name->LocalName);
|
||||
|
||||
if (dup->LocalName == NULL)
|
||||
|
@ -216,12 +240,101 @@ HRESULT WINAPI WSDXMLCleanupElement(WSDXML_ELEMENT *pAny)
|
|||
|
||||
/* IWSDXMLContext implementation */
|
||||
|
||||
struct xmlNamespace
|
||||
{
|
||||
struct list entry;
|
||||
WSDXML_NAMESPACE *namespace;
|
||||
};
|
||||
|
||||
typedef struct IWSDXMLContextImpl
|
||||
{
|
||||
IWSDXMLContext IWSDXMLContext_iface;
|
||||
LONG ref;
|
||||
|
||||
struct list *namespaces;
|
||||
int nextUnknownPrefix;
|
||||
} IWSDXMLContextImpl;
|
||||
|
||||
static WSDXML_NAMESPACE *find_namespace(struct list *namespaces, LPCWSTR uri)
|
||||
{
|
||||
struct xmlNamespace *ns;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(ns, namespaces, struct xmlNamespace, entry)
|
||||
{
|
||||
if (lstrcmpW(ns->namespace->Uri, uri) == 0)
|
||||
{
|
||||
return ns->namespace;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL is_prefix_unique(struct list *namespaces, LPCWSTR prefix)
|
||||
{
|
||||
struct xmlNamespace *ns;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(ns, namespaces, struct xmlNamespace, entry)
|
||||
{
|
||||
if (lstrcmpW(ns->namespace->PreferredPrefix, prefix) == 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static LPWSTR generate_namespace_prefix(IWSDXMLContextImpl *impl, void *parentMemoryBlock, LPCWSTR uri)
|
||||
{
|
||||
WCHAR formatString[] = { 'u','n','%','d', 0 };
|
||||
WCHAR suggestedPrefix[7];
|
||||
|
||||
/* Find a unique prefix */
|
||||
while (impl->nextUnknownPrefix < 1000)
|
||||
{
|
||||
wsprintfW(suggestedPrefix, formatString, impl->nextUnknownPrefix++);
|
||||
|
||||
/* For the unlikely event where somebody has explicitly created a prefix called 'unX', check it is unique */
|
||||
if (is_prefix_unique(impl->namespaces, suggestedPrefix))
|
||||
{
|
||||
return duplicate_string(parentMemoryBlock, suggestedPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static WSDXML_NAMESPACE *add_namespace(struct list *namespaces, LPCWSTR uri)
|
||||
{
|
||||
struct xmlNamespace *ns = WSDAllocateLinkedMemory(namespaces, sizeof(struct xmlNamespace));
|
||||
|
||||
if (ns == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ns->namespace = WSDAllocateLinkedMemory(ns, sizeof(WSDXML_NAMESPACE));
|
||||
|
||||
if (ns->namespace == NULL)
|
||||
{
|
||||
WSDFreeLinkedMemory(ns);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMemory(ns->namespace, sizeof(WSDXML_NAMESPACE));
|
||||
ns->namespace->Uri = duplicate_string(ns->namespace, uri);
|
||||
|
||||
if (ns->namespace->Uri == NULL)
|
||||
{
|
||||
WSDFreeLinkedMemory(ns);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add_tail(namespaces, &ns->entry);
|
||||
return ns->namespace;
|
||||
}
|
||||
|
||||
static inline IWSDXMLContextImpl *impl_from_IWSDXMLContext(IWSDXMLContext *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, IWSDXMLContextImpl, IWSDXMLContext_iface);
|
||||
|
@ -282,8 +395,68 @@ static ULONG WINAPI IWSDXMLContextImpl_Release(IWSDXMLContext *iface)
|
|||
|
||||
static HRESULT WINAPI IWSDXMLContextImpl_AddNamespace(IWSDXMLContext *iface, LPCWSTR pszUri, LPCWSTR pszSuggestedPrefix, WSDXML_NAMESPACE **ppNamespace)
|
||||
{
|
||||
FIXME("(%p, %s, %s, %p)\n", iface, debugstr_w(pszUri), debugstr_w(pszSuggestedPrefix), ppNamespace);
|
||||
return E_NOTIMPL;
|
||||
IWSDXMLContextImpl *This = impl_from_IWSDXMLContext(iface);
|
||||
WSDXML_NAMESPACE *ns;
|
||||
LPCWSTR newPrefix = NULL;
|
||||
BOOL setNewPrefix;
|
||||
|
||||
TRACE("(%p, %s, %s, %p)\n", This, debugstr_w(pszUri), debugstr_w(pszSuggestedPrefix), ppNamespace);
|
||||
|
||||
if ((pszUri == NULL) || (pszSuggestedPrefix == NULL) || (lstrlenW(pszUri) > WSD_MAX_TEXT_LENGTH) ||
|
||||
(lstrlenW(pszSuggestedPrefix) > WSD_MAX_TEXT_LENGTH))
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
ns = find_namespace(This->namespaces, pszUri);
|
||||
|
||||
if (ns == NULL)
|
||||
{
|
||||
ns = add_namespace(This->namespaces, pszUri);
|
||||
|
||||
if (ns == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
setNewPrefix = (ns->PreferredPrefix == NULL);
|
||||
|
||||
if ((ns->PreferredPrefix == NULL) || (lstrcmpW(ns->PreferredPrefix, pszSuggestedPrefix) != 0))
|
||||
{
|
||||
newPrefix = pszSuggestedPrefix;
|
||||
setNewPrefix = TRUE;
|
||||
}
|
||||
|
||||
if (setNewPrefix)
|
||||
{
|
||||
WSDFreeLinkedMemory((void *)ns->PreferredPrefix);
|
||||
|
||||
if ((newPrefix != NULL) && (is_prefix_unique(This->namespaces, newPrefix)))
|
||||
{
|
||||
ns->PreferredPrefix = duplicate_string(ns, newPrefix);
|
||||
}
|
||||
else
|
||||
{
|
||||
ns->PreferredPrefix = generate_namespace_prefix(This, ns, pszUri);
|
||||
if (ns->PreferredPrefix == NULL)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ppNamespace != NULL)
|
||||
{
|
||||
*ppNamespace = duplicate_namespace(NULL, ns);
|
||||
|
||||
if (*ppNamespace == NULL)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IWSDXMLContextImpl_AddNameToNamespace(IWSDXMLContext *iface, LPCWSTR pszUri, LPCWSTR pszName, WSDXML_NAME **ppName)
|
||||
|
@ -338,6 +511,16 @@ HRESULT WINAPI WSDXMLCreateContext(IWSDXMLContext **ppContext)
|
|||
|
||||
obj->IWSDXMLContext_iface.lpVtbl = &xmlcontext_vtbl;
|
||||
obj->ref = 1;
|
||||
obj->namespaces = WSDAllocateLinkedMemory(obj, sizeof(struct list));
|
||||
obj->nextUnknownPrefix = 0;
|
||||
|
||||
if (obj->namespaces == NULL)
|
||||
{
|
||||
WSDFreeLinkedMemory(obj);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
list_init(obj->namespaces);
|
||||
|
||||
*ppContext = &obj->IWSDXMLContext_iface;
|
||||
TRACE("Returning iface %p\n", *ppContext);
|
||||
|
|
Loading…
Reference in New Issue