Owen Rudge : wsdapi: Implement generation of XML from WSDXML structures.

Alexandre Julliard julliard at winehq.org
Tue Mar 20 17:51:35 CDT 2018


Module: wine
Branch: master
Commit: a2c733c057881b3529bc4a701d735cfb43944dbc
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a2c733c057881b3529bc4a701d735cfb43944dbc

Author: Owen Rudge <orudge at codeweavers.com>
Date:   Mon Mar 19 21:46:23 2018 +0000

wsdapi: Implement generation of XML from WSDXML structures.

Signed-off-by: Owen Rudge <orudge at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wsdapi/Makefile.in |   2 +-
 dlls/wsdapi/soap.c      | 183 ++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 177 insertions(+), 8 deletions(-)

diff --git a/dlls/wsdapi/Makefile.in b/dlls/wsdapi/Makefile.in
index e3f3348..f5eb0fd 100644
--- a/dlls/wsdapi/Makefile.in
+++ b/dlls/wsdapi/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = wsdapi.dll
 IMPORTLIB = wsdapi
-IMPORTS   = bcrypt iphlpapi rpcrt4 user32 ws2_32
+IMPORTS   = bcrypt iphlpapi rpcrt4 user32 webservices ws2_32
 
 C_SRCS = \
 	address.c \
diff --git a/dlls/wsdapi/soap.c b/dlls/wsdapi/soap.c
index c33c73b..bec4b1d 100644
--- a/dlls/wsdapi/soap.c
+++ b/dlls/wsdapi/soap.c
@@ -26,6 +26,7 @@
 #include "wsdapi_internal.h"
 #include "wine/debug.h"
 #include "wine/heap.h"
+#include "webservices.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(wsdapi);
 
@@ -44,6 +45,77 @@ static const WCHAR actionHello[] = {
     'd','i','s','c','o','v','e','r','y','/',
     'H','e','l','l','o', 0 };
 
