webservices: Properly restore the reader position when the next element doesn't match.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
731f22835e
commit
079f84d918
@ -4346,6 +4346,24 @@ static HRESULT read_next_node( struct reader *reader )
|
|||||||
return WS_E_INVALID_FORMAT;
|
return WS_E_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct reader_pos
|
||||||
|
{
|
||||||
|
struct node *node;
|
||||||
|
ULONG attr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void save_reader_position( const struct reader *reader, struct reader_pos *pos )
|
||||||
|
{
|
||||||
|
pos->node = reader->current;
|
||||||
|
pos->attr = reader->current_attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void restore_reader_position( struct reader *reader, const struct reader_pos *pos )
|
||||||
|
{
|
||||||
|
reader->current = pos->node;
|
||||||
|
reader->current_attr = pos->attr;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
|
static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname,
|
||||||
const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
|
const WS_XML_STRING *ns, const WS_XML_TEXT **ret, BOOL *found )
|
||||||
{
|
{
|
||||||
@ -4364,16 +4382,19 @@ static HRESULT get_text( struct reader *reader, WS_TYPE_MAPPING mapping, const W
|
|||||||
*found = TRUE;
|
*found = TRUE;
|
||||||
if (localname)
|
if (localname)
|
||||||
{
|
{
|
||||||
|
struct reader_pos pos;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (!match_element( reader->current, localname, ns ))
|
if (!match_element( reader->current, localname, ns ))
|
||||||
{
|
{
|
||||||
*found = FALSE;
|
*found = FALSE;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
save_reader_position( reader, &pos );
|
||||||
if ((hr = read_next_node( reader )) != S_OK) return hr;
|
if ((hr = read_next_node( reader )) != S_OK) return hr;
|
||||||
if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
|
if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT)
|
||||||
{
|
{
|
||||||
if (!move_to_parent_element( &reader->current )) return WS_E_INVALID_FORMAT;
|
restore_reader_position( reader, &pos );
|
||||||
*found = FALSE;
|
*found = FALSE;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -6021,8 +6042,7 @@ static HRESULT read_type_next_node( struct reader *reader )
|
|||||||
static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
|
static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_STRING *localname,
|
||||||
const WS_XML_STRING *ns )
|
const WS_XML_STRING *ns )
|
||||||
{
|
{
|
||||||
struct node *node;
|
struct reader_pos pos;
|
||||||
ULONG attr;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
if (!localname) return S_OK; /* assume reader is already correctly positioned */
|
if (!localname) return S_OK; /* assume reader is already correctly positioned */
|
||||||
@ -6034,14 +6054,10 @@ static HRESULT read_type_next_element_node( struct reader *reader, const WS_XML_
|
|||||||
}
|
}
|
||||||
if (match_element( reader->current, localname, ns )) return S_OK;
|
if (match_element( reader->current, localname, ns )) return S_OK;
|
||||||
|
|
||||||
node = reader->current;
|
save_reader_position( reader, &pos );
|
||||||
attr = reader->current_attr;
|
|
||||||
|
|
||||||
if ((hr = read_type_next_node( reader )) != S_OK) return hr;
|
if ((hr = read_type_next_node( reader )) != S_OK) return hr;
|
||||||
if (match_element( reader->current, localname, ns )) return S_OK;
|
if (match_element( reader->current, localname, ns )) return S_OK;
|
||||||
|
restore_reader_position( reader, &pos );
|
||||||
reader->current = node;
|
|
||||||
reader->current_attr = attr;
|
|
||||||
|
|
||||||
return WS_E_INVALID_FORMAT;
|
return WS_E_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
@ -6166,55 +6182,37 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
|
|||||||
|
|
||||||
static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
|
static HRESULT read_type_field( struct reader *, const WS_FIELD_DESCRIPTION *, WS_HEAP *, char *, ULONG );
|
||||||
|
|
||||||
static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_READ_OPTION option,
|
static HRESULT read_type_union( struct reader *reader, const WS_UNION_DESCRIPTION *desc, WS_HEAP *heap, void *ret,
|
||||||
WS_HEAP *heap, void *ret, ULONG size )
|
ULONG size, BOOL *found )
|
||||||
{
|
{
|
||||||
BOOL found = FALSE;
|
struct reader_pos pos;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
switch (option)
|
|
||||||
{
|
|
||||||
case WS_READ_REQUIRED_VALUE:
|
|
||||||
case WS_READ_NILLABLE_VALUE:
|
|
||||||
if (size != desc->size) return E_INVALIDARG;
|
if (size != desc->size) return E_INVALIDARG;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
save_reader_position( reader, &pos );
|
||||||
if ((hr = read_type_next_node( reader )) != S_OK) return hr;
|
if ((hr = read_type_next_node( reader )) != S_OK) return hr;
|
||||||
if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
|
|
||||||
for (i = 0; i < desc->fieldCount; i++)
|
for (i = 0; i < desc->fieldCount; i++)
|
||||||
{
|
{
|
||||||
if ((found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
|
if ((*found = match_element( reader->current, desc->fields[i]->field.localName, desc->fields[i]->field.ns )))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) *(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
|
if (!*found)
|
||||||
|
{
|
||||||
|
*(int *)((char *)ret + desc->enumOffset) = desc->noneEnumValue;
|
||||||
|
restore_reader_position( reader, &pos );
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ULONG offset = desc->fields[i]->field.offset;
|
ULONG offset = desc->fields[i]->field.offset;
|
||||||
if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) == S_OK)
|
if ((hr = read_type_field( reader, &desc->fields[i]->field, heap, ret, offset )) != S_OK) return hr;
|
||||||
*(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
|
*(int *)((char *)ret + desc->enumOffset) = desc->fields[i]->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (option)
|
return S_OK;
|
||||||
{
|
|
||||||
case WS_READ_NILLABLE_VALUE:
|
|
||||||
if (!found) move_to_parent_element( &reader->current );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WS_READ_REQUIRED_VALUE:
|
|
||||||
if (!found) hr = WS_E_INVALID_FORMAT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
|
static HRESULT read_type( struct reader *, WS_TYPE_MAPPING, WS_TYPE, const WS_XML_STRING *,
|
||||||
@ -6251,17 +6249,28 @@ static HRESULT read_type_array( struct reader *reader, const WS_FIELD_DESCRIPTIO
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (desc->type == WS_UNION_TYPE)
|
if (desc->type == WS_UNION_TYPE)
|
||||||
hr = read_type_union( reader, desc->typeDescription, option, heap, buf + offset, item_size );
|
{
|
||||||
|
BOOL found;
|
||||||
|
hr = read_type_union( reader, desc->typeDescription, heap, buf + offset, item_size, &found );
|
||||||
|
if (hr != S_OK)
|
||||||
|
{
|
||||||
|
ws_free( heap, buf, nb_allocated * item_size );
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
if (!found) break;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
|
hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->itemLocalName, desc->itemNs,
|
||||||
desc->typeDescription, option, heap, buf + offset, item_size );
|
desc->typeDescription, option, heap, buf + offset, item_size );
|
||||||
|
|
||||||
if (hr == WS_E_INVALID_FORMAT) break;
|
if (hr == WS_E_INVALID_FORMAT) break;
|
||||||
if (hr != S_OK)
|
if (hr != S_OK)
|
||||||
{
|
{
|
||||||
ws_free( heap, buf, nb_allocated * item_size );
|
ws_free( heap, buf, nb_allocated * item_size );
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
offset += item_size;
|
offset += item_size;
|
||||||
nb_items++;
|
nb_items++;
|
||||||
}
|
}
|
||||||
@ -6338,11 +6347,13 @@ static HRESULT read_type_field( struct reader *reader, const WS_FIELD_DESCRIPTIO
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WS_ELEMENT_CHOICE_FIELD_MAPPING:
|
case WS_ELEMENT_CHOICE_FIELD_MAPPING:
|
||||||
|
{
|
||||||
|
BOOL found;
|
||||||
if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
|
if (desc->type != WS_UNION_TYPE || !desc->typeDescription ||
|
||||||
(desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
|
(desc->options & (WS_FIELD_POINTER|WS_FIELD_NILLABLE))) return E_INVALIDARG;
|
||||||
hr = read_type_union( reader, desc->typeDescription, option, heap, ptr, size );
|
hr = read_type_union( reader, desc->typeDescription, heap, ptr, size, &found );
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case WS_REPEATING_ELEMENT_FIELD_MAPPING:
|
case WS_REPEATING_ELEMENT_FIELD_MAPPING:
|
||||||
case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
|
case WS_REPEATING_ELEMENT_CHOICE_FIELD_MAPPING:
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user