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;