From cd83b80acca5d635de8877242a4c3262d0f67188 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Tue, 6 Jun 2017 09:55:55 +0200 Subject: [PATCH] webservices: Write correct envelope headers for WS_ENVELOPE_VERSION_NONE. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/webservices/msg.c | 175 ++++++++++++++++------------------- dlls/webservices/tests/msg.c | 25 ++++- 2 files changed, 106 insertions(+), 94 deletions(-) diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c index 3032c831651..156060d50de 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; + {41, (BYTE *)"http://schemas.xmlsoap.org/soap/envelope/"}, + {39, (BYTE *)"http://www.w3.org/2003/05/soap-envelope"}, + {0, NULL}, + }; - 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; - - 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; + {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"}, + }; - 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; - - 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 ); /* */ } -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 ); /* */ + return WsWriteStartElement( writer, prefix_env, &body, ns_env, NULL ); /* */ } 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 868ead5a207..4d252659300 100644 --- a/dlls/webservices/tests/msg.c +++ b/dlls/webservices/tests/msg.c @@ -340,6 +340,8 @@ static void test_WsWriteEnvelopeStart(void) ""; static const char expected3[] = ""; + static const char expected4[] = + "
"; 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 ); }