diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index 9a82bcd6300..9ba4dfc0a8f 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -4000,7 +4000,11 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, char *buf; if (!desc) return E_INVALIDARG; - if (desc->structOptions) FIXME( "struct options %08x not supported\n", desc->structOptions ); + if (desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT) + { + FIXME( "struct options %08x not supported\n", + desc->structOptions & ~WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT ); + } switch (option) { @@ -4037,7 +4041,7 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, return hr; } *(char **)ret = buf; - return S_OK; + break; case WS_READ_OPTIONAL_POINTER: case WS_READ_NILLABLE_POINTER: @@ -4047,16 +4051,77 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, buf = NULL; } *(char **)ret = buf; - return S_OK; + break; case WS_READ_REQUIRED_VALUE: case WS_READ_NILLABLE_VALUE: - return hr; + if (hr != S_OK) return hr; + break; default: ERR( "unhandled read option %u\n", option ); return E_NOTIMPL; } + + if (desc->structOptions & WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT) + { + struct node *parent = find_parent( reader ); + parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT; + } + return S_OK; +} + +static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname, + const WS_XML_STRING *ns ) +{ + switch (mapping) + { + case WS_ELEMENT_TYPE_MAPPING: + case WS_ELEMENT_CONTENT_TYPE_MAPPING: + return read_type_next_element_node( reader, localname, ns ); + + case WS_ANY_ELEMENT_TYPE_MAPPING: + case WS_ATTRIBUTE_TYPE_MAPPING: + return S_OK; + + default: + FIXME( "unhandled mapping %u\n", mapping ); + return E_NOTIMPL; + } +} + +static HRESULT read_type_endelement_node( struct reader *reader ) +{ + const struct node *parent = find_parent( reader ); + HRESULT hr; + + for (;;) + { + if ((hr = read_type_next_node( reader )) != S_OK) return hr; + if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == parent) + { + return S_OK; + } + if (read_end_of_data( reader ) || !(parent->flags & NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT)) break; + } + + return WS_E_INVALID_FORMAT; +} + +static HRESULT end_mapping( struct reader *reader, WS_TYPE_MAPPING mapping ) +{ + switch (mapping) + { + case WS_ELEMENT_TYPE_MAPPING: + return read_type_endelement_node( reader ); + + case WS_ELEMENT_CONTENT_TYPE_MAPPING: + return read_type_next_node( reader ); + + case WS_ATTRIBUTE_TYPE_MAPPING: + default: + return S_OK; + } } static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem ) @@ -4078,28 +4143,17 @@ static HRESULT is_nil_element( const WS_XML_ELEMENT_NODE *elem ) } static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYPE type, - const WS_XML_STRING *localname, const WS_XML_STRING *ns, - const void *desc, WS_READ_OPTION option, WS_HEAP *heap, - void *value, ULONG size ) + const WS_XML_STRING *localname, const WS_XML_STRING *ns, const void *desc, + WS_READ_OPTION option, WS_HEAP *heap, void *value, ULONG size ) { HRESULT hr; - switch (mapping) + if ((hr = start_mapping( reader, mapping, localname, ns )) != S_OK) return hr; + + if (mapping == WS_ELEMENT_TYPE_MAPPING && is_nil_element( &reader->current->hdr )) { - case WS_ELEMENT_TYPE_MAPPING: - case WS_ELEMENT_CONTENT_TYPE_MAPPING: - if ((hr = read_type_next_element_node( reader, localname, ns )) != S_OK) return hr; - if ((option == WS_READ_NILLABLE_POINTER || option == WS_READ_NILLABLE_VALUE) && - is_nil_element( &reader->current->hdr )) return read_type_next_node( reader ); - break; - - case WS_ANY_ELEMENT_TYPE_MAPPING: - case WS_ATTRIBUTE_TYPE_MAPPING: - break; - - default: - FIXME( "unhandled mapping %u\n", mapping ); - return E_NOTIMPL; + if (option != WS_READ_NILLABLE_POINTER && option != WS_READ_NILLABLE_VALUE) return WS_E_INVALID_FORMAT; + return end_mapping( reader, mapping ); } switch (type) @@ -4189,16 +4243,7 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP return E_NOTIMPL; } - switch (mapping) - { - case WS_ELEMENT_TYPE_MAPPING: - case WS_ELEMENT_CONTENT_TYPE_MAPPING: - return read_type_next_node( reader ); - - case WS_ATTRIBUTE_TYPE_MAPPING: - default: - return S_OK; - } + return end_mapping( reader, mapping ); } /************************************************************************** diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c index a020c0111ef..62ed4990394 100644 --- a/dlls/webservices/tests/reader.c +++ b/dlls/webservices/tests/reader.c @@ -71,6 +71,12 @@ static const char data11[] = "" ""; +static const char data11b[] = + "" + "" + "content" + ""; + static const char data12[] = "" "1" @@ -2069,12 +2075,23 @@ static void test_simple_struct_type(void) s.typeLocalName = &localname2; s.typeNs = &ns; - test = NULL; prepare_struct_type_test( reader, "testtest2" ); 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 ); + prepare_struct_type_test( reader, "testtest2" ); + hr = WsReadType( reader, WS_ELEMENT_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 ); + + s.structOptions = WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT; + prepare_struct_type_test( reader, "testtest2" ); + hr = WsReadType( reader, WS_ELEMENT_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 ); + s.structOptions = 0; + test = NULL; prepare_struct_type_test( reader, "test" ); hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, @@ -2815,6 +2832,29 @@ static void test_complex_struct_type(void) ok( hr == S_OK, "got %08x\n", hr ); ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType ); + /* trailing content */ + prepare_struct_type_test( reader, data11b ); + hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + s.structOptions = WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT; + hr = WsReadType( reader, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, + WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), error ); + ok( hr == S_OK, "got %08x\n", hr ); + + 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 ); + + prepare_struct_type_test( reader, data11b ); + hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + s.structOptions = 0; + hr = WsReadType( reader, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, + WS_READ_REQUIRED_POINTER, heap, &test, sizeof(test), error ); + ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr ); + WsFreeReader( reader ); WsFreeHeap( heap ); WsFreeError( error ); diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index 12b7984b9c4..424f3fe51f7 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -41,12 +41,18 @@ HRESULT set_output( WS_XML_WRITER * ) DECLSPEC_HIDDEN; HRESULT set_input( WS_XML_READER *, char *, ULONG ) DECLSPEC_HIDDEN; ULONG get_type_size( WS_TYPE, const WS_STRUCT_DESCRIPTION * ) DECLSPEC_HIDDEN; +enum node_flag +{ + NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT = 0x1, +}; + struct node { WS_XML_ELEMENT_NODE hdr; struct list entry; struct node *parent; struct list children; + ULONG flags; }; struct node *alloc_node( WS_XML_NODE_TYPE ) DECLSPEC_HIDDEN;