From: Owen Rudge Subject: [PATCH 5/7] wsdapi: Add support for duplicating XML elements passed into PublishEx function. Message-Id: <179e81b6-f878-e393-e2ee-8811ac38b688@codeweavers.com> Date: Tue, 21 Nov 2017 22:42:52 +0000 Signed-off-by: Owen Rudge --- dlls/wsdapi/soap.c | 114 ++++++++++++++++++++++++++++++++++++++++++ dlls/wsdapi/wsdapi_internal.h | 5 ++ dlls/wsdapi/xml.c | 4 +- 3 files changed, 121 insertions(+), 2 deletions(-) diff --git a/dlls/wsdapi/soap.c b/dlls/wsdapi/soap.c index 2c85316f4e..224bc60241 100644 --- a/dlls/wsdapi/soap.c +++ b/dlls/wsdapi/soap.c @@ -61,6 +61,13 @@ static const WCHAR helloString[] = { 'H','e','l','l','o', 0 }; static const WCHAR endpointReferenceString[] = { 'E','n','d','p','o','i','n','t','R','e','f','e','r','e','n','c','e', 0 }; static const WCHAR addressString[] = { 'A','d','d','r','e','s','s', 0 }; +struct discovered_namespace +{ + struct list entry; + LPCWSTR prefix; + LPCWSTR uri; +}; + static WSDXML_ELEMENT *add_child_element(IWSDXMLContext *xmlContext, WSDXML_ELEMENT *parent, LPCWSTR nsUri, LPCWSTR name, LPCWSTR text) { WSDXML_ELEMENT *elementObj; @@ -122,6 +129,107 @@ void populate_soap_header(WSD_SOAP_HEADER *header, LPCWSTR to, LPCWSTR action, L /* TODO: Implement RelatesTo, ReplyTo, From, FaultTo */ } +static BOOL add_discovered_namespace(struct list *namespaces, WSDXML_NAMESPACE *discoveredNs) +{ + struct discovered_namespace *ns; + + LIST_FOR_EACH_ENTRY(ns, namespaces, struct discovered_namespace, entry) + { + if (lstrcmpW(ns->uri, discoveredNs->Uri) == 0) + return TRUE; /* Already added */ + } + + ns = WSDAllocateLinkedMemory(namespaces, sizeof(struct discovered_namespace)); + + if (ns == NULL) + return FALSE; + + ns->prefix = duplicate_string(ns, discoveredNs->PreferredPrefix); + ns->uri = duplicate_string(ns, discoveredNs->Uri); + + if ((ns->prefix == NULL) || (ns->uri == NULL)) + return FALSE; + + list_add_tail(namespaces, &ns->entry); + return TRUE; +} + +static WSDXML_ELEMENT *duplicate_element(WSDXML_ELEMENT *parent, const WSDXML_ELEMENT *node, struct list *namespaces) +{ + WSDXML_ATTRIBUTE *curAttribute, *newAttribute, *lastAttribute = NULL; + WSDXML_ELEMENT *newElement; + WSDXML_TEXT *textNode; + WSDXML_NODE *curNode; + + /* First record the namespace in the discovered namespaces list */ + if (!add_discovered_namespace(namespaces, node->Name->Space)) + return FALSE; + + if (FAILED(WSDXMLBuildAnyForSingleElement(node->Name, NULL, &newElement))) + return NULL; + + WSDXMLAddChild(parent, newElement); + + /* Duplicate the nodes */ + curNode = node->FirstChild; + + while (curNode != NULL) + { + if (curNode->Type == ElementType) + { + if (duplicate_element(newElement, (WSDXML_ELEMENT *)curNode, namespaces) == NULL) goto cleanup; + } + else if (curNode->Type == TextType) + { + textNode = WSDAllocateLinkedMemory(newElement, sizeof(WSDXML_TEXT)); + if (textNode == NULL) goto cleanup; + + textNode->Node.Next = NULL; + textNode->Node.Parent = newElement; + textNode->Node.Type = TextType; + textNode->Text = duplicate_string(textNode, ((WSDXML_TEXT *)curNode)->Text); + if (textNode->Text == NULL) goto cleanup; + + WSDXMLAddChild(newElement, (WSDXML_ELEMENT *)textNode); + } + + curNode = curNode->Next; + } + + /* Duplicate the attributes */ + curAttribute = node->FirstAttribute; + + while (curAttribute != NULL) + { + if ((curAttribute->Name->Space != NULL) && (!add_discovered_namespace(namespaces, curAttribute->Name->Space))) + return FALSE; + + newAttribute = WSDAllocateLinkedMemory(newElement, sizeof(WSDXML_ATTRIBUTE)); + if (newAttribute == NULL) goto cleanup; + + newAttribute->Element = newElement; + newAttribute->Name = duplicate_name(newAttribute, curAttribute->Name); + newAttribute->Value = duplicate_string(newAttribute, curAttribute->Value); + newAttribute->Next = NULL; + + if ((newAttribute->Name == NULL) || (newAttribute->Value == NULL)) goto cleanup; + + if (lastAttribute == NULL) + newElement->FirstAttribute = newAttribute; + else + lastAttribute->Next = newAttribute; + + lastAttribute = newAttribute; + curAttribute = curAttribute->Next; + } + + return newElement; + +cleanup: + WSDXMLCleanupElement(newElement); + return NULL; +} + HRESULT send_hello_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR pszId, ULONGLONG ullMetadataVersion, ULONGLONG ullInstanceId, ULONGLONG ullMessageNumber, LPCWSTR pszSessionId, const WSD_NAME_LIST *pTypesList, const WSD_URI_LIST *pScopesList, const WSD_URI_LIST *pXAddrsList, const WSDXML_ELEMENT *pHeaderAny, const WSDXML_ELEMENT *pReferenceParameterAny, @@ -164,6 +272,12 @@ HRESULT send_hello_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR pszId, ULONG if (add_child_element(impl->xmlContext, endpointReferenceElement, addressingNsUri, addressString, pszId) == NULL) goto cleanup; + /* Write any endpoint reference headers */ + if (pEndpointReferenceAny != NULL) + { + if (duplicate_element(endpointReferenceElement, pEndpointReferenceAny, discoveredNamespaces) == NULL) goto cleanup; + } + ret = E_NOTIMPL; cleanup: diff --git a/dlls/wsdapi/wsdapi_internal.h b/dlls/wsdapi/wsdapi_internal.h index 3dedc43ece..9ff7119aa9 100644 --- a/dlls/wsdapi/wsdapi_internal.h +++ b/dlls/wsdapi/wsdapi_internal.h @@ -56,4 +56,9 @@ HRESULT send_hello_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR pszId, ULONG const WSD_URI_LIST *pXAddrsList, const WSDXML_ELEMENT *pHeaderAny, const WSDXML_ELEMENT *pReferenceParameterAny, const WSDXML_ELEMENT *pEndpointReferenceAny, const WSDXML_ELEMENT *pAny); +/* xml.c */ + +LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value); +WSDXML_NAME *duplicate_name(void *parentMemoryBlock, WSDXML_NAME *name); + #endif diff --git a/dlls/wsdapi/xml.c b/dlls/wsdapi/xml.c index 4d6319c36b..968b21786a 100644 --- a/dlls/wsdapi/xml.c +++ b/dlls/wsdapi/xml.c @@ -27,7 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wsdapi); -static LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value) +LPWSTR duplicate_string(void *parentMemoryBlock, LPCWSTR value) { int valueLen; LPWSTR dup; @@ -63,7 +63,7 @@ static WSDXML_NAMESPACE *duplicate_namespace(void *parentMemoryBlock, WSDXML_NAM return newNs; } -static WSDXML_NAME *duplicate_name(void *parentMemoryBlock, WSDXML_NAME *name) +WSDXML_NAME *duplicate_name(void *parentMemoryBlock, WSDXML_NAME *name) { WSDXML_NAME *dup;