diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index 9391cf8f816..9164b4fd85b 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -1068,12 +1068,12 @@ static HRESULT read_to_startelement( struct reader *reader, BOOL *found ) return hr; } -static BOOL cmp_localname( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 ) +static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 ) { ULONG i; - if (len1 != len2) return FALSE; - for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return FALSE; } - return TRUE; + 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, @@ -1088,10 +1088,10 @@ struct node *find_parent_element( struct node *node, const WS_XML_STRING *prefix if (!localname) return parent; str = parent->hdr.prefix; - if (!cmp_localname( str->bytes, str->length, prefix->bytes, prefix->length )) continue; + if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue; str = parent->hdr.localName; - if (!cmp_localname( str->bytes, str->length, localname->bytes, localname->length )) continue; + if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue; return parent; } @@ -1579,6 +1579,59 @@ static HRESULT read_get_attribute_text( struct reader *reader, WS_XML_UTF8_TEXT return S_OK; } +static BOOL find_attribute( struct reader *reader, const WS_XML_STRING *localname, + const WS_XML_STRING *ns, ULONG *index ) +{ + ULONG i; + WS_XML_ELEMENT_NODE *elem = &reader->current->hdr; + + if (!localname) + { + *index = reader->current_attr; + return TRUE; + } + for (i = 0; i < elem->attributeCount; i++) + { + const WS_XML_STRING *localname2 = elem->attributes[i]->localName; + const WS_XML_STRING *ns2 = elem->attributes[i]->ns; + + if (!cmp_name( localname->bytes, localname->length, localname2->bytes, localname2->length ) && + !cmp_name( ns->bytes, ns->length, ns2->bytes, ns2->length )) + { + *index = i; + return TRUE; + } + } + return FALSE; +} + +/************************************************************************** + * WsFindAttribute [webservices.@] + */ +HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *localname, + const WS_XML_STRING *ns, BOOL required, ULONG *index, + WS_ERROR *error ) +{ + struct reader *reader = (struct reader *)handle; + + TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), + required, index, error ); + if (error) FIXME( "ignoring error parameter\n" ); + + if (!reader || !localname || !ns || !index) return E_INVALIDARG; + + if (reader->current->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT) + return WS_E_INVALID_OPERATION; + + if (!find_attribute( reader, localname, ns, index )) + { + if (required) return WS_E_INVALID_FORMAT; + *index = ~0u; + return S_FALSE; + } + return S_OK; +} + static HRESULT read_type_bool( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_BOOL_DESCRIPTION *desc, BOOL *ret ) { diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c index f9b2ea9b8db..555226d92d8 100644 --- a/dlls/webservices/tests/reader.c +++ b/dlls/webservices/tests/reader.c @@ -1871,6 +1871,94 @@ static void test_cdata(void) WsFreeReader( reader ); } +static void test_WsFindAttribute(void) +{ + static const char test[] = ""; + WS_XML_STRING ns = {0, NULL}, localname = {4, (BYTE *)"attr"}; + WS_XML_STRING localname2 = {5, (BYTE *)"attr2"}, localname3 = {5, (BYTE *)"attr3"}; + WS_XML_READER *reader; + ULONG index; + HRESULT hr; + + hr = WsCreateReader( NULL, 0, &reader, NULL ) ; + ok( hr == S_OK, "got %08x\n", hr ); + + hr = set_input( reader, test, sizeof(test) - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsFindAttribute( reader, &localname, &ns, TRUE, NULL, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_input( reader, test, sizeof(test) - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsFindAttribute( reader, &localname, NULL, TRUE, &index, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_input( reader, test, sizeof(test) - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsFindAttribute( reader, NULL, &ns, TRUE, &index, NULL ); + ok( hr == E_INVALIDARG, "got %08x\n", hr ); + + hr = set_input( reader, test, sizeof(test) - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + index = 0xdeadbeef; + hr = WsFindAttribute( reader, &localname, &ns, TRUE, &index, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( !index, "got %u\n", index ); + + index = 0xdeadbeef; + hr = WsFindAttribute( reader, &localname2, &ns, TRUE, &index, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + ok( index == 1, "got %u\n", index ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + index = 0xdeadbeef; + hr = WsFindAttribute( reader, &localname, &ns, TRUE, &index, NULL ); + ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr ); + ok( index == 0xdeadbeef, "got %u\n", index ); + + hr = set_input( reader, test, sizeof(test) - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + index = 0xdeadbeef; + hr = WsFindAttribute( reader, &localname3, &ns, TRUE, &index, NULL ); + ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr ); + ok( index == 0xdeadbeef, "got %u\n", index ); + + hr = set_input( reader, test, sizeof(test) - 1 ); + ok( hr == S_OK, "got %08x\n", hr ); + + hr = WsReadNode( reader, NULL ); + ok( hr == S_OK, "got %08x\n", hr ); + + index = 0xdeadbeef; + hr = WsFindAttribute( reader, &localname3, &ns, FALSE, &index, NULL ); + ok( hr == S_FALSE, "got %08x\n", hr ); + ok( index == ~0u, "got %u\n", index ); + + WsFreeReader( reader ); +} + START_TEST(reader) { test_WsCreateError(); @@ -1890,4 +1978,5 @@ START_TEST(reader) test_WsMoveReader(); test_simple_struct_type(); test_cdata(); + test_WsFindAttribute(); } diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec index ffe8bcab284..55004240eb1 100644 --- a/dlls/webservices/webservices.spec +++ b/dlls/webservices/webservices.spec @@ -45,7 +45,7 @@ @ stub WsFileTimeToDateTime @ stub WsFillBody @ stdcall WsFillReader(ptr long ptr ptr) -@ stub WsFindAttribute +@ stdcall WsFindAttribute(ptr ptr ptr long ptr ptr) @ stub WsFlushBody @ stub WsFlushWriter @ stub WsFreeChannel