[6/6] webservices: Add support for structure types in WsReadType.

Hans Leidekker hans at codeweavers.com
Fri Jan 29 06:27:30 CST 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/reader.c       | 712 ++++++++++++++++++++++++++++++++++------
 dlls/webservices/tests/reader.c |  99 ++++++
 2 files changed, 709 insertions(+), 102 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 82a3a1a..a0c32a9 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -164,6 +164,12 @@ void *ws_alloc( WS_HEAP *handle, SIZE_T size )
     return HeapAlloc( heap->handle, 0, size );
 }
 
+static void *ws_alloc_zero( WS_HEAP *handle, SIZE_T size )
+{
+    struct heap *heap = (struct heap *)handle;
+    return HeapAlloc( heap->handle, HEAP_ZERO_MEMORY, size );
+}
+
 void *ws_realloc( WS_HEAP *handle, void *ptr, SIZE_T size )
 {
     struct heap *heap = (struct heap *)handle;
@@ -1463,177 +1469,679 @@ static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, U
     return S_OK;
 }
 
-/**************************************************************************
- *          WsReadType		[webservices.@]
- */
-HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
-                           const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
-                           ULONG value_size, WS_ERROR *error )
+static HRESULT read_get_node_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
 {
-    struct reader *reader = (struct reader *)handle;
     WS_XML_TEXT_NODE *text;
 
-    TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
-           value_size, error );
-    if (error) FIXME( "ignoring error parameter\n" );
+    if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_TEXT)
+        return WS_E_INVALID_FORMAT;
 
-    if (!reader || !value) return E_INVALIDARG;
+    text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
+    if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
+    {
+        FIXME( "text type %u not supported\n", text->text->textType );
+        return E_NOTIMPL;
+    }
+    *ret = (WS_XML_UTF8_TEXT *)text->text;
+    return S_OK;
+}
 
-    if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_TEXT)
+static HRESULT read_get_attribute_text( struct reader *reader, WS_XML_UTF8_TEXT **ret )
+{
+    WS_XML_ELEMENT_NODE *elem = &reader->current->hdr;
+    WS_XML_ATTRIBUTE *attr;
+
+    if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT ||
+        reader->current_attr >= elem->attributeCount) return WS_E_INVALID_FORMAT;
+
+    attr = elem->attributes[reader->current_attr];
+    if (attr->value->textType != WS_XML_TEXT_TYPE_UTF8)
     {
-        FIXME( "only text nodes are supported\n" );
+        FIXME( "text type %u not supported\n", attr->value->textType );
         return E_NOTIMPL;
     }
-    text = (WS_XML_TEXT_NODE *)&reader->current->hdr.node;
-    if (text->text->textType != WS_XML_TEXT_TYPE_UTF8)
+    *ret = (WS_XML_UTF8_TEXT *)attr->value;
+    reader->current_attr++;
+    return S_OK;
+}
+
+static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping,
+                               const WS_BOOL_DESCRIPTION *desc, BOOL *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    ULONG len;
+
+    if (desc)
     {
-        FIXME( "text type %u not supported\n", text->text->textType );
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        len = utf8->value.length;
+        break;
+
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
+        len = utf8->value.length;
+        break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
         return E_NOTIMPL;
     }
 
