[1/8] webservices: Store standard headers in an XML buffer.
Hans Leidekker
hans at codeweavers.com
Wed Aug 31 07:35:27 CDT 2016
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/msg.c | 314 ++++++++++++++++++++++++++++++-------------------
1 file changed, 194 insertions(+), 120 deletions(-)
diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c
index f13e3cc..67b157e 100644
--- a/dlls/webservices/msg.c
+++ b/dlls/webservices/msg.c
@@ -26,6 +26,7 @@
#include "wine/debug.h"
#include "wine/list.h"
+#include "wine/unicode.h"
#include "webservices_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(webservices);
@@ -50,10 +51,15 @@ static const struct prop_desc msg_props[] =
struct header
{
- WS_HEADER_TYPE type;
- WS_XML_STRING name;
- BOOL mapped;
- WS_XML_UTF8_TEXT text;
+ WS_HEADER_TYPE type;
+ BOOL mapped;
+ WS_XML_STRING name;
+ WS_XML_STRING ns;
+ union
+ {
+ WS_XML_BUFFER *buf;
+ WS_XML_STRING *text;
+ } u;
};
struct msg
@@ -99,6 +105,8 @@ static struct msg *alloc_msg(void)
static void free_header( struct header *header )
{
heap_free( header->name.bytes );
+ heap_free( header->ns.bytes );
+ if (header->mapped) heap_free( header->u.text );
heap_free( header );
}
@@ -385,22 +393,6 @@ static const WS_XML_STRING *get_header_name( WS_HEADER_TYPE type )
}
}
-static HRESULT write_header( WS_XML_WRITER *writer, const struct header *header )
-{
- 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 *localname = get_header_name( header->type );
- WS_XML_INT32_TEXT one = {{WS_XML_TEXT_TYPE_INT32}, 1};
- HRESULT hr;
-
- if ((hr = WsWriteStartElement( writer, &prefix_a, localname, &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 = WsWriteText( writer, &header->text.text, NULL )) != S_OK) return hr;
- return WsWriteEndElement( writer, NULL );
-}
-
static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer )
{
static const char anonymous[] = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
@@ -432,7 +424,8 @@ static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer )
for (i = 0; i < msg->header_count; i++)
{
- if (!msg->header[i]->mapped && (hr = write_header( writer, msg->header[i] )) != S_OK) return hr;
+ if (msg->header[i]->mapped) continue;
+ if ((hr = WsWriteXmlBuffer( writer, msg->header[i]->u.buf, NULL )) != S_OK) return hr;
}
if (msg->version_addr == WS_ADDRESSING_VERSION_0_9)
@@ -452,7 +445,7 @@ static HRESULT write_envelope_start( struct msg *msg, WS_XML_WRITER *writer )
return WsWriteStartElement( writer, &prefix_s, &body, &ns_env, NULL ); /* <s:Body> */
}
-static HRESULT write_envelope_end( struct msg *msg, WS_XML_WRITER *writer )
+static HRESULT write_envelope_end( WS_XML_WRITER *writer )
{
HRESULT hr;
if ((hr = WsWriteEndElement( writer, NULL )) != S_OK) return hr; /* </s:Body> */
@@ -466,7 +459,7 @@ static HRESULT write_envelope( struct msg *msg )
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 );
+ return write_envelope_end( msg->writer );
}
/**************************************************************************
@@ -511,7 +504,7 @@ HRESULT WINAPI WsWriteEnvelopeEnd( WS_MESSAGE *handle, WS_ERROR *error )
if (!handle) return E_INVALIDARG;
if (msg->state != WS_MESSAGE_STATE_WRITING) return WS_E_INVALID_OPERATION;
- if ((hr = write_envelope_end( msg, msg->writer_body )) != S_OK) return hr;
+ if ((hr = write_envelope_end( msg->writer_body )) != S_OK) return hr;
msg->state = WS_MESSAGE_STATE_DONE;
return S_OK;
@@ -567,87 +560,89 @@ HRESULT WINAPI WsInitializeMessage( WS_MESSAGE *handle, WS_MESSAGE_INITIALIZATIO
return write_envelope( msg );
}
-static inline void set_utf8_text( WS_XML_UTF8_TEXT *text, BYTE *bytes, ULONG len )
+static HRESULT grow_header_array( struct msg *msg, ULONG size )
{
- text->text.textType = WS_XML_TEXT_TYPE_UTF8;
- text->value.bytes = bytes;
- text->value.length = len;
+ struct header **tmp;
+ if (size <= msg->header_size) return S_OK;
+ if (!(tmp = heap_realloc( msg->header, 2 * msg->header_size * sizeof(struct header *) )))
+ return E_OUTOFMEMORY;
+ msg->header = tmp;
+ msg->header_size *= 2;
+ return S_OK;
}
-static HRESULT alloc_header( WS_HEADER_TYPE type, const WS_XML_STRING *name, BOOL mapped, WS_TYPE value_type,
- WS_WRITE_OPTION option, const void *value, ULONG size, struct header **ret )
+static struct header *alloc_header( WS_HEADER_TYPE type, BOOL mapped, const WS_XML_STRING *name,
+ const WS_XML_STRING *ns )
{
- 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_zero( 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:
+ struct header *ret;
+ if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
+ if (name && name->length)
{
- const WS_XML_STRING *str = value;
-
- if (option != WS_WRITE_REQUIRED_VALUE)
+ if (!(ret->name.bytes = heap_alloc( name->length )))
{
- FIXME( "unhandled write option %u\n", option );
- return E_NOTIMPL;
+ free_header( ret );
+ return NULL;
}
- if (size != sizeof(*str)) return E_INVALIDARG;
- if (!(header = heap_alloc_zero( 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;
+ memcpy( ret->name.bytes, name->bytes, name->length );
+ ret->name.length = name->length;
}
- case WS_STRING_TYPE:
+ if (ns && ns->length)
{
- int len;
- const WS_STRING *str = value;
-
- if (option != WS_WRITE_REQUIRED_VALUE)
+ if (!(ret->ns.bytes = heap_alloc( ns->length )))
{
- FIXME( "unhandled write option %u\n", option );
- return E_NOTIMPL;
+ free_header( ret );
+ return NULL;
}
- if (size != sizeof(*str)) return E_INVALIDARG;
- len = WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, NULL, 0, NULL, NULL );
- if (!(header = heap_alloc_zero( sizeof(*header) + len ))) return E_OUTOFMEMORY;
- set_utf8_text( &header->text, (BYTE *)(header + 1), len );
- WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, (char *)header->text.value.bytes,
- len, NULL, NULL );
- break;
- }
- default:
- FIXME( "unhandled type %u\n", value_type );
- return E_NOTIMPL;
+ memcpy( ret->ns.bytes, ns->bytes, ns->length );
+ ret->ns.length = ns->length;
}
+ ret->type = type;
+ ret->mapped = mapped;
+ return ret;
+}
- if (name && name->length)
- {
- if (!(header->name.bytes = heap_alloc( name->length )))
- {
- heap_free( header );
- return E_OUTOFMEMORY;
- }
- memcpy( header->name.bytes, name->bytes, name->length );
- header->name.length = name->length;
- }
- header->type = type;
- header->mapped = mapped;
+static HRESULT write_standard_header( WS_XML_WRITER *writer, const WS_XML_STRING *name, WS_TYPE value_type,
+ WS_WRITE_OPTION option, const void *value, ULONG size )
+{
+ 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};
+ WS_XML_INT32_TEXT one = {{WS_XML_TEXT_TYPE_INT32}, 1};
+ HRESULT hr;
- *ret = header;
- return S_OK;
+ 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,
+ NULL )) != S_OK) return hr;
+ return WsWriteEndElement( writer, NULL );
+}
+
+static HRESULT build_standard_header( WS_HEAP *heap, 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 ((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;
+
+ header->u.buf = buf;
+
+done:
+ if (hr != S_OK) free_header( header );
+ else *ret = header;
+ WsFreeWriter( writer );
+ return hr;
}
/**************************************************************************
@@ -679,25 +674,27 @@ HRESULT WINAPI WsSetHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_TYPE val
if (!found)
{
- 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 = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr;
+ i = msg->header_count;
}
- if ((hr = alloc_header( type, NULL, FALSE, value_type, option, value, size, &header )) != S_OK)
+ if ((hr = build_standard_header( msg->heap, type, value_type, option, value, size, &header )) != S_OK)
return hr;
- if (found) free_header( msg->header[i] );
+ if (!found) msg->header_count++;
+ else free_header( msg->header[i] );
+
msg->header[i] = header;
return write_envelope( msg );
}
+static void remove_header( struct msg *msg, ULONG i )
+{
+ free_header( msg->header[i] );
+ memmove( &msg->header[i], &msg->header[i + 1], (msg->header_count - i) * sizeof(struct header *) );
+ msg->header_count--;
+}
+
/**************************************************************************
* WsRemoveHeader [webservices.@]
*/
@@ -718,9 +715,7 @@ HRESULT WINAPI WsRemoveHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_ERROR
{
if (msg->header[i]->type == type)
{
- free_header( msg->header[i] );
- memmove( &msg->header[i], &msg->header[i + 1], (msg->header_count - i) * sizeof(struct header *) );
- msg->header_count--;
+ remove_header( msg, i );
removed = TRUE;
break;
}
@@ -730,6 +725,93 @@ HRESULT WINAPI WsRemoveHeader( WS_MESSAGE *handle, WS_HEADER_TYPE type, WS_ERROR
return S_OK;
}
+static HRESULT build_mapped_header( const WS_XML_STRING *name, WS_TYPE type, WS_WRITE_OPTION option,
+ const void *value, ULONG size, struct header **ret )
+{
+ struct header *header;
+
+ if (!(header = alloc_header( 0, TRUE, name, NULL ))) return E_OUTOFMEMORY;
+ switch (type)
+ {
+ case WS_WSZ_TYPE:
+ {
+ int len;
+ const WCHAR *src;
+
+ if (option != WS_WRITE_REQUIRED_POINTER || size != sizeof(WCHAR *))
+ {
+ free_header( header );
+ return E_INVALIDARG;
+ }
+ src = *(const WCHAR **)value;
+ len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL ) - 1;
+ if (!(header->u.text = alloc_xml_string( NULL, len )))
+ {
+ free_header( header );
+ return E_OUTOFMEMORY;
+ }
+ WideCharToMultiByte( CP_UTF8, 0, src, -1, (char *)header->u.text->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 );
+ free_header( header );
+ return E_NOTIMPL;
+ }
+ if (size != sizeof(*str))
+ {
+ free_header( header );
+ return E_INVALIDARG;
+ }
+ if (!(header->u.text = alloc_xml_string( NULL, str->length )))
+ {
+ free_header( header );
+ return E_OUTOFMEMORY;
+ }
+ memcpy( header->u.text->bytes, str->bytes, str->length );
+ break;
+ }
+ case WS_STRING_TYPE:
+ {
+ int len;
+ const WS_STRING *str = value;
+
+ if (option != WS_WRITE_REQUIRED_VALUE)
+ {
+ FIXME( "unhandled write option %u\n", option );
+ free_header( header );
+ return E_NOTIMPL;
+ }
+ if (size != sizeof(*str))
+ {
+ free_header( header );
+ return E_INVALIDARG;
+ }
+ len = WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, NULL, 0, NULL, NULL );
+ if (!(header->u.text = alloc_xml_string( NULL, len )))
+ {
+ free_header( header );
+ return E_OUTOFMEMORY;
+ }
+ WideCharToMultiByte( CP_UTF8, 0, str->chars, str->length, (char *)header->u.text->bytes,
+ len, NULL, NULL );
+ break;
+ }
+ default:
+ FIXME( "unhandled type %u\n", type );
+ free_header( header );
+ return E_NOTIMPL;
+ }
+
+ *ret = header;
+ return S_OK;
+}
+
/**************************************************************************
* WsAddMappedHeader [webservices.@]
*/
@@ -760,21 +842,15 @@ HRESULT WINAPI WsAddMappedHeader( WS_MESSAGE *handle, const WS_XML_STRING *name,
if (!found)
{
- 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 = grow_header_array( msg, msg->header_count + 1 )) != S_OK) return hr;
+ i = msg->header_count;
}
- if ((hr = alloc_header( 0, name, TRUE, WS_XML_STRING_TYPE, option, value, size, &header )) != S_OK)
- return hr;
+ if ((hr = build_mapped_header( name, type, option, value, size, &header )) != S_OK) return hr;
+
+ if (!found) msg->header_count++;
+ else free_header( msg->header[i] );
- if (found) free_header( msg->header[i] );
msg->header[i] = header;
return S_OK;
}
@@ -798,9 +874,7 @@ HRESULT WINAPI WsRemoveMappedHeader( WS_MESSAGE *handle, const WS_XML_STRING *na
if (msg->header[i]->type || !msg->header[i]->mapped) continue;
if (WsXmlStringEquals( name, &msg->header[i]->name, NULL ) == S_OK)
{
- free_header( msg->header[i] );
- memmove( &msg->header[i], &msg->header[i + 1], (msg->header_count - i) * sizeof(struct header *) );
- msg->header_count--;
+ remove_header( msg, i );
break;
}
}
--
2.1.4
More information about the wine-patches
mailing list