diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index 37c2045cdf2..db68733d5d1 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -1001,11 +1001,47 @@ error: return hr; } +static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 ) +{ + ULONG i; + if (len1 != len2) return 1; + for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; } + return 0; +} + +static struct node *read_find_parent( struct reader *reader, const WS_XML_STRING *prefix, + const WS_XML_STRING *localname ) +{ + struct node *parent; + const WS_XML_STRING *str; + + for (parent = reader->current; parent; parent = parent->parent) + { + if (parent->hdr.node.nodeType == WS_XML_NODE_TYPE_BOF) + { + if (!localname) return parent; + return NULL; + } + else if (parent->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT) + { + if (!localname) return parent; + + str = parent->hdr.prefix; + if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue; + str = parent->hdr.localName; + if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue; + return parent; + } + } + + return NULL; +} + static HRESULT read_element( struct reader *reader ) { unsigned int len = 0, ch, skip; const unsigned char *start; - struct node *node; + struct node *node = NULL, *parent; WS_XML_ELEMENT_NODE *elem; WS_XML_ATTRIBUTE *attr; HRESULT hr = WS_E_INVALID_FORMAT; @@ -1018,9 +1054,6 @@ static HRESULT read_element( struct reader *reader ) return S_OK; } - if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY; - elem = (WS_XML_ELEMENT_NODE *)node; - if (read_cmp( reader, "<", 1 )) goto error; read_skip( reader, 1 ); @@ -1034,6 +1067,12 @@ static HRESULT read_element( struct reader *reader ) } if (!len) goto error; + if (!(parent = read_find_parent( reader, NULL, NULL ))) goto error; + + hr = E_OUTOFMEMORY; + if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error; + elem = (WS_XML_ELEMENT_NODE *)node; + if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error; hr = E_OUTOFMEMORY; if (!(elem->ns = alloc_xml_string( NULL, 0 ))) goto error; @@ -1053,26 +1092,8 @@ static HRESULT read_element( struct reader *reader ) reader->current_attr++; } - read_skip_whitespace( reader ); - if (read_cmp( reader, ">", 1 ) && read_cmp( reader, "/>", 2 )) - { - hr = WS_E_INVALID_FORMAT; - goto error; - } - - read_insert_node( reader, reader->current, node ); - if (!read_cmp( reader, "/>", 2 )) - { - read_skip( reader, 2 ); - if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY; - read_insert_node( reader, reader->current, node ); - reader->state = READER_STATE_ENDELEMENT; - } - else - { - read_skip( reader, 1 ); - reader->state = READER_STATE_STARTELEMENT; - } + read_insert_node( reader, parent, node ); + reader->state = READER_STATE_STARTELEMENT; return S_OK; error: @@ -1112,10 +1133,27 @@ static HRESULT read_text( struct reader *reader ) return S_OK; } +static HRESULT read_node( struct reader * ); + static HRESULT read_startelement( struct reader *reader ) { - if (!read_cmp( reader, "<", 1 )) return read_element( reader ); - return read_text( reader ); + struct node *node; + + read_skip_whitespace( reader ); + if (!read_cmp( reader, "/>", 2 )) + { + read_skip( reader, 2 ); + if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY; + read_insert_node( reader, reader->current, node ); + reader->state = READER_STATE_ENDELEMENT; + return S_OK; + } + else if (!read_cmp( reader, ">", 1 )) + { + read_skip( reader, 1 ); + return read_node( reader ); + } + return WS_E_INVALID_FORMAT; } static HRESULT read_to_startelement( struct reader *reader, BOOL *found ) @@ -1148,36 +1186,6 @@ static HRESULT read_to_startelement( struct reader *reader, BOOL *found ) return hr; } -static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 ) -{ - ULONG i; - if (len1 != len2) return 1; - for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; } - return 0; -} - -struct node *find_parent_element( struct node *node, const WS_XML_STRING *prefix, - const WS_XML_STRING *localname ) -{ - struct node *parent; - const WS_XML_STRING *str; - - for (parent = node; parent; parent = parent->parent) - { - if (parent->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT) continue; - if (!localname) return parent; - - str = parent->hdr.prefix; - if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue; - - str = parent->hdr.localName; - if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue; - - return parent; - } - return NULL; -} - static HRESULT read_endelement( struct reader *reader ) { struct node *node, *parent; @@ -1204,7 +1212,7 @@ static HRESULT read_endelement( struct reader *reader ) } if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr; - parent = find_parent_element( reader->current, prefix, localname ); + parent = read_find_parent( reader, prefix, localname ); heap_free( prefix ); heap_free( localname ); if (!parent) return WS_E_INVALID_FORMAT; @@ -1333,7 +1341,8 @@ static HRESULT read_node( struct reader *reader ) else if (!read_cmp( reader, "", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader ); else return read_text( reader ); } } diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c index 720379e076a..62a88465d16 100644 --- a/dlls/webservices/tests/reader.c +++ b/dlls/webservices/tests/reader.c @@ -2045,7 +2045,7 @@ static void test_WsGetNamespaceFromPrefix(void) hr = set_input( reader, "", sizeof("") - 1 ); ok( hr == S_OK, "got %08x\n", hr ); hr = WsReadStartElement( reader, NULL ); - todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr ); + ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr ); prepare_namespace_test( reader, "" ); ns = NULL; @@ -2132,7 +2132,7 @@ static void test_WsGetNamespaceFromPrefix(void) prepare_namespace_test( reader, "" ); hr = WsReadStartElement( reader, NULL ); - todo_wine ok( hr == S_OK, "got %08x\n", hr ); + ok( hr == S_OK, "got %08x\n", hr ); hr = WsReadEndElement( reader, NULL ); todo_wine ok( hr == S_OK, "got %08x\n", hr ); hr = WsGetNamespaceFromPrefix( reader, &prefix, TRUE, &ns, NULL ); diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index 4eeedf5f0b2..bae214939ca 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -32,8 +32,6 @@ WS_XML_STRING *alloc_xml_string( const unsigned char *, ULONG ) DECLSPEC_HIDDEN; WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *, ULONG ) DECLSPEC_HIDDEN; HRESULT append_attribute( WS_XML_ELEMENT_NODE *, WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN; void free_attribute( WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN; -struct node *find_parent_element( struct node *, const WS_XML_STRING *, - const WS_XML_STRING * ) DECLSPEC_HIDDEN; struct node { diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index 14bddfbd758..f29b257cdb8 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -597,9 +597,18 @@ static HRESULT write_startelement( struct writer *writer ) return S_OK; } +static struct node *write_find_parent_element( struct writer *writer ) +{ + struct node *node = writer->current; + + if (node->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT) return node; + if (node->parent->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT) return node->parent; + return NULL; +} + static HRESULT write_endelement( struct writer *writer ) { - struct node *node = find_parent_element( writer->current, NULL, NULL ); + struct node *node = write_find_parent_element( writer ); WS_XML_ELEMENT_NODE *elem = &node->hdr; ULONG size; HRESULT hr;