+    if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) *ret = TRUE;
+    else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) *ret = TRUE;
+    else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) *ret = FALSE;
+    else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) *ret = FALSE;
+    else return WS_E_INVALID_FORMAT;
+
+    return S_OK;
+}
+
+static HRESULT read_type_int8( struct reader *reader, WS_TYPE_MAPPING mapping,
+                               const WS_INT8_DESCRIPTION *desc, INT8 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    INT64 val;
+
+    if (desc)
+    {
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
     switch (mapping)
     {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
+
     case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
     default:
         FIXME( "mapping %u not supported\n", mapping );
         return E_NOTIMPL;
     }
 
-    switch (type)
+    if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_int16( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                const WS_INT16_DESCRIPTION *desc, INT16 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    INT64 val;
+
+    if (desc)
     {
-    case WS_BOOL_TYPE:
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        ULONG len = utf8->value.length;
-        BOOL *ret = value;
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
+
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
+        break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
+    }
+
+    if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_int32( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                const WS_INT32_DESCRIPTION *desc, INT32 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    INT64 val;
 
-        if (value_size != sizeof(BOOL)) return E_INVALIDARG;
+    if (desc)
+    {
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
 
-        if (len == 4 && !memcmp( utf8->value.bytes, "true", 4 )) *ret = TRUE;
-        else if (len == 1 && !memcmp( utf8->value.bytes, "1", 1 )) *ret = TRUE;
-        else if (len == 5 && !memcmp( utf8->value.bytes, "false", 5 )) *ret = FALSE;
-        else if (len == 1 && !memcmp( utf8->value.bytes, "0", 1 )) *ret = FALSE;
-        else return WS_E_INVALID_FORMAT;
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_INT8_TYPE:
+
+    if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_int64( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                const WS_INT64_DESCRIPTION *desc, INT64 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    INT64 val;
+
+    if (desc)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        INT8 *ret = value;
-        HRESULT hr;
-        INT64 val;
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
 
-        if (value_size != sizeof(INT8)) return E_INVALIDARG;
-        hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT8, MAX_INT8, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_INT16_TYPE:
+
+    if ((hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_uint8( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                const WS_UINT8_DESCRIPTION *desc, UINT8 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    UINT64 val;
+
+    if (desc)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        INT16 *ret = value;
-        HRESULT hr;
-        INT64 val;
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
 
-        if (value_size != sizeof(INT16)) return E_INVALIDARG;
-        hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT16, MAX_INT16, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_INT32_TYPE:
+
+    if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_uint16( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                 const WS_UINT16_DESCRIPTION *desc, UINT16 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    UINT64 val;
+
+    if (desc)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        INT32 *ret = value;
-        HRESULT hr;
-        INT64 val;
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
 
-        if (value_size != sizeof(INT32)) return E_INVALIDARG;
-        hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT32, MAX_INT32, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_INT64_TYPE:
+
+    if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_uint32( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                 const WS_UINT32_DESCRIPTION *desc, UINT32 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    UINT64 val;
+
+    if (desc)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        INT64 val, *ret = value;
-        HRESULT hr;
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
 
-        if (value_size != sizeof(INT64)) return E_INVALIDARG;
-        hr = str_to_int64( utf8->value.bytes, utf8->value.length, MIN_INT64, MAX_INT64, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_UINT8_TYPE:
+
+    if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                 const WS_UINT64_DESCRIPTION *desc, UINT64 *ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    UINT64 val;
+
+    if (desc)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        UINT8 *ret = value;
-        HRESULT hr;
-        UINT64 val;
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
 
-        if (value_size != sizeof(UINT8)) return E_INVALIDARG;
-        hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT8, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_UINT16_TYPE:
+
+    if ((hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val )) != S_OK)
+        return hr;
+
+    *ret = val;
+    return S_OK;
+}
+
+static HRESULT read_type_wsz( struct reader *reader, WS_TYPE_MAPPING mapping,
+                              const WS_WSZ_DESCRIPTION *desc, WS_HEAP *heap, WCHAR **ret )
+{
+    WS_XML_UTF8_TEXT *utf8;
+    HRESULT hr;
+    WCHAR *str;
+
+    if (desc)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        UINT16 *ret = value;
-        HRESULT hr;
-        UINT64 val;
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+    switch (mapping)
+    {
+    case WS_ATTRIBUTE_TYPE_MAPPING:
+        if ((hr = read_get_attribute_text( reader, &utf8 )) != S_OK) return hr;
+        break;
 
-        if (value_size != sizeof(UINT16)) return E_INVALIDARG;
-        hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT16, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    case WS_ELEMENT_TYPE_MAPPING:
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_get_node_text( reader, &utf8 )) != S_OK) return hr;
         break;
+
+    default:
+        FIXME( "mapping %u not supported\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_UINT32_TYPE:
+
+    if (!(str = xmltext_to_widechar( heap, &utf8->text ))) return WS_E_QUOTA_EXCEEDED;
+    *ret = str;
+    return S_OK;
+}
+
+static HRESULT read_type_struct( struct reader *, WS_TYPE_MAPPING, const WS_STRUCT_DESCRIPTION *,
+                                 WS_HEAP *, void ** );
+
+static HRESULT read_type_struct_field( struct reader *reader, const WS_FIELD_DESCRIPTION *desc,
+                                       WS_HEAP *heap, char *buf )
+{
+    char *ptr = buf + desc->offset;
+    WS_TYPE_MAPPING mapping;
+    HRESULT hr;
+
+    if (desc->options && desc->options != WS_FIELD_POINTER &&
+        desc->options != WS_FIELD_OPTIONAL &&
+        desc->options != (WS_FIELD_POINTER | WS_FIELD_OPTIONAL))
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        UINT32 *ret = value;
-        HRESULT hr;
-        UINT64 val;
+        FIXME( "options 0x%x not supported\n", desc->options );
+        return E_NOTIMPL;
+    }
 
-        if (value_size != sizeof(UINT32)) return E_INVALIDARG;
-        hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT32, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    switch (desc->mapping)
+    {
+    case WS_ATTRIBUTE_FIELD_MAPPING:
+        mapping = WS_ATTRIBUTE_TYPE_MAPPING;
+        break;
+
+    case WS_ELEMENT_FIELD_MAPPING:
+        mapping = WS_ELEMENT_TYPE_MAPPING;
         break;
+
+    default:
+        FIXME( "unhandled field mapping %u\n", desc->mapping );
+        return E_NOTIMPL;
     }
+
+    switch (desc->type)
+    {
+    case WS_STRUCT_TYPE:
+        hr = read_type_struct( reader, mapping, desc->typeDescription, heap, (void **)ptr );
+        break;
+
+    case WS_BOOL_TYPE:
+        hr = read_type_bool( reader, mapping, desc->typeDescription, (BOOL *)ptr );
+        break;
+
+    case WS_INT8_TYPE:
+        hr = read_type_int8( reader, mapping, desc->typeDescription, (INT8 *)ptr );
+        break;
+
+    case WS_INT16_TYPE:
+        hr = read_type_int16( reader, mapping, desc->typeDescription, (INT16 *)ptr );
+        break;
+
+    case WS_INT32_TYPE:
+        hr = read_type_int32( reader, mapping, desc->typeDescription, (INT32 *)ptr );
+        break;
+
+    case WS_INT64_TYPE:
+        hr = read_type_int64( reader, mapping, desc->typeDescription, (INT64 *)ptr );
+        break;
+
+    case WS_UINT8_TYPE:
+        hr = read_type_uint8( reader, mapping, desc->typeDescription, (UINT8 *)ptr );
+        break;
+
+    case WS_UINT16_TYPE:
+        hr = read_type_uint16( reader, mapping, desc->typeDescription, (UINT16 *)ptr );
+        break;
+
+    case WS_UINT32_TYPE:
+        hr = read_type_uint32( reader, mapping, desc->typeDescription, (UINT32 *)ptr );
+        break;
+
     case WS_UINT64_TYPE:
+        hr = read_type_uint64( reader, mapping, desc->typeDescription, (UINT64 *)ptr );
+        break;
+
+    case WS_WSZ_TYPE:
+        hr = read_type_wsz( reader, mapping, desc->typeDescription, heap, (WCHAR **)ptr );
+        break;
+
+    default:
+        FIXME( "type %u not implemented\n", desc->type );
+        return E_NOTIMPL;
+    }
+
+    return hr;
+}
+
+static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping,
+                                 const WS_STRUCT_DESCRIPTION *desc, WS_HEAP *heap, void **ret )
+{
+    ULONG i;
+    HRESULT hr;
+    char *buf;
+
+    if (!desc) return E_INVALIDARG;
+
+    if (desc->structOptions)
     {
-        WS_XML_UTF8_TEXT *utf8 = (WS_XML_UTF8_TEXT *)text->text;
-        UINT64 val, *ret = value;
-        HRESULT hr;
+        FIXME( "struct options 0x%x not supported\n", desc->structOptions );
+        return E_NOTIMPL;
+    }
 
-        if (value_size != sizeof(UINT64)) return E_INVALIDARG;
-        hr = str_to_uint64( utf8->value.bytes, utf8->value.length, MAX_UINT64, &val );
-        if (hr != S_OK) return hr;
-        *ret = val;
+    switch (mapping)
+    {
+    case WS_ELEMENT_TYPE_MAPPING:
+        if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
         break;
+
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_to_startelement( reader, NULL )) != S_OK) return hr;
+        if ((hr = read_startelement( reader )) != S_OK) return hr;
+        break;
+
+    default:
+        FIXME( "unhandled mapping %u\n", mapping );
+        return E_NOTIMPL;
     }
-    case WS_WSZ_TYPE:
+
+    if (!(buf = ws_alloc_zero( heap, desc->size ))) return WS_E_QUOTA_EXCEEDED;
+
+    for (i = 0; i < desc->fieldCount; i++)
+    {
+        if ((hr = read_type_struct_field( reader, desc->fields[i], heap, buf )) != S_OK)
+        {
+            ws_free( heap, buf );
+            return hr;
+        }
+    }
+
+    switch (mapping)
     {
-        WCHAR *str, **ret = value;
+    case WS_ELEMENT_TYPE_MAPPING:
+        if ((hr = read_endelement( reader )) != S_OK) return hr;
+        break;
 
-        if (value_size != sizeof(WCHAR *)) return E_INVALIDARG;
-        if (!(str = xmltext_to_widechar( heap, text->text ))) return E_OUTOFMEMORY;
-        *ret = str;
+    case WS_ELEMENT_CONTENT_TYPE_MAPPING:
+        if ((hr = read_endelement( reader )) != S_OK) return hr;
+        if ((hr = read_node( reader )) != S_OK) return hr;
+        if (reader->state != READER_STATE_EOF) return WS_E_INVALID_FORMAT;
         break;
+
+    default: break;
+    }
+
+    *ret = buf;
+    return S_OK;
+}
+
+static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type,
+                          const void *desc, WS_READ_OPTION option, WS_HEAP *heap,
+                          void *value, ULONG size )
+{
+    switch (type)
+    {
+    case WS_STRUCT_TYPE:
+    {
+        void **ptr = value;
+        if (option != WS_READ_REQUIRED_POINTER || size != sizeof(*ptr))
+            return E_INVALIDARG;
+
+        return read_type_struct( reader, mapping, desc, heap, ptr );
+    }
+    case WS_BOOL_TYPE:
+    {
+        BOOL *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_bool( reader, mapping, desc, ptr );
+    }
+    case WS_INT8_TYPE:
+    {
+        INT8 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_int8( reader, mapping, desc, ptr );
+    }
+    case WS_INT16_TYPE:
+    {
+        INT16 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_int16( reader, mapping, desc, ptr );
+    }
+    case WS_INT32_TYPE:
+    {
+        INT32 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_int32( reader, mapping, desc, ptr );
+    }
+    case WS_INT64_TYPE:
+    {
+        INT64 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_int64( reader, mapping, desc, ptr );
+    }
+    case WS_UINT8_TYPE:
+    {
+        UINT8 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_uint8( reader, mapping, desc, ptr );
+    }
+    case WS_UINT16_TYPE:
+    {
+        UINT16 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_uint16( reader, mapping, desc, ptr );
+    }
+    case WS_UINT32_TYPE:
+    {
+        UINT32 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_uint32( reader, mapping, desc, ptr );
+    }
+    case WS_UINT64_TYPE:
+    {
+        UINT64 *ptr = value;
+        if (option != WS_READ_REQUIRED_VALUE)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_uint64( reader, mapping, desc, ptr );
+    }
+    case WS_WSZ_TYPE:
+    {
+        WCHAR **ptr = value;
+        if (option != WS_READ_REQUIRED_POINTER)
+        {
+            FIXME( "read option %u not supported\n", option );
+            return E_NOTIMPL;
+        }
+        if (size != sizeof(*ptr)) return E_INVALIDARG;
+        return read_type_wsz( reader, mapping, desc, heap, ptr );
     }
     default:
         FIXME( "type %u not supported\n", type );
         return E_NOTIMPL;
     }
+}
 
-    return S_OK;
+/**************************************************************************
+ *          WsReadType		[webservices.@]
+ */
+HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TYPE type,
+                           const void *desc, WS_READ_OPTION option, WS_HEAP *heap, void *value,
+                           ULONG size, WS_ERROR *error )
+{
+    struct reader *reader = (struct reader *)handle;
+
+    TRACE( "%p %u %u %p %u %p %p %u %p\n", handle, mapping, type, desc, option, heap, value,
+           size, error );
+    if (error) FIXME( "ignoring error parameter\n" );
+
+    if (!reader || !value) return E_INVALIDARG;
+
+    return read_type( reader, mapping, type, desc, option, heap, value, size );
 }
 
 /**************************************************************************
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index 58d1b2b..d2f2308 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -1707,6 +1707,104 @@ static void test_WsMoveReader(void)
     WsFreeHeap( heap );
 }
 
+static void prepare_struct_type_test( WS_XML_READER *reader, const char *data )
+{
+    HRESULT hr;
+    ULONG size = strlen( data );
+
+    hr = set_input( reader, data, size );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsFillReader( reader, size, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+}
+
+static void test_simple_struct_type(void)
+{
+    static const WCHAR testW[] = {'t','e','s','t',0};
+    HRESULT hr;
+    WS_XML_READER *reader;
+    WS_HEAP *heap;
+    WS_STRUCT_DESCRIPTION s;
+    WS_FIELD_DESCRIPTION f, *fields[1];
+    WS_XML_STRING ns = {0, NULL}, localname = {3, (BYTE *)"str"};
+    WS_XML_STRING localname2 = {4, (BYTE *)"test"};
+    const WS_XML_NODE *node;
+    struct test { WCHAR *str; } *test;
+
+    hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    prepare_struct_type_test( reader, "<str>test</str>" );
+    hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, NULL,
+                     WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    hr = WsGetReaderNode( reader, &node, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( node->nodeType == WS_XML_NODE_TYPE_BOF, "got %u\n", node->nodeType );
+
+    /* element field mapping */
+    memset( &f, 0, sizeof(f) );
+    f.mapping   = WS_ELEMENT_FIELD_MAPPING;
+    f.localName = &localname;
+    f.ns        = &ns;
+    f.type      = WS_WSZ_TYPE;
+    fields[0] = &f;
+
+    memset( &s, 0, sizeof(s) );
+    s.size          = sizeof(struct test);
+    s.alignment     = TYPE_ALIGNMENT(struct test);
+    s.fields        = fields;
+    s.fieldCount    = 1;
+    s.typeLocalName = &localname2;
+    s.typeNs        = &ns;
+
+    test = NULL;
+    prepare_struct_type_test( reader, "<?xml version=\"1.0\" encoding=\"utf-8\"?><str>test</str><str>test2</str>" );
+    hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
+                     WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
+    ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
+
+    test = NULL;
+    prepare_struct_type_test( reader, "<?xml version=\"1.0\" encoding=\"utf-8\"?><str>test</str>" );
+    hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
+                     WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( test != NULL, "test not set\n" );
+    if (test)
+    {
+        ok( test->str != NULL, "str not set\n" );
+        if (test->str) ok( !lstrcmpW( test->str, testW ), "wrong data\n" );
+    }
+
+    hr = WsGetReaderNode( reader, &node, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
+
+    test = NULL;
+    prepare_struct_type_test( reader, "<str>test</str>" );
+    hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s,
+                     WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( test != NULL, "test not set\n" );
+    if (test)
+    {
+        ok( test->str != NULL, "str not set\n" );
+        if (test->str) ok( !lstrcmpW( test->str, testW ), "wrong data\n" );
+    }
+
+    hr = WsGetReaderNode( reader, &node, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
+
+    WsFreeReader( reader );
+    WsFreeHeap( heap );
+}
+
 START_TEST(reader)
 {
     test_WsCreateError();
@@ -1724,4 +1822,5 @@ START_TEST(reader)
     test_WsXmlStringEquals();
     test_WsAlloc();
     test_WsMoveReader();
+    test_simple_struct_type();
 }
-- 
2.7.0.rc3




More information about the wine-patches mailing list