+static const WCHAR addressingNsUri[] = {
+    'h','t','t','p',':','/','/',
+    's','c','h','e','m','a','s','.','x','m','l','s','o','a','p','.','o','r','g','/',
+    'w','s','/','2','0','0','4','/','0','8','/','a','d','d','r','e','s','s','i','n','g', 0 };
+
+static const WCHAR discoveryNsUri[] = {
+    'h','t','t','p',':','/','/',
+    's','c','h','e','m','a','s','.','x','m','l','s','o','a','p','.','o','r','g','/',
+    'w','s','/','2','0','0','5','/','0','4','/','d','i','s','c','o','v','e','r','y', 0 };
+
+static const WCHAR envelopeNsUri[] = {
+    'h','t','t','p',':','/','/',
+    '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 char *wide_to_utf8(LPCWSTR wide_string, int *length)
+{
+    char *new_string = NULL;
+
+    if (wide_string == NULL)
+        return NULL;
+
+    *length = WideCharToMultiByte(CP_UTF8, 0, wide_string, -1, NULL, 0, NULL, NULL);
+
+    if (*length < 0)
+        return NULL;
+
+    new_string = heap_alloc(*length);
+    WideCharToMultiByte(CP_UTF8, 0, wide_string, -1, new_string, *length, NULL, NULL);
+
+    return new_string;
+}
+
+static WS_XML_STRING *populate_xml_string(LPCWSTR str)
+{
+    WS_XML_STRING *xml = heap_alloc_zero(sizeof(WS_XML_STRING));
+    int utf8Length;
+
+    if (xml == NULL)
+        return NULL;
+
+    xml->bytes = (BYTE *)wide_to_utf8(str, &utf8Length);
+
+    if (xml->bytes == NULL)
+    {
+        heap_free(xml);
+        return NULL;
+    }
+
+    xml->dictionary = NULL;
+    xml->id = 0;
+    xml->length = (xml->bytes == NULL) ? 0 : (utf8Length - 1);
+
+    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 create_guid(LPWSTR buffer)
 {
     const WCHAR formatString[] = { 'u','r','n',':','u','u','i','d',':','%','s', 0 };
@@ -79,30 +151,126 @@ static void populate_soap_header(WSD_SOAP_HEADER *header, LPCWSTR to, LPCWSTR ac
     /* TODO: Implement RelatesTo, ReplyTo, From, FaultTo */
 }
 
+static WSDXML_ELEMENT *create_soap_header_xml_elements(IWSDXMLContext *xml_context, WSD_SOAP_HEADER *header)
+{
+    /* TODO: Implement header generation */
+    return NULL;
+}
+
+static HRESULT create_soap_envelope(IWSDXMLContext *xml_context, WSD_SOAP_HEADER *header, WSDXML_ELEMENT *body_element,
+    WS_HEAP **heap, char **output_xml, ULONG *xml_length, struct list *discovered_namespaces)
+{
+    WS_XML_STRING *actual_envelope_prefix = NULL, *envelope_uri_xmlstr = NULL;
+    WSDXML_NAMESPACE *addressing_ns = NULL, *discovery_ns = NULL, *envelope_ns = NULL;
+    WSDXML_ELEMENT *header_element = NULL;
+    WS_XML_BUFFER *buffer = NULL;
+    WS_XML_WRITER *writer = NULL;
+    WS_XML_STRING envelope;
+    HRESULT ret = E_OUTOFMEMORY;
+    static BYTE envelopeString[] = "Envelope";
+
+    /* Create the necessary XML prefixes */
+    if (FAILED(IWSDXMLContext_AddNamespace(xml_context, addressingNsUri, addressingPrefix, &addressing_ns))) goto cleanup;
+
+    if (FAILED(IWSDXMLContext_AddNamespace(xml_context, discoveryNsUri, discoveryPrefix, &discovery_ns))) goto cleanup;
+
+    if (FAILED(IWSDXMLContext_AddNamespace(xml_context, envelopeNsUri, envelopePrefix, &envelope_ns))) goto cleanup;
+
+    envelope.bytes = envelopeString;
+    envelope.length = sizeof(envelopeString) - 1;
+    envelope.dictionary = NULL;
+    envelope.id = 0;
+
+    actual_envelope_prefix = populate_xml_string(envelope_ns->PreferredPrefix);
+    envelope_uri_xmlstr = populate_xml_string(envelope_ns->Uri);
+
+    if ((actual_envelope_prefix == NULL) || (envelope_uri_xmlstr == 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 */
+    header_element = create_soap_header_xml_elements(xml_context, header);
+    if (header_element == NULL) goto cleanup;
+
+    /* <s:Envelope> */
+    ret = WsWriteStartElement(writer, actual_envelope_prefix, &envelope, envelope_uri_xmlstr, NULL);
+    if (FAILED(ret)) goto cleanup;
+
+    /* TODO: Write the header */
+
+    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**)output_xml, xml_length, NULL);
+    if (FAILED(ret)) goto cleanup;
+
+cleanup:
+    WSDFreeLinkedMemory(addressing_ns);
+    WSDFreeLinkedMemory(discovery_ns);
+    WSDFreeLinkedMemory(envelope_ns);
+
+    WSDXMLCleanupElement(header_element);
+
+    free_xml_string(actual_envelope_prefix);
+    free_xml_string(envelope_uri_xmlstr);
+
+    if (writer != NULL)
+        WsFreeWriter(writer);
+
+    /* Don't free the heap unless the operation has failed */
+    if ((FAILED(ret)) && (*heap != NULL))
+    {
+        WsFreeHeap(*heap);
+        *heap = NULL;
+    }
+
+    return ret;
+}
+
 static HRESULT write_and_send_message(IWSDiscoveryPublisherImpl *impl, WSD_SOAP_HEADER *header, WSDXML_ELEMENT *body_element,
     struct list *discovered_namespaces, IWSDUdpAddress *remote_address, int max_initial_delay)
 {
     static const char xml_header[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
-    ULONG xml_header_len = sizeof(xml_header) - 1;
-    HRESULT ret = E_FAIL;
+    ULONG xml_length = 0, xml_header_len = sizeof(xml_header) - 1;
+    WS_HEAP *heap = NULL;
+    char *xml = NULL;
     char *full_xml;
+    HRESULT ret;
 
-    /* TODO: Create SOAP envelope */
+    ret = create_soap_envelope(impl->xmlContext, header, NULL, &heap, &xml, &xml_length, NULL);
+    if (ret != S_OK) return ret;
 
     /* Prefix the XML header */
-    full_xml = heap_alloc(xml_header_len + 1);
+    full_xml = heap_alloc(xml_length + xml_header_len + 1);
 
     if (full_xml == NULL)
+    {
+        WsFreeHeap(heap);
         return E_OUTOFMEMORY;
+    }
 
     memcpy(full_xml, xml_header, xml_header_len);
-    full_xml[xml_header_len] = 0;
+    memcpy(full_xml + xml_header_len, xml, xml_length);
+    full_xml[xml_length + xml_header_len] = 0;
 
     if (remote_address == NULL)
     {
         /* Send the message via UDP multicast */
-        if (send_udp_multicast(impl, full_xml, sizeof(xml_header), max_initial_delay))
-            ret = S_OK;
+        ret = send_udp_multicast(impl, full_xml, xml_length + xml_header_len + 1, max_initial_delay) ? S_OK : E_FAIL;
     }
     else
     {
@@ -111,6 +279,7 @@ static HRESULT write_and_send_message(IWSDiscoveryPublisherImpl *impl, WSD_SOAP_
     }
 
     heap_free(full_xml);
+    WsFreeHeap(heap);
 
     return ret;
 }




More information about the wine-cvs mailing list