[8/8] webservices: Protect readers with a critical section.

Hans Leidekker hans at codeweavers.com
Wed Mar 8 04:26:00 CST 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 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 6c95d8a..0951af7 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;
 }
-- 
2.1.4




More information about the wine-patches mailing list