[2/8] webservices: Write correct envelope headers for WS_ENVELOPE_VERSION_NONE.

Hans Leidekker hans at codeweavers.com
Tue Jun 6 02:55:55 CDT 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/msg.c       | 175 ++++++++++++++++++++-----------------------
 dlls/webservices/tests/msg.c |  23 ++++++
 2 files changed, 105 insertions(+), 93 deletions(-)

diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c
index 3032c83165..156060d50d 100644
--- a/dlls/webservices/msg.c
+++ b/dlls/webservices/msg.c
@@ -31,11 +31,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(webservices);
 
-static const char ns_env_1_1[] = "http://schemas.xmlsoap.org/soap/envelope/";
-static const char ns_env_1_2[] = "http://www.w3.org/2003/05/soap-envelope";
-static const char ns_addr_0_9[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing";
-static const char ns_addr_1_0[] = "http://www.w3.org/2005/08/addressing";
-
 static const struct prop_desc msg_props[] =
 {
     { sizeof(WS_MESSAGE_STATE), TRUE },         /* WS_MESSAGE_PROPERTY_STATE */
@@ -78,6 +73,7 @@ struct msg
     WS_XML_BUFFER                      *buf;
     WS_XML_WRITER                      *writer;
     WS_XML_WRITER                      *writer_body;
+    WS_XML_READER                      *reader;
     WS_XML_READER                      *reader_body;
     ULONG                               header_count;
     ULONG                               header_size;
@@ -160,6 +156,7 @@ static void free_msg( struct msg *msg )
     reset_msg( msg );
 
     WsFreeWriter( msg->writer );
+    WsFreeReader( msg->reader );
     WsFreeHeap( msg->heap );
     heap_free( msg->header );
 
@@ -219,7 +216,11 @@ HRESULT WINAPI WsCreateMessage( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_V
     TRACE( "%u %u %p %u %p %p\n", env_version, addr_version, properties, count, handle, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
-    if (!handle || !env_version || !addr_version) return E_INVALIDARG;
+    if (!handle || !env_version || !addr_version ||
+        (env_version == WS_ENVELOPE_VERSION_NONE && addr_version != WS_ADDRESSING_VERSION_TRANSPORT))
+    {
+        return E_INVALIDARG;
+    }
     return create_msg( env_version, addr_version, properties, count, handle );
 }
 
@@ -460,57 +461,40 @@ HRESULT WINAPI WsAddressMessage( WS_MESSAGE *handle, const WS_ENDPOINT_ADDRESS *
     return hr;
 }
 
-static HRESULT get_env_namespace( WS_ENVELOPE_VERSION ver, WS_XML_STRING *str )
+static const WS_XML_STRING *get_env_namespace( WS_ENVELOPE_VERSION version )
 {
-    switch (ver)
+    static const WS_XML_STRING namespaces[] =
     {
-    case WS_ENVELOPE_VERSION_SOAP_1_1:
-        str->bytes  = (BYTE *)ns_env_1_1;
-        str->length = sizeof(ns_env_1_1)/sizeof(ns_env_1_1[0]) - 1;
-        break;
-
-    case WS_ENVELOPE_VERSION_SOAP_1_2:
-        str->bytes  = (BYTE *)ns_env_1_2;
-        str->length = sizeof(ns_env_1_2)/sizeof(ns_env_1_2[0]) - 1;
-        break;
+        {41, (BYTE *)"http://schemas.xmlsoap.org/soap/envelope/"},
+        {39, (BYTE *)"http://www.w3.org/2003/05/soap-envelope"},
+        {0, NULL},
+    };
 
-    default:
-        ERR( "unhandled envelope version %u\n", ver );
-        return E_NOTIMPL;
+    if (version < WS_ENVELOPE_VERSION_SOAP_1_1 || version > WS_ENVELOPE_VERSION_NONE)
+    {
+        ERR( "unknown version %u\n", version );
+        return NULL;
     }
 
-    str->dictionary = NULL;
-    str->id         = 0;
-    return S_OK;
+    return &namespaces[version - 1];
 }
 
-static HRESULT get_addr_namespace( WS_ADDRESSING_VERSION ver, WS_XML_STRING *str )
+static const WS_XML_STRING *get_addr_namespace( WS_ADDRESSING_VERSION version )
 {
-    switch (ver)
+    static const WS_XML_STRING namespaces[] =
     {
-    case WS_ADDRESSING_VERSION_0_9:
-        str->bytes  = (BYTE *)ns_addr_0_9;
-        str->length = sizeof(ns_addr_0_9)/sizeof(ns_addr_0_9[0]) - 1;
-        break;
-
-    case WS_ADDRESSING_VERSION_1_0:
-        str->bytes  = (BYTE *)ns_addr_1_0;
-        str->length = sizeof(ns_addr_1_0)/sizeof(ns_addr_1_0[0]) - 1;
-        break;
-
-    case WS_ADDRESSING_VERSION_TRANSPORT:
-        str->bytes  = NULL;
-        str->length = 0;
-        break;
+        {48, (BYTE *)"http://schemas.xmlsoap.org/ws/2004/08/addressing"},
+        {36, (BYTE *)"http://www.w3.org/2005/08/addressing"},
+        {55, (BYTE *)"http://schemas.microsoft.com/ws/2005/05/addressing/none"},
+    };
 
-    default:
-        ERR( "unhandled addressing version %u\n", ver );
-        return E_NOTIMPL;
+    if (version < WS_ADDRESSING_VERSION_0_9 || version > WS_ADDRESSING_VERSION_TRANSPORT)
+    {
+        ERR( "unknown version %u\n", version );
+        return NULL;
     }
 
-    str->dictionary = NULL;
-    str->id         = 0;
-    return S_OK;
+    return &namespaces[version - 1];
 }
 
 static const WS_XML_STRING *get_header_name( WS_HEADER_TYPE type )
@@ -535,21 +519,22 @@ static const WS_XML_STRING *get_header_name( WS_HEADER_TYPE type )
     return &headers[type - 1];
 }
 
-static HRESULT write_headers( struct msg *msg, const WS_XML_STRING *ns_env, const WS_XML_STRING *ns_addr,
-                              WS_XML_WRITER *writer )
+static HRESULT write_headers( struct msg *msg, WS_XML_WRITER *writer, const WS_XML_STRING *prefix_env,
+                              const WS_XML_STRING *ns_env, const WS_XML_STRING *prefix_addr,
+                              const WS_XML_STRING *ns_addr )
 {
     static const char anonymous[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
-    static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
-    static const WS_XML_STRING msgid = {9, (BYTE *)"MessageID"}, replyto = {7, (BYTE *)"ReplyTo"};
-    static const WS_XML_STRING address = {7, (BYTE *)"Address"}, header = {6, (BYTE *)"Header"};
+    static const WS_XML_STRING header = {6, (BYTE *)"Header"}, address = {7, (BYTE *)"Address"};
+    const WS_XML_STRING *msgid = get_header_name( WS_MESSAGE_ID_HEADER );
+    const WS_XML_STRING *replyto = get_header_name( WS_REPLY_TO_HEADER );
     WS_XML_UTF8_TEXT urn, addr;
     HRESULT hr;
     ULONG i;
 
-    if ((hr = WsWriteXmlnsAttribute( writer, &prefix_a, ns_addr, FALSE, NULL )) != S_OK) return hr;
-    if ((hr = WsWriteStartElement( writer, &prefix_s, &header, ns_env, NULL )) != S_OK) return hr;
+    if ((hr = WsWriteXmlnsAttribute( writer, prefix_addr, ns_addr, FALSE, NULL )) != S_OK) return hr;
+    if ((hr = WsWriteStartElement( writer, prefix_env, &header, ns_env, NULL )) != S_OK) return hr;
 
-    if ((hr = WsWriteStartElement( writer, &prefix_a, &msgid, ns_addr, NULL )) != S_OK) return hr;
+    if ((hr = WsWriteStartElement( writer, prefix_addr, msgid, ns_addr, NULL )) != S_OK) return hr;
     urn.text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
     memcpy( &urn.value, &msg->id, sizeof(msg->id) );
     if ((hr = WsWriteText( writer, &urn.text, NULL )) != S_OK) return hr;
@@ -557,8 +542,8 @@ static HRESULT write_headers( struct msg *msg, const WS_XML_STRING *ns_env, cons
 
     if (msg->version_addr == WS_ADDRESSING_VERSION_0_9)
     {
-        if ((hr = WsWriteStartElement( writer, &prefix_a, &replyto, ns_addr, NULL )) != S_OK) return hr;
-        if ((hr = WsWriteStartElement( writer, &prefix_a, &address, ns_addr, NULL )) != S_OK) return hr;
+        if ((hr = WsWriteStartElement( writer, prefix_addr, replyto, ns_addr, NULL )) != S_OK) return hr;
+        if ((hr = WsWriteStartElement( writer, prefix_addr, &address, ns_addr, NULL )) != S_OK) return hr;
 
         addr.text.textType = WS_XML_TEXT_TYPE_UTF8;
         addr.value.bytes   = (BYTE *)anonymous;
@@ -577,14 +562,15 @@ static HRESULT write_headers( struct msg *msg, const WS_XML_STRING *ns_env, cons
     return WsWriteEndElement( writer, NULL ); /* </s:Header> */
 }
 
-static HRESULT write_headers_transport( struct msg *msg, const WS_XML_STRING *ns_env, WS_XML_WRITER *writer )
+static HRESULT write_headers_transport( struct msg *msg, WS_XML_WRITER *writer, const WS_XML_STRING *prefix,
+                                        const WS_XML_STRING *ns )
 {
-    static const WS_XML_STRING prefix = {1, (BYTE *)"s"}, header = {6, (BYTE *)"Header"};
+    static const WS_XML_STRING header = {6, (BYTE *)"Header"};
     HRESULT hr = S_OK;
     ULONG i;
 
     if ((msg->header_count || !msg->action.length) &&
-        (hr = WsWriteStartElement( writer, &prefix, &header, ns_env, NULL )) != S_OK) return hr;
+        (hr = WsWriteStartElement( writer, prefix, &header, ns, NULL )) != S_OK) return hr;
 
     for (i = 0; i < msg->header_count; i++)
     {
@@ -599,21 +585,22 @@ static HRESULT write_headers_transport( struct msg *msg, const WS_XML_STRING *ns
 static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer )
 {
     static const WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, body = {4, (BYTE *)"Body"};
-    static const WS_XML_STRING prefix = {1, (BYTE *)"s"};
-    WS_XML_STRING ns_env, ns_addr;
+    static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
+    const WS_XML_STRING *prefix_env = (msg->version_env == WS_ENVELOPE_VERSION_NONE) ? NULL : &prefix_s;
+    const WS_XML_STRING *prefix_addr = (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT) ? NULL : &prefix_a;
+    const WS_XML_STRING *ns_env = get_env_namespace( msg->version_env );
+    const WS_XML_STRING *ns_addr = get_addr_namespace( msg->version_addr );
     HRESULT hr;
 
-    if ((hr = get_env_namespace( msg->version_env, &ns_env )) != S_OK) return hr;
-    if ((hr = get_addr_namespace( msg->version_addr, &ns_addr )) != S_OK) return hr;
-    if ((hr = WsWriteStartElement( writer, &prefix, &envelope, &ns_env, NULL )) != S_OK) return hr;
+    if ((hr = WsWriteStartElement( writer, prefix_env, &envelope, ns_env, NULL )) != S_OK) return hr;
 
     if (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT)
-        hr = write_headers_transport( msg, &ns_env, writer );
+        hr = write_headers_transport( msg, writer, prefix_env, ns_env );
     else
-        hr = write_headers( msg, &ns_env, &ns_addr, writer );
+        hr = write_headers( msg, writer, prefix_env, ns_env, prefix_addr, ns_addr );
     if (hr != S_OK) return hr;
 
-    return WsWriteStartElement( writer, &prefix, &body, &ns_env, NULL ); /* <s:Body> */
+    return WsWriteStartElement( writer, prefix_env, &body, ns_env, NULL ); /* <s:Body> */
 }
 
 static HRESULT write_envelope_end( WS_XML_WRITER *writer )
@@ -986,47 +973,51 @@ static struct header *alloc_header( WS_HEADER_TYPE type, BOOL mapped, const WS_X
     return ret;
 }
 
-static HRESULT write_standard_header( WS_XML_WRITER *writer, const WS_XML_STRING *name, WS_TYPE value_type,
+static HRESULT write_standard_header( struct msg *msg, WS_HEADER_TYPE type, WS_TYPE value_type,
                                       WS_WRITE_OPTION option, const void *value, ULONG size )
 {
+    static const WS_XML_STRING ns = {0, NULL}, understand = {14, (BYTE *)"mustUnderstand"};
     static const WS_XML_STRING prefix_s = {1, (BYTE *)"s"}, prefix_a = {1, (BYTE *)"a"};
-    static const WS_XML_STRING understand = {14, (BYTE *)"mustUnderstand"}, ns = {0, NULL};
+    const WS_XML_STRING *prefix_env = (msg->version_env == WS_ENVELOPE_VERSION_NONE) ? NULL : &prefix_s;
+    const WS_XML_STRING *prefix_addr = (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT) ? NULL : &prefix_a;
+    const WS_XML_STRING *localname = get_header_name( type );
     WS_XML_INT32_TEXT one = {{WS_XML_TEXT_TYPE_INT32}, 1};
     HRESULT hr;
 
-    if ((hr = WsWriteStartElement( writer, &prefix_a, name, &ns, NULL )) != S_OK) return hr;
-    if ((hr = WsWriteStartAttribute( writer, &prefix_s, &understand, &ns, FALSE, NULL )) != S_OK) return hr;
-    if ((hr = WsWriteText( writer, &one.text, NULL )) != S_OK) return hr;
-    if ((hr = WsWriteEndAttribute( writer, NULL )) != S_OK) return hr;
-    if ((hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, value_type, NULL, option, value, size,
+    if ((hr = WsWriteStartElement( msg->writer, prefix_addr, localname, &ns, NULL )) != S_OK) return hr;
+    if ((hr = WsWriteStartAttribute( msg->writer, prefix_env, &understand, &ns, FALSE, NULL )) != S_OK) return hr;
+    if ((hr = WsWriteText( msg->writer, &one.text, NULL )) != S_OK) return hr;
+    if ((hr = WsWriteEndAttribute( msg->writer, NULL )) != S_OK) return hr;
+    if (msg->version_addr == WS_ADDRESSING_VERSION_TRANSPORT)
+    {
+        const WS_XML_STRING *ns_addr = get_addr_namespace( WS_ADDRESSING_VERSION_TRANSPORT );
+        if ((hr = WsWriteXmlnsAttribute( msg->writer, NULL, ns_addr, FALSE, NULL )) != S_OK) return hr;
+    }
+    if ((hr = WsWriteType( msg->writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, value_type, NULL, option, value, size,
                            NULL )) != S_OK) return hr;
-    return WsWriteEndElement( writer, NULL );
+    return WsWriteEndElement( msg->writer, NULL );
 }
 
-static HRESULT build_standard_header( WS_HEAP *heap, WS_HEADER_TYPE type, WS_TYPE value_type,
+static HRESULT build_standard_header( struct msg *msg, WS_HEADER_TYPE type, WS_TYPE value_type,
                                       WS_WRITE_OPTION option, const void *value, ULONG size,
                                       struct header **ret )
 {
-    const WS_XML_STRING *name = get_header_name( type );
     struct header *header;
-    WS_XML_WRITER *writer;
     WS_XML_BUFFER *buf;
     HRESULT hr;
 
-    if (!(header = alloc_header( type, FALSE, name, NULL ))) return E_OUTOFMEMORY;
+    if (!(header = alloc_header( type, FALSE, get_header_name(type), NULL ))) return E_OUTOFMEMORY;
 
-    if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
-    if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
-    if ((hr = WsSetOutputToBuffer( writer, buf, NULL, 0, NULL )) != S_OK) goto done;
-    if ((hr = write_standard_header( writer, name, value_type, option, value, size )) != S_OK)
-        goto done;
+    if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) return hr;
+    if ((hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
+    if ((hr = WsSetOutputToBuffer( msg->writer, buf, NULL, 0, NULL )) != S_OK) goto done;
+    if ((hr = write_standard_header( msg, type, value_type, option, value, size )) != S_OK) goto done;
 
     header->u.buf = buf;
 
 done:
     if (hr != S_OK) free_header( header );
     else *ret = header;
-    WsFreeWriter( writer );
     return hr;
 }
 
@@ -1076,7 +1067,7 @@ HRESULT WINAPI WsSetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE val
         i = msg->header_count;
     }
 
-    if ((hr = build_standard_header( msg->heap, type, value_type, option, value, size, &header )) != S_OK)
+    if ((hr = build_standard_header( msg, type, value_type, option, value, size, &header )) != S_OK)
         goto done;
 
     if (!found) msg->header_count++;
@@ -1346,28 +1337,26 @@ static HRESULT write_custom_header( WS_XML_WRITER *writer, const WS_XML_STRING *
     return WsWriteEndElement( writer, NULL );
 }
 
-static HRESULT build_custom_header( WS_HEAP *heap, const WS_XML_STRING *name, const WS_XML_STRING *ns,
+static HRESULT build_custom_header( struct msg *msg, const WS_XML_STRING *name, const WS_XML_STRING *ns,
                                     WS_TYPE type, const void *desc, WS_WRITE_OPTION option, const void *value,
                                     ULONG size, struct header **ret )
 {
     struct header *header;
-    WS_XML_WRITER *writer;
     WS_XML_BUFFER *buf;
     HRESULT hr;
 
     if (!(header = alloc_header( 0, FALSE, name, ns ))) return E_OUTOFMEMORY;
 
-    if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) goto done;
-    if ((hr = WsCreateXmlBuffer( heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
-    if ((hr = WsSetOutputToBuffer( writer, buf, NULL, 0, NULL )) != S_OK) goto done;
-    if ((hr = write_custom_header( writer, name, ns, type, desc, option, value, size )) != S_OK) goto done;
+    if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) return hr;
+    if ((hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &buf, NULL )) != S_OK) goto done;
+    if ((hr = WsSetOutputToBuffer( msg->writer, buf, NULL, 0, NULL )) != S_OK) goto done;
+    if ((hr = write_custom_header( msg->writer, name, ns, type, desc, option, value, size )) != S_OK) goto done;
 
     header->u.buf = buf;
 
 done:
     if (hr != S_OK) free_header( header );
     else *ret = header;
-    WsFreeWriter( writer );
     return hr;
 }
 
@@ -1401,7 +1390,7 @@ HRESULT WINAPI WsAddCustomHeader( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTI
     }
 
     if ((hr = grow_header_array( msg, msg->header_count + 1 )) != S_OK) goto done;
-    if ((hr = build_custom_header( msg->heap, desc->elementLocalName, desc->elementNs, desc->type,
+    if ((hr = build_custom_header( msg, desc->elementLocalName, desc->elementNs, desc->type,
                                    desc->typeDescription, option, value, size, &header )) != S_OK) goto done;
     msg->header[msg->header_count++] = header;
     hr = write_envelope( msg );
diff --git a/dlls/webservices/tests/msg.c b/dlls/webservices/tests/msg.c
index 868ead5a20..4d25265930 100644
--- a/dlls/webservices/tests/msg.c
+++ b/dlls/webservices/tests/msg.c
@@ -340,6 +340,8 @@ static void test_WsWriteEnvelopeStart(void)
         "</a:ReplyTo></s:Header><s:Body/></s:Envelope>";
     static const char expected3[] =
         "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Header/><s:Body/></s:Envelope>";
+    static const char expected4[] =
+        "<Envelope><Header/><Body/></Envelope>";
     HRESULT hr;
     WS_MESSAGE *msg;
     WS_XML_WRITER *writer;
@@ -391,8 +393,29 @@ static void test_WsWriteEnvelopeStart(void)
     hr = WsWriteEnvelopeStart( msg, writer, NULL, NULL, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
     check_output_header( msg, expected3, -1, 0, 0, __LINE__ );
+    WsFreeMessage( msg );
+
+    hr = WsCreateMessage( WS_ENVELOPE_VERSION_NONE, WS_ADDRESSING_VERSION_TRANSPORT, NULL, 0, &msg,
+                          NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsInitializeMessage( msg, WS_REQUEST_MESSAGE, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
 
+    hr = WsWriteEnvelopeStart( msg, writer, NULL, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output_header( msg, expected4, -1, 0, 0, __LINE__ );
     WsFreeMessage( msg );
+
+    hr = WsCreateMessage( WS_ENVELOPE_VERSION_NONE, WS_ADDRESSING_VERSION_0_9, NULL, 0, &msg,
+                          NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+    hr = WsCreateMessage( WS_ENVELOPE_VERSION_NONE, WS_ADDRESSING_VERSION_1_0, NULL, 0, &msg,
+                          NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
     WsFreeWriter( writer );
 }
 
-- 
2.11.0




More information about the wine-patches mailing list