diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 4b2706b5879..dbe993b70fc 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -3663,6 +3663,18 @@ static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap,
return S_OK;
}
+static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_XML_STRING *ret )
+{
+ const unsigned char *p = str;
+
+ if (!(ret->bytes = ws_alloc( heap, len ))) return WS_E_QUOTA_EXCEEDED;
+ memcpy( ret->bytes, p, len );
+ ret->length = len;
+ ret->dictionary = NULL;
+ ret->id = 0;
+ return S_OK;
+}
+
static const int month_offsets[2][12] =
{
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
@@ -4882,6 +4894,58 @@ static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
return S_OK;
}
+static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapping,
+ const WS_XML_STRING *localname, const WS_XML_STRING *ns,
+ const WS_XML_STRING_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
+{
+ WS_XML_UTF8_TEXT *utf8;
+ WS_XML_STRING val = {0};
+ HRESULT hr;
+ BOOL found;
+
+ if (desc) FIXME( "ignoring description\n" );
+
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_xml_string( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
+ return hr;
+
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_NILLABLE_VALUE:
+ if (size != sizeof(val)) return E_INVALIDARG;
+ *(WS_XML_STRING *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ case WS_READ_NILLABLE_POINTER:
+ {
+ WS_XML_STRING *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(WS_XML_STRING **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
static BOOL is_empty_text_node( const struct node *node )
{
const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
@@ -5468,6 +5532,11 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP
return hr;
break;
+ case WS_XML_STRING_TYPE:
+ if ((hr = read_type_xml_string( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_STRUCT_TYPE:
if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index bbb899e9005..d528ecadb75 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -1379,8 +1379,7 @@ static void test_WsReadType(void)
WS_XML_READER *reader;
WS_HEAP *heap;
enum { ONE = 1, TWO = 2 };
- WS_XML_STRING one = { 3, (BYTE *)"ONE" };
- WS_XML_STRING two = { 3, (BYTE *)"TWO" };
+ WS_XML_STRING one = { 3, (BYTE *)"ONE" }, two = { 3, (BYTE *)"TWO" }, val_xmlstr;
WS_ENUM_VALUE enum_values[] = { { ONE, &one }, { TWO, &two } };
WS_ENUM_DESCRIPTION enum_desc;
int val_enum;
@@ -1696,6 +1695,14 @@ static void test_WsReadType(void)
ok( val_str != NULL, "pointer not set\n" );
if (val_str) ok( !lstrcmpW( val_str, utf8W ), "wrong data %s\n", wine_dbgstr_w(val_str) );
+ memset( &val_xmlstr, 0, sizeof(val_xmlstr) );
+ prepare_type_test( reader, " test ", sizeof(" test ") - 1 );
+ hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL,
+ WS_READ_REQUIRED_VALUE, heap, &val_xmlstr, sizeof(val_xmlstr), NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( val_xmlstr.length == 6, "got %u\n", val_xmlstr.length );
+ ok( !memcmp( val_xmlstr.bytes, " test ", 6 ), "wrong data\n" );
+
memset( &val_string, 0, sizeof(val_string) );
prepare_type_test( reader, " test ", sizeof(" test ") - 1 );
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRING_TYPE, NULL,