On Wed, Mar 07, 2018 at 10:51:53PM +0000, Owen Rudge wrote:
Signed-off-by: Owen Rudge orudge@codeweavers.com
dlls/wsdapi/Makefile.in | 2 +- dlls/wsdapi/soap.c | 423 +++++++++++++++++++++++++++++++++++++++++- dlls/wsdapi/wsdapi_internal.h | 4 + dlls/wsdapi/xml.c | 2 +- 4 files changed, 427 insertions(+), 4 deletions(-)
There's a lot going on in the patch, can you split it?
diff --git a/dlls/wsdapi/Makefile.in b/dlls/wsdapi/Makefile.in index 2e7c448125..762a3b2f12 100644 --- a/dlls/wsdapi/Makefile.in +++ b/dlls/wsdapi/Makefile.in @@ -1,6 +1,6 @@ MODULE = wsdapi.dll IMPORTLIB = wsdapi -IMPORTS = rpcrt4 user32 ws2_32 +IMPORTS = rpcrt4 user32 webservices ws2_32
C_SRCS = \ address.c \ diff --git a/dlls/wsdapi/soap.c b/dlls/wsdapi/soap.c index 09b2215840..12b60ce23e 100644 --- a/dlls/wsdapi/soap.c +++ b/dlls/wsdapi/soap.c @@ -25,6 +25,8 @@
#include "wsdapi_internal.h" #include "wine/debug.h" +#include "wine/heap.h" +#include "webservices.h"
WINE_DEFAULT_DEBUG_CHANNEL(wsdapi);
@@ -58,12 +60,209 @@ static const WCHAR envelopeNsUri[] = { 'w','w','w','.','w','3','.','o','r','g','/', '2','0','0','3','/','0','5','/','s','o','a','p','-','e','n','v','e','l','o','p','e', 0 };
+static const WCHAR addressingPrefix[] = { 'w','s','a', 0 }; +static const WCHAR discoveryPrefix[] = { 'w','s','d', 0 }; +static const WCHAR envelopePrefix[] = { 's','o','a','p', 0 }; +static const WCHAR headerString[] = { 'H','e','a','d','e','r', 0 }; +static const WCHAR actionString[] = { 'A','c','t','i','o','n', 0 }; +static const WCHAR messageIdString[] = { 'M','e','s','s','a','g','e','I','D', 0 }; +static const WCHAR toString[] = { 'T','o', 0 }; +static const WCHAR relatesToString[] = { 'R','e','l','a','t','e','s','T','o', 0 }; +static const WCHAR appSequenceString[] = { 'A','p','p','S','e','q','u','e','n','c','e', 0 }; +static const WCHAR emptyString[] = { 0 }; static const WCHAR bodyString[] = { 'B','o','d','y', 0 }; 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 }; static const WCHAR metadataVersionString[] = { 'M','e','t','a','d','a','t','a','V','e','r','s','i','o','n', 0 };
+struct discovered_namespace +{
- struct list entry;
- LPCWSTR prefix;
- LPCWSTR uri;
+};
+static char *wide_to_utf8(LPCWSTR wideString) +{
- char *newString = NULL;
- int sizeNeeded = 0;
- if (wideString == NULL)
return NULL;
- sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, wideString, -1, NULL, 0, NULL, NULL);
- if (sizeNeeded < 0)
return NULL;
- newString = heap_alloc(sizeNeeded);
- WideCharToMultiByte(CP_UTF8, 0, wideString, -1, newString, sizeNeeded, NULL, NULL);
- return newString;
+}
+static WS_XML_STRING *populate_xml_string(LPCWSTR str) +{
- WS_XML_STRING *xml = heap_alloc_zero(sizeof(WS_XML_STRING));
- if (xml == NULL)
return NULL;
- xml->bytes = (BYTE *)wide_to_utf8(str);
- if (xml->bytes == NULL)
- {
heap_free(xml);
return NULL;
- }
- xml->dictionary = NULL;
- xml->id = 0;
- xml->length = (xml->bytes == NULL) ? 0 : lstrlenA((LPCSTR)xml->bytes);
- return xml;
+}
+static inline void free_xml_string(WS_XML_STRING *value) +{
- if (value == NULL)
return;
- if (value->bytes != NULL)
heap_free(value->bytes);
- heap_free(value);
+}
+static BOOL write_xml_attribute(WSDXML_ATTRIBUTE *attribute, WS_XML_WRITER *writer) +{
- WS_XML_STRING *localName = NULL, *elementNs = NULL, *nsPrefix = NULL;
- WS_XML_UTF16_TEXT utf16Text;
- BOOL retVal = FALSE;
- HRESULT ret;
- if (attribute == NULL)
return TRUE;
- /* Start the attribute */
- localName = populate_xml_string(attribute->Name->LocalName);
- if (localName == NULL) goto cleanup;
- if (attribute->Name->Space == NULL)
- {
elementNs = populate_xml_string(emptyString);
if (elementNs == NULL) goto cleanup;
nsPrefix = NULL;
- }
- else
- {
elementNs = populate_xml_string(attribute->Name->Space->Uri);
if (elementNs == NULL) goto cleanup;
nsPrefix = populate_xml_string(attribute->Name->Space->PreferredPrefix);
if (nsPrefix == NULL) goto cleanup;
- }
- ret = WsWriteStartAttribute(writer, nsPrefix, localName, elementNs, FALSE, NULL);
- if (FAILED(ret)) goto cleanup;
- utf16Text.text.textType = WS_XML_TEXT_TYPE_UTF16;
- utf16Text.bytes = (BYTE *)attribute->Value;
- utf16Text.byteCount = lstrlenW(attribute->Value) * sizeof(WCHAR);
- ret = WsWriteText(writer, (WS_XML_TEXT *)&utf16Text, NULL);
- if (FAILED(ret)) goto cleanup;
- ret = WsWriteEndAttribute(writer, NULL);
- if (FAILED(ret)) goto cleanup;
- retVal = TRUE;
+cleanup:
- free_xml_string(localName);
- free_xml_string(elementNs);
- free_xml_string(nsPrefix);
- return retVal;
+}
+static BOOL write_xml_element(WSDXML_ELEMENT *element, WS_XML_WRITER *writer) +{
- WS_XML_STRING *localName = NULL, *elementNs = NULL, *nsPrefix = NULL;
- WSDXML_ATTRIBUTE *currentAttribute;
- WS_XML_UTF16_TEXT utf16Text;
- WSDXML_NODE *currentChild;
- WSDXML_TEXT *nodeAsText;
- BOOL retVal = FALSE;
- HRESULT ret;
- int textLen;
- if (element == NULL)
return TRUE;
- /* Start the element */
- localName = populate_xml_string(element->Name->LocalName);
- if (localName == NULL) goto cleanup;
- elementNs = populate_xml_string(element->Name->Space->Uri);
- if (elementNs == NULL) goto cleanup;
- nsPrefix = populate_xml_string(element->Name->Space->PreferredPrefix);
- if (nsPrefix == NULL) goto cleanup;
- ret = WsWriteStartElement(writer, nsPrefix, localName, elementNs, NULL);
- if (FAILED(ret)) goto cleanup;
- /* Write attributes */
- currentAttribute = element->FirstAttribute;
- while (currentAttribute != NULL)
- {
if (!write_xml_attribute(currentAttribute, writer)) goto cleanup;
currentAttribute = currentAttribute->Next;
- }
- /* Write child elements */
- currentChild = element->FirstChild;
- while (currentChild != NULL)
- {
if (currentChild->Type == ElementType)
{
if (!write_xml_element((WSDXML_ELEMENT *)currentChild, writer)) goto cleanup;
}
else if (currentChild->Type == TextType)
{
nodeAsText = (WSDXML_TEXT *)currentChild;
textLen = lstrlenW(nodeAsText->Text);
utf16Text.text.textType = WS_XML_TEXT_TYPE_UTF16;
utf16Text.bytes = (BYTE *)nodeAsText->Text;
utf16Text.byteCount = min(WSD_MAX_TEXT_LENGTH, textLen) * sizeof(WCHAR);
ret = WsWriteText(writer, (WS_XML_TEXT *)&utf16Text, NULL);
if (FAILED(ret)) goto cleanup;
}
currentChild = currentChild->Next;
- }
- /* End the element */
- ret = WsWriteEndElement(writer, NULL);
- if (FAILED(ret)) goto cleanup;
- retVal = TRUE;
+cleanup:
- free_xml_string(localName);
- free_xml_string(elementNs);
- free_xml_string(nsPrefix);
- return retVal;
+}
static WSDXML_ELEMENT *add_child_element(IWSDXMLContext *xmlContext, WSDXML_ELEMENT *parent, LPCWSTR nsUri, LPCWSTR name, LPCWSTR text) { WSDXML_ELEMENT *elementObj; @@ -141,11 +340,231 @@ static LPWSTR ulonglong_to_string(void *parent, ULONGLONG value) return ret; }
+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 *create_soap_header_xml_elements(IWSDXMLContext *xmlContext, WSD_SOAP_HEADER *header, struct list *discoveredNamespaces) +{
- WSDXML_ELEMENT *headerElement, *appSequenceElement;
- WSDXML_NAME *headerName = NULL;
- /* <s:Header> */
- if (FAILED(IWSDXMLContext_AddNameToNamespace(xmlContext, envelopeNsUri, headerString, &headerName))) goto cleanup;
If the above condition succeeds, then it'll jump to cleanup with headerElement uninitialized.
- if (FAILED(WSDXMLBuildAnyForSingleElement(headerName, NULL, &headerElement))) goto cleanup;
- WSDFreeLinkedMemory(headerName);
- /* <a:Action> */
- if (add_child_element(xmlContext, headerElement, addressingNsUri, actionString, header->Action) == NULL) goto cleanup;
- /* <a:MessageId> */
- if (add_child_element(xmlContext, headerElement, addressingNsUri, messageIdString, header->MessageID) == NULL) goto cleanup;
- /* <a:To> */
- if (add_child_element(xmlContext, headerElement, addressingNsUri, toString, header->To) == NULL) goto cleanup;
- /* <a:RelatesTo> */
- if (header->RelatesTo.MessageID != NULL)
if (add_child_element(xmlContext, headerElement, addressingNsUri, relatesToString, header->RelatesTo.MessageID) == NULL) goto cleanup;
- /* <d:AppSequence> */
- appSequenceElement = add_child_element(xmlContext, headerElement, discoveryNsUri, appSequenceString, emptyString);
- if (appSequenceElement == NULL) goto cleanup;
- /* TODO: InstanceId attribute */
- /* TODO: MessageNumber attribute */
- /* TODO: SequenceID attribute */
- /* </d:AppSequence> */
- /* TODO: Write any headers */
- /* </s:Header> */
- return headerElement;
+cleanup:
- if (headerName != NULL) WSDFreeLinkedMemory(headerName);
- WSDXMLCleanupElement(headerElement);
- return NULL;
+}
+static BOOL create_soap_envelope(IWSDXMLContext *xmlContext, WSD_SOAP_HEADER *header, WSDXML_ELEMENT *bodyElement, WS_HEAP **heap, char **outputXml, ULONG *xmlLength, struct list *discoveredNamespaces) +{
- WS_XML_STRING *actualEnvelopePrefix = NULL, *envelopeUriXmlStr = NULL, *tmpPrefix = NULL, *tmpUri = NULL;
- WSDXML_NAMESPACE *addressingNs = NULL, *discoveryNs = NULL, *envelopeNs = NULL;
- WSDXML_ELEMENT *headerElement = NULL;
- struct discovered_namespace *ns;
- WS_XML_BUFFER *buffer = NULL;
- WS_XML_WRITER *writer = NULL;
- WS_XML_STRING envelope;
- BOOL retVal = FALSE;
- HRESULT ret;
- /* Create the necessary XML prefixes */
- if (FAILED(IWSDXMLContext_AddNamespace(xmlContext, addressingNsUri, addressingPrefix, &addressingNs))) goto cleanup;
- if (!add_discovered_namespace(discoveredNamespaces, addressingNs)) goto cleanup;
- if (FAILED(IWSDXMLContext_AddNamespace(xmlContext, discoveryNsUri, discoveryPrefix, &discoveryNs))) goto cleanup;
- if (!add_discovered_namespace(discoveredNamespaces, discoveryNs)) goto cleanup;
- if (FAILED(IWSDXMLContext_AddNamespace(xmlContext, envelopeNsUri, envelopePrefix, &envelopeNs))) goto cleanup;
- if (!add_discovered_namespace(discoveredNamespaces, envelopeNs)) goto cleanup;
- envelope.bytes = (BYTE*)"Envelope";
- envelope.length = strlen((const char *) envelope.bytes);
- envelope.dictionary = NULL;
- envelope.id = 0;
- actualEnvelopePrefix = populate_xml_string(envelopeNs->PreferredPrefix);
- envelopeUriXmlStr = populate_xml_string(envelopeNs->Uri);
- if ((actualEnvelopePrefix == NULL) || (envelopeUriXmlStr == NULL)) goto cleanup;
- /* Now try to create the appropriate WebServices buffers, etc */
- ret = WsCreateHeap(16384, 4096, NULL, 0, heap, NULL);
- if (FAILED(ret)) goto cleanup;
- ret = WsCreateXmlBuffer(*heap, NULL, 0, &buffer, NULL);
- if (FAILED(ret)) goto cleanup;
- ret = WsCreateWriter(NULL, 0, &writer, NULL);
- if (FAILED(ret)) goto cleanup;
- ret = WsSetOutputToBuffer(writer, buffer, NULL, 0, NULL);
- if (FAILED(ret)) goto cleanup;
- /* Create the header XML elements */
- headerElement = create_soap_header_xml_elements(xmlContext, header, discoveredNamespaces);
- if (headerElement == NULL) goto cleanup;
- /* <s:Envelope> */
- ret = WsWriteStartElement(writer, actualEnvelopePrefix, &envelope, envelopeUriXmlStr, NULL);
- if (FAILED(ret)) goto cleanup;
- LIST_FOR_EACH_ENTRY(ns, discoveredNamespaces, struct discovered_namespace, entry)
- {
tmpPrefix = populate_xml_string(ns->prefix);
tmpUri = populate_xml_string(ns->uri);
if ((tmpPrefix == NULL) || (tmpUri == NULL)) goto cleanup;
ret = WsWriteXmlnsAttribute(writer, tmpPrefix, tmpUri, FALSE, NULL);
if (FAILED(ret)) goto cleanup;
free_xml_string(tmpPrefix);
free_xml_string(tmpUri);
- }
- tmpPrefix = NULL;
- tmpUri = NULL;
- /* Write the header */
- if (!write_xml_element(headerElement, writer)) goto cleanup;
- /* Write the body */
- if (!write_xml_element(bodyElement, writer)) goto cleanup;
- ret = WsWriteEndElement(writer, NULL);
- if (FAILED(ret)) goto cleanup;
- /* </s:Envelope> */
- /* Generate the bytes of the document */
- ret = WsWriteXmlBufferToBytes(writer, buffer, NULL, NULL, 0, *heap, (void**)outputXml, xmlLength, NULL);
- if (FAILED(ret)) goto cleanup;
- retVal = TRUE;
+cleanup:
- WSDFreeLinkedMemory(addressingNs);
- WSDFreeLinkedMemory(discoveryNs);
- WSDFreeLinkedMemory(envelopeNs);
- WSDXMLCleanupElement(headerElement);
- free_xml_string(actualEnvelopePrefix);
- free_xml_string(envelopeUriXmlStr);
- if (writer != NULL)
WsFreeWriter(writer);
- /* Don't free the heap unless the operation has failed */
- if ((!retVal) && (*heap != NULL))
- {
WsFreeHeap(*heap);
*heap = NULL;
- }
- return retVal;
+}
static BOOL write_and_send_message(IWSDiscoveryPublisherImpl *impl, WSD_SOAP_HEADER *header, WSDXML_ELEMENT *bodyElement, struct list *discoveredNamespaces, IWSDUdpAddress *remoteAddress, int maxInitialDelay) {
- FIXME("stub\n");
- return FALSE;
- const char *xmlHeader = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
- WS_HEAP *heap = NULL;
- ULONG xmlLength = 0;
- int xmlHeaderLen;
- char *xml = NULL;
- char *fullXml;
- BOOL ret = FALSE;
- if (!create_soap_envelope(impl->xmlContext, header, bodyElement, &heap, &xml, &xmlLength, discoveredNamespaces))
return FALSE;
- /* Prefix the XML header */
- xmlHeaderLen = strlen(xmlHeader);
- fullXml = heap_alloc_zero(xmlLength + xmlHeaderLen + 1);
- if (fullXml == NULL)
- {
WsFreeHeap(heap);
return FALSE;
- }
- memcpy(fullXml, xmlHeader, xmlHeaderLen);
- memcpy(fullXml + xmlHeaderLen, xml, xmlLength);
- if (remoteAddress == NULL)
- {
/* TODO: Send the message via UDP multicast */
FIXME("TODO: Send the message via UDP multicast\n");
- }
- else
- {
/* TODO: Send the message via UDP unicast */
FIXME("TODO: Send the message via UDP unicast\n");
- }
- heap_free(fullXml);
- WsFreeHeap(heap);
- return ret;
}
HRESULT send_hello_message(IWSDiscoveryPublisherImpl *impl, LPCWSTR pszId, ULONGLONG ullMetadataVersion, ULONGLONG ullInstanceId, diff --git a/dlls/wsdapi/wsdapi_internal.h b/dlls/wsdapi/wsdapi_internal.h index 4f8ce91d36..c9c5a72bfc 100644 --- a/dlls/wsdapi/wsdapi_internal.h +++ b/dlls/wsdapi/wsdapi_internal.h @@ -56,4 +56,8 @@ 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);
#endif diff --git a/dlls/wsdapi/xml.c b/dlls/wsdapi/xml.c index 4d6319c36b..fc02d8b2d4 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;