From 36c5252265be968388db4e65bdeeae1d4063bd53 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Wed, 8 Mar 2017 11:26:00 +0100 Subject: [PATCH] webservices: Protect readers with a critical section. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- dlls/webservices/reader.c | 592 +++++++++++++++++++++++++++++++------- 1 file changed, 488 insertions(+), 104 deletions(-) diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index 6c95d8abb75..0951af767a2 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -834,26 +834,30 @@ struct prefix struct reader { - ULONG read_size; - ULONG read_pos; - const unsigned char *read_bufptr; - enum reader_state state; - struct node *root; - struct node *current; - ULONG current_attr; - struct node *last; - struct prefix *prefixes; - ULONG nb_prefixes; - ULONG nb_prefixes_allocated; - WS_XML_READER_INPUT_TYPE input_type; - struct xmlbuf *input_buf; - const unsigned char *input_data; - ULONG input_size; - ULONG text_conv_offset; - ULONG prop_count; - struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])]; + ULONG magic; + CRITICAL_SECTION cs; + ULONG read_size; + ULONG read_pos; + const unsigned char *read_bufptr; + enum reader_state state; + struct node *root; + struct node *current; + ULONG current_attr; + struct node *last; + struct prefix *prefixes; + ULONG nb_prefixes; + ULONG nb_prefixes_allocated; + WS_XML_READER_INPUT_TYPE input_type; + struct xmlbuf *input_buf; + const unsigned char *input_data; + ULONG input_size; + ULONG text_conv_offset; + ULONG prop_count; + struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])]; }; +#define READER_MAGIC (('R' << 24) | ('E' << 16) | ('A' << 8) | 'D') + static struct reader *alloc_reader(void) { static const ULONG count = sizeof(reader_props)/sizeof(reader_props[0]); @@ -868,8 +872,12 @@ static struct reader *alloc_reader(void) } ret->nb_prefixes = ret->nb_prefixes_allocated = 1; + ret->magic = READER_MAGIC; + InitializeCriticalSection( &ret->cs ); + ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": reader.cs"); + prop_init( reader_props, count, ret->prop, &ret[1] ); - ret->prop_count = count; + ret->prop_count = count; return ret; } @@ -888,19 +896,23 @@ static void clear_prefixes( struct prefix *prefixes, ULONG count ) } } -static void free_reader( struct reader *reader ) -{ - if (!reader) return; - destroy_nodes( reader->root ); - clear_prefixes( reader->prefixes, reader->nb_prefixes ); - heap_free( reader->prefixes ); - heap_free( reader ); -} - HRESULT copy_node( WS_XML_READER *handle, struct node **node ) { struct reader *reader = (struct reader *)handle; - return dup_tree( node, reader->current ); + HRESULT hr; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = dup_tree( node, reader->current ); + + LeaveCriticalSection( &reader->cs ); + return hr; } static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns ) @@ -981,18 +993,28 @@ static void read_insert_node( struct reader *reader, struct node *parent, struct reader->current = reader->last = node; } -static HRESULT read_init_state( struct reader *reader ) +static void free_reader( struct reader *reader ) +{ + destroy_nodes( reader->root ); + clear_prefixes( reader->prefixes, reader->nb_prefixes ); + heap_free( reader->prefixes ); + reader->cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &reader->cs ); + heap_free( reader ); +} + +static HRESULT init_reader( struct reader *reader ) { struct node *node; + reader->state = READER_STATE_INITIAL; destroy_nodes( reader->root ); - reader->root = NULL; - reader->input_buf = NULL; + reader->root = reader->current = NULL; + reader->current_attr = 0; clear_prefixes( reader->prefixes, reader->nb_prefixes ); - reader->nb_prefixes = 1; + reader->nb_prefixes = 1; if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY; read_insert_eof( reader, node ); - reader->state = READER_STATE_INITIAL; return S_OK; } @@ -1031,7 +1053,7 @@ HRESULT WINAPI WsCreateReader( const WS_XML_READER_PROPERTY *properties, ULONG c } } - if ((hr = read_init_state( reader )) != S_OK) + if ((hr = init_reader( reader )) != S_OK) { free_reader( reader ); return hr; @@ -1049,6 +1071,20 @@ void WINAPI WsFreeReader( WS_XML_READER *handle ) struct reader *reader = (struct reader *)handle; TRACE( "%p\n", handle ); + + if (!reader) return; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return; + } + + reader->magic = 0; + + LeaveCriticalSection( &reader->cs ); free_reader( reader ); } @@ -1065,10 +1101,19 @@ HRESULT WINAPI WsFillReader( WS_XML_READER *handle, ULONG min_size, const WS_ASY if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + /* FIXME: add support for stream input */ reader->read_size = min( min_size, reader->input_size ); reader->read_pos = 0; + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -1090,7 +1135,20 @@ HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STR if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !prefix || !ns) return E_INVALIDARG; - if (reader->state != READER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (reader->state != READER_STATE_STARTELEMENT) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } if (!prefix->length) { @@ -1130,6 +1188,8 @@ HRESULT WINAPI WsGetNamespaceFromPrefix( WS_XML_READER *handle, const WS_XML_STR *ns = NULL; return S_FALSE; } + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -1146,7 +1206,17 @@ HRESULT WINAPI WsGetReaderNode( WS_XML_READER *handle, const WS_XML_NODE **node, if (!reader || !node) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + *node = &reader->current->hdr.node; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -1157,23 +1227,44 @@ HRESULT WINAPI WsGetReaderProperty( WS_XML_READER *handle, WS_XML_READER_PROPERT void *buf, ULONG size, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!reader->input_type) return WS_E_INVALID_OPERATION; + if (!reader) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } if (id == WS_XML_READER_PROPERTY_CHARSET) { WS_CHARSET charset; - HRESULT hr; - - if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) return hr; - if (!charset) return WS_E_INVALID_FORMAT; + if ((hr = prop_get( reader->prop, reader->prop_count, id, &charset, size )) != S_OK) goto done; + if (!charset) + { + hr = WS_E_INVALID_FORMAT; + goto done; + } *(WS_CHARSET *)buf = charset; - return S_OK; + hr = S_OK; } - return prop_get( reader->prop, reader->prop_count, id, buf, size ); + else hr = prop_get( reader->prop, reader->prop_count, id, buf, size ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -1391,8 +1482,7 @@ static HRESULT parse_name( const unsigned char *str, unsigned int len, static int codepoint_to_utf8( int cp, unsigned char *dst ) { - if (!cp) - return -1; + if (!cp) return -1; if (cp < 0x80) { *dst = cp; @@ -1476,7 +1566,7 @@ static HRESULT decode_text( const unsigned char *str, ULONG len, unsigned char * p++; len--; if (!len) return WS_E_INVALID_FORMAT; - else if (*p == 'x') + if (*p == 'x') { p++; len--; @@ -2040,12 +2130,25 @@ static HRESULT read_node( struct reader *reader ) HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - return read_endelement( reader ); + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_endelement( reader ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -2054,12 +2157,25 @@ HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error ) HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - return read_node( reader ); + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_node( reader ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -2068,12 +2184,25 @@ HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error ) HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p\n", handle, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - return read_startelement( reader ); + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_startelement( reader ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -2083,6 +2212,7 @@ HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING const WS_XML_STRING *ns, BOOL *found, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %s %s %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), found, error ); if (error) FIXME( "ignoring error parameter\n" ); @@ -2090,7 +2220,18 @@ HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING if (!reader) return E_INVALIDARG; if (localname || ns) FIXME( "name and/or namespace not verified\n" ); - return read_to_startelement( reader, found ); + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_to_startelement( reader, found ); + + LeaveCriticalSection( &reader->cs ); + return hr; } BOOL move_to_root_element( struct node *root, struct node **current ) @@ -2369,14 +2510,31 @@ static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %u %p %p\n", handle, move, found, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - return read_move_to( reader, move, found ); + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + hr = read_move_to( reader, move, found ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -2385,19 +2543,32 @@ HRESULT WINAPI WsMoveReader( WS_XML_READER *handle, WS_MOVE_TO move, BOOL *found HRESULT WINAPI WsReadStartAttribute( WS_XML_READER *handle, ULONG index, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; - WS_XML_ELEMENT_NODE *elem; + const WS_XML_ELEMENT_NODE *elem; TRACE( "%p %u %p\n", handle, index, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + elem = &reader->current->hdr; if (reader->state != READER_STATE_STARTELEMENT || index >= elem->attributeCount) + { + LeaveCriticalSection( &reader->cs ); return WS_E_INVALID_FORMAT; + } reader->current_attr = index; - reader->state = READER_STATE_STARTATTRIBUTE; + reader->state = READER_STATE_STARTATTRIBUTE; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -2413,10 +2584,23 @@ HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error ) if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if (reader->state != READER_STATE_STARTATTRIBUTE) + { + LeaveCriticalSection( &reader->cs ); return WS_E_INVALID_FORMAT; + } reader->state = READER_STATE_STARTELEMENT; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -3010,6 +3194,7 @@ HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *loca WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr = S_OK; TRACE( "%p %s %s %d %p %p\n", handle, debugstr_xmlstr(localname), debugstr_xmlstr(ns), required, index, error ); @@ -3017,16 +3202,32 @@ HRESULT WINAPI WsFindAttribute( WS_XML_READER *handle, const WS_XML_STRING *loca if (!reader || !localname || !ns || !index) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) + { + LeaveCriticalSection( &reader->cs ); return WS_E_INVALID_OPERATION; + } if (!find_attribute( reader, localname, ns, index )) { - if (required) return WS_E_INVALID_FORMAT; - *index = ~0u; - return S_FALSE; + if (required) hr = WS_E_INVALID_FORMAT; + else + { + *index = ~0u; + hr = S_FALSE; + } } - return S_OK; + + LeaveCriticalSection( &reader->cs ); + return hr; } static HRESULT read_get_text( struct reader *reader, WS_TYPE_MAPPING mapping, @@ -4485,21 +4686,34 @@ HRESULT WINAPI WsReadType( WS_XML_READER *handle, WS_TYPE_MAPPING mapping, WS_TY if (!reader || !value) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if ((hr = read_type( reader, mapping, type, NULL, NULL, desc, option, heap, value, size )) != S_OK) + { + LeaveCriticalSection( &reader->cs ); return hr; + } switch (mapping) { case WS_ELEMENT_TYPE_MAPPING: - if ((hr = read_node( reader )) != S_OK) return hr; + hr = read_node( reader ); break; default: break; } - if (!read_end_of_data( reader )) return WS_E_INVALID_FORMAT; - return S_OK; + if (hr == S_OK && !read_end_of_data( reader )) hr = WS_E_INVALID_FORMAT; + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4510,14 +4724,26 @@ HRESULT WINAPI WsReadElement( WS_XML_READER *handle, const WS_ELEMENT_DESCRIPTIO WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p %u %p %p %u %p\n", handle, desc, option, heap, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !desc || !value) return E_INVALIDARG; - return read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName, - desc->elementNs, desc->typeDescription, option, heap, value, size ); + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, desc->type, desc->elementLocalName, + desc->elementNs, desc->typeDescription, option, heap, value, size ); + + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4528,14 +4754,26 @@ HRESULT WINAPI WsReadValue( WS_XML_READER *handle, WS_VALUE_TYPE value_type, voi { struct reader *reader = (struct reader *)handle; WS_TYPE type = map_value_type( value_type ); + HRESULT hr; TRACE( "%p %u %p %u %p\n", handle, type, value, size, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !value || type == ~0u) return E_INVALIDARG; - return read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE, - NULL, value, size ); + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, type, NULL, NULL, NULL, WS_READ_REQUIRED_VALUE, + NULL, value, size ); + + LeaveCriticalSection( &reader->cs ); + return hr; } static inline BOOL is_utf8( const unsigned char *data, ULONG size, ULONG *offset ) @@ -4584,6 +4822,8 @@ static void set_input_buffer( struct reader *reader, struct xmlbuf *buf, const u reader->read_size = reader->input_size; reader->read_pos = 0; reader->read_bufptr = reader->input_data; + + reader->text_conv_offset = 0; } /************************************************************************** @@ -4595,22 +4835,30 @@ HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING * { struct reader *reader = (struct reader *)handle; struct node *node; - HRESULT hr; ULONG i, offset = 0; + HRESULT hr; TRACE( "%p %p %p %p %u %p\n", handle, encoding, input, properties, count, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + for (i = 0; i < count; i++) { hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; } - if ((hr = read_init_state( reader )) != S_OK) return hr; + if ((hr = init_reader( reader )) != S_OK) goto done; switch (encoding->encodingType) { @@ -4623,7 +4871,8 @@ HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING * if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER) { FIXME( "charset detection on input type %u not supported\n", input->inputType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } if (charset == WS_CHARSET_AUTO) @@ -4631,13 +4880,15 @@ HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING * hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; break; } default: FIXME( "encoding type %u not supported\n", encoding->encodingType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } + switch (input->inputType) { case WS_XML_READER_INPUT_TYPE_BUFFER: @@ -4649,12 +4900,16 @@ HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING * } default: FIXME( "input type %u not supported\n", input->inputType ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } - if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY; - read_insert_bof( reader, node ); - return S_OK; + if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY; + else read_insert_bof( reader, node ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4668,32 +4923,43 @@ HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer, struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer; WS_CHARSET charset; struct node *node; - HRESULT hr; ULONG i, offset = 0; + HRESULT hr; TRACE( "%p %p %p %u %p\n", handle, buffer, properties, count, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !xmlbuf) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + for (i = 0; i < count; i++) { hr = prop_set( reader->prop, reader->prop_count, properties[i].id, properties[i].value, properties[i].valueSize ); - if (hr != S_OK) return hr; + if (hr != S_OK) goto done; } - if ((hr = read_init_state( reader )) != S_OK) return hr; + if ((hr = init_reader( reader )) != S_OK) goto done; charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset ); - hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, - &charset, sizeof(charset) ); - if (hr != S_OK) return hr; + hr = prop_set( reader->prop, reader->prop_count, WS_XML_READER_PROPERTY_CHARSET, &charset, + sizeof(charset) ); + if (hr != S_OK) goto done; set_input_buffer( reader, xmlbuf, (const unsigned char *)xmlbuf->ptr + offset, xmlbuf->size - offset ); - if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY; - read_insert_bof( reader, node ); - return S_OK; + if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY; + else read_insert_bof( reader, node ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; } /************************************************************************** @@ -4722,10 +4988,25 @@ HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION if (error) FIXME( "ignoring error parameter\n" ); if (!reader || !pos) return E_INVALIDARG; - if (!reader->input_buf) return WS_E_INVALID_OPERATION; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_buf) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } pos->buffer = (WS_XML_BUFFER *)reader->input_buf; pos->node = reader->current; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4739,10 +5020,25 @@ HRESULT WINAPI WsSetReaderPosition( WS_XML_READER *handle, const WS_XML_NODE_POS TRACE( "%p %p %p\n", handle, pos, error ); if (error) FIXME( "ignoring error parameter\n" ); - if (!reader || !pos || (struct xmlbuf *)pos->buffer != reader->input_buf) return E_INVALIDARG; - if (!reader->input_buf) return WS_E_INVALID_OPERATION; + if (!reader || !pos) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC || (struct xmlbuf *)pos->buffer != reader->input_buf) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_buf) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } reader->current = pos->node; + + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4766,8 +5062,26 @@ HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - if (!count) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!count) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } *count = 0; if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes) @@ -4775,11 +5089,17 @@ HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current; WS_XML_BASE64_TEXT base64; - if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK) return hr; + if ((hr = utf8_to_base64( (const WS_XML_UTF8_TEXT *)text->text, &base64 )) != S_OK) + { + LeaveCriticalSection( &reader->cs ); + return hr; + } if (reader->text_conv_offset == base64.length) { heap_free( base64.bytes ); - return read_node( reader ); + hr = read_node( reader ); + LeaveCriticalSection( &reader->cs ); + return hr; } *count = min( base64.length - reader->text_conv_offset, max_count ); memcpy( bytes, base64.bytes + reader->text_conv_offset, *count ); @@ -4787,6 +5107,7 @@ HRESULT WINAPI WsReadBytes( WS_XML_READER *handle, void *bytes, ULONG max_count, heap_free( base64.bytes ); } + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4810,8 +5131,26 @@ HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - if (!count) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!count) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } *count = 0; if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && chars) @@ -4820,11 +5159,17 @@ HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count WS_XML_UTF16_TEXT utf16; HRESULT hr; - if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK) return hr; + if ((hr = utf8_to_utf16( (const WS_XML_UTF8_TEXT *)text->text, &utf16 )) != S_OK) + { + LeaveCriticalSection( &reader->cs ); + return hr; + } if (reader->text_conv_offset == utf16.byteCount / sizeof(WCHAR)) { heap_free( utf16.bytes ); - return read_node( reader ); + hr = read_node( reader ); + LeaveCriticalSection( &reader->cs ); + return hr; } *count = min( utf16.byteCount / sizeof(WCHAR) - reader->text_conv_offset, max_count ); memcpy( chars, utf16.bytes + reader->text_conv_offset * sizeof(WCHAR), *count * sizeof(WCHAR) ); @@ -4832,6 +5177,7 @@ HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count heap_free( utf16.bytes ); } + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4841,13 +5187,32 @@ HRESULT WINAPI WsReadChars( WS_XML_READER *handle, WCHAR *chars, ULONG max_count HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_count, ULONG *count, WS_ERROR *error ) { struct reader *reader = (struct reader *)handle; + HRESULT hr; TRACE( "%p %p %u %p %p\n", handle, bytes, max_count, count, error ); if (error) FIXME( "ignoring error parameter\n" ); if (!reader) return E_INVALIDARG; - if (!reader->input_type) return WS_E_INVALID_OPERATION; - if (!count) return E_INVALIDARG; + + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + + if (!reader->input_type) + { + LeaveCriticalSection( &reader->cs ); + return WS_E_INVALID_OPERATION; + } + + if (!count) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } *count = 0; if (node_type( reader->current ) == WS_XML_NODE_TYPE_TEXT && bytes) @@ -4855,12 +5220,18 @@ HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_co const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)reader->current; const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text->text; - if (reader->text_conv_offset == utf8->value.length) return read_node( reader ); + if (reader->text_conv_offset == utf8->value.length) + { + hr = read_node( reader ); + LeaveCriticalSection( &reader->cs ); + return hr; + } *count = min( utf8->value.length - reader->text_conv_offset, max_count ); memcpy( bytes, utf8->value.bytes + reader->text_conv_offset, *count ); reader->text_conv_offset += *count; } + LeaveCriticalSection( &reader->cs ); return S_OK; } @@ -4934,8 +5305,16 @@ HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEME if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG; + EnterCriticalSection( &reader->cs ); + + if (reader->magic != READER_MAGIC) + { + LeaveCriticalSection( &reader->cs ); + return E_INVALIDARG; + } + if ((hr = start_mapping( reader, WS_ELEMENT_TYPE_MAPPING, desc->elementLocalName, desc->elementNs )) != S_OK) - return hr; + goto done; for (i = 0; i < count; i++) { @@ -4943,18 +5322,19 @@ HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEME if (params[i].parameterType == WS_PARAMETER_TYPE_MESSAGES) { FIXME( "messages type not supported\n" ); - return E_NOTIMPL; + hr = E_NOTIMPL; + goto done; } - if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) return hr; + if ((hr = get_param_desc( desc_struct, params[i].outputMessageIndex, &desc_field )) != S_OK) goto done; if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL) { void *ptr = *(void **)args[i]; - if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) return hr; + if ((hr = read_param( reader, desc_field, heap, ptr )) != S_OK) goto done; } else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY) { void **ptr = *(void ***)args[i]; - if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) return hr; + if ((hr = read_param_array( reader, desc_field, heap, ptr, &len )) != S_OK) goto done; set_array_len( params, count, params[i].outputMessageIndex, len, args ); } } @@ -4965,5 +5345,9 @@ HRESULT read_output_params( WS_XML_READER *handle, WS_HEAP *heap, const WS_ELEME parent->flags |= NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT; } - return end_mapping( reader, WS_ELEMENT_TYPE_MAPPING ); + hr = end_mapping( reader, WS_ELEMENT_TYPE_MAPPING ); + +done: + LeaveCriticalSection( &reader->cs ); + return hr; }