[PATCH 5/8] [v2] wsdapi: Implement generation of XML from WSDXML structures.

Huw Davies huw at codeweavers.com
Mon Mar 19 05:54:51 CDT 2018


On Thu, Mar 15, 2018 at 09:58:40PM +0000, Owen Rudge wrote:
> +static char *wide_to_utf8(LPCWSTR wide_string)
> +{
> +    char *new_string = NULL;
> +    int size_needed = 0;
> +
> +    if (wide_string == NULL)
> +        return NULL;
> +
> +    size_needed = WideCharToMultiByte(CP_UTF8, 0, wide_string, -1, NULL, 0, NULL, NULL);
> +
> +    if (size_needed < 0)
> +        return NULL;
> +
> +    new_string = heap_alloc(size_needed);
> +    WideCharToMultiByte(CP_UTF8, 0, wide_string, -1, new_string, size_needed, 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));
> +
> +    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);

In principle you already know the length here.  So either have wide_to_utf8
return a length param, or merge these two functions.

> +
> +    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,29 +151,125 @@ 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;
> +
> +    /* 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 = (BYTE*)"Envelope";
> +    envelope.length = strlen((const char *) envelope.bytes);

This length is known by the compiler.

> +    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\"?>";
> -    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(sizeof(xml_header) + 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, sizeof(xml_header));
> -    full_xml[sizeof(xml_header)] = 0;
> +    memcpy(full_xml, xml_header, xml_header_len);
> +    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
>      {
> @@ -110,6 +278,7 @@ static HRESULT write_and_send_message(IWSDiscoveryPublisherImpl *impl, WSD_SOAP_
>      }
>  
>      heap_free(full_xml);
> +    WsFreeHeap(heap);
>  
>      return ret;
>  }
> 

> 




More information about the wine-devel mailing list