From 2946dc71aaf1478d97c1427ef9da69ac4c80b4bf Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 6 Sep 2017 15:56:14 +0200 Subject: [PATCH] webservices: Include a RelatesTo header in reply messages. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/webservices/channel.c | 3 + dlls/webservices/msg.c | 161 ++++++++++++++++++++++++++------- dlls/webservices/webservices_private.h | 2 + 3 files changed, 131 insertions(+), 35 deletions(-) diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index 2b2415ab585..20d4f4c7afb 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -1155,6 +1155,7 @@ HRESULT WINAPI WsSendReplyMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct channel *channel = (struct channel *)handle; + GUID req_id; HRESULT hr; TRACE( "%p %p %p %08x %p %u %p %p %p\n", handle, msg, desc, option, body, size, request, ctx, error ); @@ -1174,6 +1175,8 @@ HRESULT WINAPI WsSendReplyMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS if ((hr = WsInitializeMessage( msg, WS_REPLY_MESSAGE, NULL, NULL )) != S_OK) goto done; if ((hr = WsAddressMessage( msg, &channel->addr, NULL )) != S_OK) goto done; if ((hr = message_set_action( msg, desc->action )) != S_OK) goto done; + if ((hr = message_get_id( request, &req_id )) != S_OK) goto done; + if ((hr = message_set_request_id( msg, &req_id )) != S_OK) goto done; if ((hr = init_writer( channel )) != S_OK) goto done; if ((hr = write_message( msg, channel->writer, desc->bodyElementDescription, option, body, size )) != S_OK) diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c index add55261385..fdbd6720015 100644 --- a/dlls/webservices/msg.c +++ b/dlls/webservices/msg.c @@ -531,57 +531,110 @@ static HRESULT write_must_understand( WS_XML_WRITER *writer, const WS_XML_STRING return WsWriteEndAttribute( writer, NULL ); } +static HRESULT write_action_header( 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, const WS_XML_STRING *text ) +{ + WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}}; + const WS_XML_STRING *action = get_header_name( WS_ACTION_HEADER ); + HRESULT hr; + + if (!text || !text->length) return S_OK; + utf8.value.length = text->length; + utf8.value.bytes = text->bytes; + + if ((hr = WsWriteStartElement( writer, prefix_addr, action, ns_addr, NULL )) != S_OK) return hr; + if ((hr = write_must_understand( writer, prefix_env, ns_env )) != S_OK) return hr; + if ((hr = WsWriteText( writer, &utf8.text, NULL )) != S_OK) return hr; + return WsWriteEndElement( writer, NULL ); /* */ +} + +static HRESULT write_to_header( 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, const WS_STRING *addr ) +{ + WS_XML_UTF16_TEXT utf16 = {{WS_XML_TEXT_TYPE_UTF16}, (BYTE *)addr->chars, addr->length * sizeof(WCHAR)}; + const WS_XML_STRING *to = get_header_name( WS_TO_HEADER ); + HRESULT hr; + + if ((hr = WsWriteStartElement( writer, prefix_addr, to, ns_addr, NULL )) != S_OK) return hr; + if ((hr = write_must_understand( writer, prefix_env, ns_env )) != S_OK) return hr; + if ((hr = WsWriteText( writer, &utf16.text, NULL )) != S_OK) return hr; + return WsWriteEndElement( writer, NULL ); /* */ +} + +static HRESULT write_replyto_header( 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"; + WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}, {sizeof(anonymous) - 1, (BYTE *)anonymous}}; + const WS_XML_STRING address = {7, (BYTE *)"Address"}, *replyto = get_header_name( WS_REPLY_TO_HEADER ); + HRESULT 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; + if ((hr = WsWriteText( writer, &utf8.text, NULL )) != S_OK) return hr; + if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* */ + return WsWriteEndElement( writer, NULL ); /* */ +} + +static HRESULT write_msgid_header( 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, const GUID *guid ) +{ + WS_XML_UNIQUE_ID_TEXT id = {{WS_XML_TEXT_TYPE_UNIQUE_ID}, *guid}; + const WS_XML_STRING *msgid = get_header_name( WS_MESSAGE_ID_HEADER ); + HRESULT hr; + + if ((hr = WsWriteStartElement( writer, prefix_addr, msgid, ns_addr, NULL )) != S_OK) return hr; + if ((hr = WsWriteText( writer, &id.text, NULL )) != S_OK) return hr; + return WsWriteEndElement( writer, NULL ); /* */ +} + +static HRESULT write_relatesto_header( 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, const GUID *guid ) +{ + WS_XML_UNIQUE_ID_TEXT id = {{WS_XML_TEXT_TYPE_UNIQUE_ID}, *guid}; + const WS_XML_STRING *relatesto = get_header_name( WS_RELATES_TO_HEADER ); + HRESULT hr; + + if ((hr = WsWriteStartElement( writer, prefix_addr, relatesto, ns_addr, NULL )) != S_OK) return hr; + if ((hr = WsWriteText( writer, &id.text, NULL )) != S_OK) return hr; + return WsWriteEndElement( writer, NULL ); /* */ +} + 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 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 ); - const WS_XML_STRING *to = get_header_name( WS_TO_HEADER ); - const WS_XML_STRING *action = get_header_name( WS_ACTION_HEADER ); + static const WS_XML_STRING header = {6, (BYTE *)"Header"}; HRESULT hr; ULONG i; 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 (msg->action) + if ((hr = write_action_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, msg->action )) != S_OK) + return hr; + + if (msg->init == WS_REPLY_MESSAGE) { - WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}, {msg->action->length, msg->action->bytes}}; - if ((hr = WsWriteStartElement( writer, prefix_addr, action, ns_addr, NULL )) != S_OK) return hr; - if ((hr = write_must_understand( writer, prefix_env, ns_env )) != S_OK) return hr; - if ((hr = WsWriteText( writer, &utf8.text, NULL )) != S_OK) return hr; - if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* */ + if ((hr = write_relatesto_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, &msg->id_req )) != S_OK) + return hr; } - if (msg->addr.length) + else if (msg->addr.length) { - WS_XML_UTF16_TEXT utf16 = {{WS_XML_TEXT_TYPE_UTF16}, (BYTE *)msg->addr.chars, - msg->addr.length * sizeof(WCHAR)}; - if ((hr = WsWriteStartElement( writer, prefix_addr, to, ns_addr, NULL )) != S_OK) return hr; - if ((hr = write_must_understand( writer, prefix_env, ns_env )) != S_OK) return hr; - if ((hr = WsWriteText( writer, &utf16.text, NULL )) != S_OK) return hr; - if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* */ + if ((hr = write_to_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, &msg->addr )) != S_OK) + return hr; } else { - WS_XML_UNIQUE_ID_TEXT id; - if ((hr = WsWriteStartElement( writer, prefix_addr, msgid, ns_addr, NULL )) != S_OK) return hr; - id.text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID; - id.value = msg->id; - if ((hr = WsWriteText( writer, &id.text, NULL )) != S_OK) return hr; - if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* */ - - if (msg->version_addr == WS_ADDRESSING_VERSION_0_9) - { - WS_XML_UTF8_TEXT utf8 = {{WS_XML_TEXT_TYPE_UTF8}, {sizeof(anonymous) - 1, (BYTE *)anonymous}}; - 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; - if ((hr = WsWriteText( writer, &utf8.text, NULL )) != S_OK) return hr; - if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* */ - if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* */ - } + if ((hr = write_msgid_header( writer, prefix_env, ns_env, prefix_addr, ns_addr, &msg->id )) != S_OK) + return hr; + if (msg->version_addr == WS_ADDRESSING_VERSION_0_9 && + (hr = write_replyto_header( writer, prefix_env, ns_env, prefix_addr, ns_addr )) != S_OK) return hr; } for (i = 0; i < msg->header_count; i++) @@ -1869,3 +1922,41 @@ HRESULT message_set_action( WS_MESSAGE *handle, const WS_XML_STRING *action ) LeaveCriticalSection( &msg->cs ); return hr; } + +HRESULT message_get_id( WS_MESSAGE *handle, GUID *id ) +{ + struct msg *msg = (struct msg *)handle; + HRESULT hr = S_OK; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + *id = msg->id_req; + + LeaveCriticalSection( &msg->cs ); + return hr; +} + +HRESULT message_set_request_id( WS_MESSAGE *handle, const GUID *id ) +{ + struct msg *msg = (struct msg *)handle; + HRESULT hr = S_OK; + + EnterCriticalSection( &msg->cs ); + + if (msg->magic != MSG_MAGIC) + { + LeaveCriticalSection( &msg->cs ); + return E_INVALIDARG; + } + + msg->id_req = *id; + + LeaveCriticalSection( &msg->cs ); + return hr; +} diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index da032136b19..219dd39273d 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -148,6 +148,8 @@ HRESULT prop_set( const struct prop *, ULONG, ULONG, const void *, ULONG ) DECLS HRESULT prop_get( const struct prop *, ULONG, ULONG, void *, ULONG ) DECLSPEC_HIDDEN; HRESULT message_set_action( WS_MESSAGE *, const WS_XML_STRING * ) DECLSPEC_HIDDEN; +HRESULT message_get_id( WS_MESSAGE *, GUID * ) DECLSPEC_HIDDEN; +HRESULT message_set_request_id( WS_MESSAGE *, const GUID * ) DECLSPEC_HIDDEN; void message_set_send_context( WS_MESSAGE *, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT * ) DECLSPEC_HIDDEN; void message_set_receive_context( WS_MESSAGE *, const WS_PROXY_MESSAGE_CALLBACK_CONTEXT * ) DECLSPEC_HIDDEN; void message_do_send_callback( WS_MESSAGE * ) DECLSPEC_HIDDEN; -- 2.11.4.GIT