From e47e132d1bc0218e28e5d7764aec7d887d5450ac Mon Sep 17 00:00:00 2001 From: Owen Rudge Date: Wed, 3 May 2017 23:55:30 +0100 Subject: [PATCH] wsdapi: Implement WSDXMLAddChild, Sibling, BuildAnyForSingleElement, CleanupElement. Signed-off-by: Owen Rudge Signed-off-by: Alexandre Julliard --- dlls/wsdapi/Makefile.in | 3 +- dlls/wsdapi/wsdapi.spec | 8 +- dlls/wsdapi/xml.c | 215 ++++++++++++++++++++++++++++++++++++++++ include/wsdutil.h | 5 + include/wsdxmldom.h | 7 ++ 5 files changed, 233 insertions(+), 5 deletions(-) create mode 100644 dlls/wsdapi/xml.c diff --git a/dlls/wsdapi/Makefile.in b/dlls/wsdapi/Makefile.in index 7d63fe26d62..764682dd84f 100644 --- a/dlls/wsdapi/Makefile.in +++ b/dlls/wsdapi/Makefile.in @@ -5,4 +5,5 @@ IMPORTS = kernel32 C_SRCS = \ discovery.c \ main.c \ - memory.c + memory.c \ + xml.c diff --git a/dlls/wsdapi/wsdapi.spec b/dlls/wsdapi/wsdapi.spec index 7145f7d2cff..8ee17cb7237 100644 --- a/dlls/wsdapi/wsdapi.spec +++ b/dlls/wsdapi/wsdapi.spec @@ -36,10 +36,10 @@ @ stub WSDSetConfigurationOption @ stub WSDUriDecode @ stub WSDUriEncode -@ stub WSDXMLAddChild -@ stub WSDXMLAddSibling -@ stub WSDXMLBuildAnyForSingleElement -@ stub WSDXMLCleanupElement +@ stdcall WSDXMLAddChild(ptr ptr) +@ stdcall WSDXMLAddSibling(ptr ptr) +@ stdcall WSDXMLBuildAnyForSingleElement(ptr ptr ptr) +@ stdcall WSDXMLCleanupElement(ptr) @ stub WSDXMLCreateContext @ stub WSDXMLGetNameFromBuiltinNamespace @ stub WSDXMLGetValueFromAny diff --git a/dlls/wsdapi/xml.c b/dlls/wsdapi/xml.c new file mode 100644 index 00000000000..1cc45b87842 --- /dev/null +++ b/dlls/wsdapi/xml.c @@ -0,0 +1,215 @@ +/* + * Web Services on Devices + * + * Copyright 2017 Owen Rudge for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "wine/debug.h" +#include "wsdapi.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wsdapi); + +#define WSD_MAX_TEXT_LENGTH 8192 + +static LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value) +{ + int valueLen; + LPWSTR dup; + + valueLen = lstrlenW(value) + 1; + + dup = WSDAllocateLinkedMemory(parentMemoryBlock, valueLen * sizeof(WCHAR)); + + if (dup) memcpy(dup, value, valueLen * sizeof(WCHAR)); + return dup; +} + +static WSDXML_NAME *duplicate_name(void *parentMemoryBlock, WSDXML_NAME *name) +{ + WSDXML_NAME *dup; + + dup = WSDAllocateLinkedMemory(parentMemoryBlock, sizeof(WSDXML_NAME)); + + if (dup == NULL) + { + return NULL; + } + + dup->Space = name->Space; + dup->LocalName = duplicate_string(dup, name->LocalName); + + if (dup->LocalName == NULL) + { + WSDFreeLinkedMemory(dup); + return NULL; + } + + return dup; +} + +HRESULT WINAPI WSDXMLAddChild(WSDXML_ELEMENT *pParent, WSDXML_ELEMENT *pChild) +{ + WSDXML_NODE *currentNode; + + TRACE("(%p, %p)\n", pParent, pChild); + + if ((pParent == NULL) || (pChild == NULL) || (pChild->Node.Parent != NULL)) + { + return E_INVALIDARG; + } + + /* See if the parent already has a child */ + currentNode = pParent->FirstChild; + + if (currentNode == NULL) + { + pParent->FirstChild = (WSDXML_NODE *)pChild; + } + else + { + /* Find the last sibling node and make this child the next sibling */ + WSDXMLAddSibling((WSDXML_ELEMENT *)currentNode, pChild); + } + + pChild->Node.Parent = pParent; + + /* Link the memory allocations */ + WSDAttachLinkedMemory(pParent, pChild); + + return S_OK; +} + +HRESULT WINAPI WSDXMLAddSibling(WSDXML_ELEMENT *pFirst, WSDXML_ELEMENT *pSecond) +{ + WSDXML_NODE *currentNode; + + TRACE("(%p, %p)\n", pFirst, pSecond); + + if ((pFirst == NULL) || (pSecond == NULL)) + { + return E_INVALIDARG; + } + + /* See if the first node already has a sibling */ + currentNode = pFirst->Node.Next; + + if (currentNode == NULL) + { + pFirst->Node.Next = (WSDXML_NODE *)pSecond; + } + else + { + /* Find the last sibling node and make the second element the next sibling */ + while (1) + { + if (currentNode->Next == NULL) + { + currentNode->Next = (WSDXML_NODE *)pSecond; + break; + } + + currentNode = currentNode->Next; + } + } + + /* Reparent the second node under the first */ + pSecond->Node.Parent = pFirst->Node.Parent; + + /* Link the memory allocations */ + WSDAttachLinkedMemory(pFirst->Node.Parent, pSecond); + + return S_OK; +} + +HRESULT WINAPI WSDXMLBuildAnyForSingleElement(WSDXML_NAME *pElementName, LPCWSTR pszText, WSDXML_ELEMENT **ppAny) +{ + WSDXML_TEXT *child; + + TRACE("(%p, %s, %p)\n", pElementName, debugstr_w(pszText), ppAny); + + if ((pElementName == NULL) || ((pszText != NULL) && (lstrlenW(pszText) > WSD_MAX_TEXT_LENGTH))) + { + return E_INVALIDARG; + } + + if (ppAny == NULL) + { + return E_POINTER; + } + + *ppAny = WSDAllocateLinkedMemory(NULL, sizeof(WSDXML_ELEMENT)); + + if (*ppAny == NULL) + { + return E_OUTOFMEMORY; + } + + ZeroMemory(*ppAny, sizeof(WSDXML_ELEMENT)); + + (*ppAny)->Name = duplicate_name(*ppAny, pElementName); + + if ((*ppAny)->Name == NULL) + { + WSDFreeLinkedMemory(*ppAny); + return E_OUTOFMEMORY; + } + + if (pszText != NULL) + { + child = WSDAllocateLinkedMemory(*ppAny, sizeof(WSDXML_TEXT)); + + if (child == NULL) + { + WSDFreeLinkedMemory(*ppAny); + return E_OUTOFMEMORY; + } + + child->Node.Parent = *ppAny; + child->Node.Next = NULL; + child->Node.Type = TextType; + child->Text = duplicate_string(child, pszText); + + if (child->Text == NULL) + { + WSDFreeLinkedMemory(*ppAny); + return E_OUTOFMEMORY; + } + + (*ppAny)->FirstChild = (WSDXML_NODE *)child; + } + + return S_OK; +} + +HRESULT WINAPI WSDXMLCleanupElement(WSDXML_ELEMENT *pAny) +{ + TRACE("(%p)\n", pAny); + + if (pAny == NULL) + { + return E_INVALIDARG; + } + + WSDFreeLinkedMemory(pAny); + return S_OK; +} diff --git a/include/wsdutil.h b/include/wsdutil.h index 8a89eb1da2f..2980d4034ac 100644 --- a/include/wsdutil.h +++ b/include/wsdutil.h @@ -24,4 +24,9 @@ void WINAPI WSDAttachLinkedMemory(void *pParent, void *pChild); void WINAPI WSDDetachLinkedMemory(void *pVoid); void WINAPI WSDFreeLinkedMemory(void *pVoid); +HRESULT WINAPI WSDXMLAddChild(WSDXML_ELEMENT *pParent, WSDXML_ELEMENT *pChild); +HRESULT WINAPI WSDXMLAddSibling(WSDXML_ELEMENT *pFirst, WSDXML_ELEMENT *pSecond); +HRESULT WINAPI WSDXMLBuildAnyForSingleElement(WSDXML_NAME *pElementName, LPCWSTR pszText, WSDXML_ELEMENT **ppAny); +HRESULT WINAPI WSDXMLCleanupElement(WSDXML_ELEMENT *pAny); + #endif diff --git a/include/wsdxmldom.h b/include/wsdxmldom.h index e9fb3bd06c7..89012361d28 100644 --- a/include/wsdxmldom.h +++ b/include/wsdxmldom.h @@ -26,6 +26,7 @@ typedef struct _WSDXML_PREFIX_MAPPING WSDXML_PREFIX_MAPPING; typedef struct _WSDXML_ATTRIBUTE WSDXML_ATTRIBUTE; typedef struct _WSDXML_NODE WSDXML_NODE; typedef struct _WSDXML_ELEMENT WSDXML_ELEMENT; +typedef struct _WSDXML_TEXT WSDXML_TEXT; typedef const WSDXML_NAMESPACE *PCWSDXML_NAMESPACE; typedef const WSDXML_TYPE *PCWSDXML_TYPE; @@ -87,4 +88,10 @@ struct _WSDXML_ELEMENT WSDXML_PREFIX_MAPPING *PrefixMappings; }; +struct _WSDXML_TEXT +{ + WSDXML_NODE Node; + WCHAR *Text; +}; + #endif /* __WSDXMLDOM_H__ */