Module: wine Branch: master Commit: dff16756e9e4e31f47c7ce0126591a427c24c250 URL: http://source.winehq.org/git/wine.git/?a=commit;h=dff16756e9e4e31f47c7ce0126...
Author: Hans Leidekker hans@codeweavers.com Date: Wed Aug 10 13:13:55 2016 +0200
webservices: Implement WsSetHeader.
Signed-off-by: Hans Leidekker hans@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/webservices/msg.c | 145 +++++++++++++++++++++++++++++++++++--- dlls/webservices/webservices.spec | 2 +- 2 files changed, 138 insertions(+), 9 deletions(-)
diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c index d7898a2..2c8fb3b 100644 --- a/dlls/webservices/msg.c +++ b/dlls/webservices/msg.c @@ -48,6 +48,12 @@ static const struct prop_desc msg_props[] = { sizeof(BOOL), TRUE }, /* WS_MESSAGE_PROPERTY_IS_ADDRESSED */ };
+struct header +{ + WS_HEADER_TYPE type; + WS_XML_UTF8_TEXT text; +}; + struct msg { WS_MESSAGE_INITIALIZATION init; @@ -61,10 +67,14 @@ struct msg WS_XML_BUFFER *buf; WS_XML_WRITER *writer; WS_XML_WRITER *writer_body; + ULONG header_count; + ULONG header_size; + struct header **header; ULONG prop_count; struct prop prop[sizeof(msg_props)/sizeof(msg_props[0])]; };
+#define HEADER_ARRAY_SIZE 2 static struct msg *alloc_msg(void) { static const ULONG count = sizeof(msg_props)/sizeof(msg_props[0]); @@ -72,23 +82,36 @@ static struct msg *alloc_msg(void) ULONG size = sizeof(*ret) + prop_size( msg_props, count );
if (!(ret = heap_alloc_zero( size ))) return NULL; - ret->state = WS_MESSAGE_STATE_EMPTY; + if (!(ret->header = heap_alloc( HEADER_ARRAY_SIZE * sizeof(struct header *) ))) + { + heap_free( ret ); + return NULL; + } + ret->state = WS_MESSAGE_STATE_EMPTY; + ret->header_size = HEADER_ARRAY_SIZE; prop_init( msg_props, count, ret->prop, &ret[1] ); - ret->prop_count = count; + ret->prop_count = count; return ret; }
+static void free_headers( struct header **header, ULONG count ) +{ + ULONG i; + for (i = 0; i < count; i++) heap_free( header[i] ); +} + static void free_msg( struct msg *msg ) { if (!msg) return; WsFreeWriter( msg->writer ); WsFreeHeap( msg->heap ); heap_free( msg->addr.chars ); + free_headers( msg->header, msg->header_count ); + heap_free( msg->header ); heap_free( msg ); }
#define HEAP_MAX_SIZE (1 << 16) - static HRESULT create_msg( WS_ENVELOPE_VERSION env_version, WS_ADDRESSING_VERSION addr_version, const WS_MESSAGE_PROPERTY *properties, ULONG count, WS_MESSAGE **handle ) { @@ -403,6 +426,16 @@ static HRESULT write_envelope_end( struct msg *msg, WS_XML_WRITER *writer ) return WsWriteEndElement( writer, NULL ); /* </s:Envelope> */ }
+static HRESULT write_envelope( struct msg *msg ) +{ + HRESULT hr; + if (!msg->writer && (hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) return hr; + if (!msg->buf && (hr = WsCreateXmlBuffer( msg->heap, NULL, 0, &msg->buf, NULL )) != S_OK) return hr; + if ((hr = WsSetOutputToBuffer( msg->writer, msg->buf, NULL, 0, NULL )) != S_OK) return hr; + if ((hr = write_envelope_start( msg, msg->writer )) != S_OK) return hr; + return write_envelope_end( msg, msg->writer ); +} + /************************************************************************** * WsWriteEnvelopeStart [webservices.@] */ @@ -420,14 +453,11 @@ HRESULT WINAPI WsWriteEnvelopeStart( WS_MESSAGE *handle, WS_XML_WRITER *writer, return E_NOTIMPL; }
- if (!handle) return E_INVALIDARG; + if (!handle || !writer) return E_INVALIDARG; if (msg->state != WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION;
- if ((hr = WsCreateWriter( NULL, 0, &msg->writer, NULL )) != S_OK) return hr; - if ((hr = WsSetOutputToBuffer( msg->writer, msg->buf, NULL, 0, NULL )) != S_OK) return hr; - if ((hr = write_envelope_start( msg, msg->writer )) != S_OK) return hr; + if ((hr = write_envelope( msg )) != S_OK) return hr; if ((hr = write_envelope_start( msg, writer )) != S_OK) return hr; - if ((hr = write_envelope_end( msg, msg->writer )) != S_OK) return hr;
msg->writer_body = writer; msg->state = WS_MESSAGE_STATE_WRITING; @@ -479,3 +509,102 @@ HRESULT WINAPI WsWriteBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *de if (desc->elementLocalName) hr = WsWriteEndElement( msg->writer_body, NULL ); return hr; } + +static inline void set_utf8_text( WS_XML_UTF8_TEXT *text, BYTE *bytes, ULONG len ) +{ + text->text.textType = WS_XML_TEXT_TYPE_UTF8; + text->value.bytes = bytes; + text->value.length = len; +} + +static HRESULT alloc_header( WS_HEADER_TYPE type, WS_TYPE value_type, WS_WRITE_OPTION option, + const void *value, ULONG size, struct header **ret ) +{ + struct header *header; + + switch (value_type) + { + case WS_WSZ_TYPE: + { + int len; + const WCHAR *src; + + if (option != WS_WRITE_REQUIRED_POINTER || size != sizeof(WCHAR *)) return E_INVALIDARG; + + src = *(const WCHAR **)value; + len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1; + if (!(header = heap_alloc( sizeof(*header) + len ))) return E_OUTOFMEMORY; + set_utf8_text( &header->text, (BYTE *)(header + 1), len ); + WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)header->text.value.bytes, len, NULL, NULL ); + break; + } + case WS_XML_STRING_TYPE: + { + const WS_XML_STRING *str = value; + + if (option != WS_WRITE_REQUIRED_VALUE) + { + FIXME( "unhandled write option %u\n", option ); + return E_NOTIMPL; + } + if (size != sizeof(*str)) return E_INVALIDARG; + if (!(header = heap_alloc( sizeof(*header) + str->length ))) return E_OUTOFMEMORY; + set_utf8_text( &header->text, (BYTE *)(header + 1), str->length ); + memcpy( header->text.value.bytes, str->bytes, str->length ); + break; + } + default: + FIXME( "unhandled type %u\n", value_type ); + return E_NOTIMPL; + } + + header->type = type; + *ret = header; + return S_OK; +} + +/************************************************************************** + * WsSetHeader [webservices.@] + */ +HRESULT WINAPI WsSetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE value_type, + WS_WRITE_OPTION option, const void *value, ULONG size, WS_ERROR *error ) +{ + struct msg *msg = (struct msg *)handle; + struct header *header; + BOOL found = FALSE; + HRESULT hr; + ULONG i; + + TRACE( "%p %u %u %08x %p %u %p\n", handle, type, value_type, option, value, size, error ); + if (error) FIXME( "ignoring error parameter\n" ); + + if (!handle || type < WS_ACTION_HEADER || type > WS_FAULT_TO_HEADER) return E_INVALIDARG; + if (msg->state < WS_MESSAGE_STATE_INITIALIZED) return WS_E_INVALID_OPERATION; + + for (i = 0; i < msg->header_count; i++) + { + if (msg->header[i]->type == type) + { + found = TRUE; + break; + } + } + + if (found) heap_free( msg->header[i] ); + else + { + if (msg->header_count == msg->header_size) + { + struct header **tmp; + if (!(tmp = heap_realloc( msg->header, 2 * msg->header_size * sizeof(struct header *) ))) + return E_OUTOFMEMORY; + msg->header = tmp; + msg->header_size *= 2; + } + i = msg->header_count++; + } + + if ((hr = alloc_header( type, value_type, option, value, size, &header )) != S_OK) return hr; + msg->header[i] = header; + return write_envelope( msg ); +} diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec index 29b09c6..477f236 100644 --- a/dlls/webservices/webservices.spec +++ b/dlls/webservices/webservices.spec @@ -149,7 +149,7 @@ @ stdcall WsSetErrorProperty(ptr long ptr long) @ stub WsSetFaultErrorDetail @ stub WsSetFaultErrorProperty -@ stub WsSetHeader +@ stdcall WsSetHeader(ptr long long long ptr long ptr) @ stdcall WsSetInput(ptr ptr ptr ptr long ptr) @ stdcall WsSetInputToBuffer(ptr ptr ptr long ptr) @ stub WsSetListenerProperty