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

Hans Leidekker hans at codeweavers.com
Wed Mar 8 04:25:57 CST 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/writer.c | 625 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 515 insertions(+), 110 deletions(-)

diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 852cfdb..20cbace 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -71,19 +71,23 @@ enum writer_state
 
 struct writer
 {
-    ULONG                     write_pos;
-    unsigned char            *write_bufptr;
-    enum writer_state         state;
-    struct node              *root;
-    struct node              *current;
-    WS_XML_STRING            *current_ns;
-    WS_XML_WRITER_OUTPUT_TYPE output_type;
-    struct xmlbuf            *output_buf;
-    WS_HEAP                  *output_heap;
-    ULONG                     prop_count;
-    struct prop               prop[sizeof(writer_props)/sizeof(writer_props[0])];
+    ULONG                      magic;
+    CRITICAL_SECTION           cs;
+    ULONG                      write_pos;
+    unsigned char             *write_bufptr;
+    enum writer_state          state;
+    struct node               *root;
+    struct node               *current;
+    WS_XML_STRING             *current_ns;
+    WS_XML_WRITER_OUTPUT_TYPE  output_type;
+    struct xmlbuf             *output_buf;
+    WS_HEAP                   *output_heap;
+    ULONG                      prop_count;
+    struct prop                prop[sizeof(writer_props)/sizeof(writer_props[0])];
 };
 
+#define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
+
 static struct writer *alloc_writer(void)
 {
     static const ULONG count = sizeof(writer_props)/sizeof(writer_props[0]);
@@ -91,6 +95,11 @@ static struct writer *alloc_writer(void)
     ULONG size = sizeof(*ret) + prop_size( writer_props, count );
 
     if (!(ret = heap_alloc_zero( size ))) return NULL;
+
+    ret->magic      = WRITER_MAGIC;
+    InitializeCriticalSection( &ret->cs );
+    ret->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": writer.cs");
+
     prop_init( writer_props, count, ret->prop, &ret[1] );
     ret->prop_count = count;
     return ret;
@@ -98,10 +107,12 @@ static struct writer *alloc_writer(void)
 
 static void free_writer( struct writer *writer )
 {
-    if (!writer) return;
     destroy_nodes( writer->root );
     heap_free( writer->current_ns );
     WsFreeHeap( writer->output_heap );
+
+    writer->cs.DebugInfo->Spare[0] = 0;
+    DeleteCriticalSection( &writer->cs );
     heap_free( writer );
 }
 
@@ -137,18 +148,20 @@ static struct node *find_parent( struct writer *writer )
     return NULL;
 }
 
-static HRESULT write_init_state( struct writer *writer )
+static HRESULT init_writer( struct writer *writer )
 {
     struct node *node;
 
-    heap_free( writer->current_ns );
-    writer->current_ns = NULL;
+    writer->write_pos    = 0;
+    writer->write_bufptr = NULL;
     destroy_nodes( writer->root );
-    writer->root = NULL;
+    writer->root         = writer->current = NULL;
+    heap_free( writer->current_ns );
+    writer->current_ns   = NULL;
 
     if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
     write_insert_eof( writer, node );
-    writer->state = WRITER_STATE_INITIAL;
+    writer->state        = WRITER_STATE_INITIAL;
     return S_OK;
 }
 
@@ -203,7 +216,7 @@ HRESULT WINAPI WsCreateWriter( const WS_XML_WRITER_PROPERTY *properties, ULONG c
         return hr;
     }
 
-    hr = write_init_state( writer );
+    hr = init_writer( writer );
     if (hr != S_OK)
     {
         free_writer( writer );
@@ -222,6 +235,20 @@ void WINAPI WsFreeWriter( WS_XML_WRITER *handle )
     struct writer *writer = (struct writer *)handle;
 
     TRACE( "%p\n", handle );
+
+    if (!writer) return;
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return;
+    }
+
+    writer->magic = 0;
+
+    LeaveCriticalSection( &writer->cs );
     free_writer( writer );
 }
 
@@ -273,25 +300,46 @@ HRESULT WINAPI WsGetWriterProperty( WS_XML_WRITER *handle, WS_XML_WRITER_PROPERT
                                     void *buf, ULONG size, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr = S_OK;
 
     TRACE( "%p %u %p %u %p\n", handle, id, buf, size, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
-    if (!writer->output_type) return WS_E_INVALID_OPERATION;
+    if (!writer) return E_INVALIDARG;
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (!writer->output_type)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
 
     switch (id)
     {
     case WS_XML_WRITER_PROPERTY_BYTES:
     {
         WS_BYTES *bytes = buf;
-        if (size != sizeof(*bytes)) return E_INVALIDARG;
-        bytes->bytes  = writer->output_buf->ptr;
-        bytes->length = writer->output_buf->size;
-        return S_OK;
+        if (size != sizeof(*bytes)) hr = E_INVALIDARG;
+        else
+        {
+            bytes->bytes  = writer->output_buf->ptr;
+            bytes->length = writer->output_buf->size;
+        }
+        break;
     }
     default:
-        return prop_get( writer->prop, writer->prop_count, id, buf, size );
+        hr = prop_get( writer->prop, writer->prop_count, id, buf, size );
     }
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static void set_output_buffer( struct writer *writer, struct xmlbuf *xmlbuf )
@@ -324,14 +372,22 @@ HRESULT WINAPI WsSetOutput( WS_XML_WRITER *handle, const WS_XML_WRITER_ENCODING
 
     if (!writer) return E_INVALIDARG;
 
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
     for (i = 0; i < count; i++)
     {
         hr = prop_set( writer->prop, writer->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 = write_init_state( writer )) != S_OK) return hr;
+    if ((hr = init_writer( writer )) != S_OK) goto done;
 
     switch (encoding->encodingType)
     {
@@ -341,32 +397,39 @@ HRESULT WINAPI WsSetOutput( WS_XML_WRITER *handle, const WS_XML_WRITER_ENCODING
         if (text->charSet != WS_CHARSET_UTF8)
         {
             FIXME( "charset %u not supported\n", text->charSet );
-            return E_NOTIMPL;
+            hr = E_NOTIMPL;
+            goto done;
         }
         break;
     }
     default:
         FIXME( "encoding type %u not supported\n", encoding->encodingType );
-        return E_NOTIMPL;
+        hr = E_NOTIMPL;
+        goto done;
     }
+
     switch (output->outputType)
     {
     case WS_XML_WRITER_OUTPUT_TYPE_BUFFER:
     {
         struct xmlbuf *xmlbuf;
 
-        if (!(xmlbuf = alloc_xmlbuf( writer->output_heap ))) return WS_E_QUOTA_EXCEEDED;
-        set_output_buffer( writer, xmlbuf );
+        if (!(xmlbuf = alloc_xmlbuf( writer->output_heap ))) hr = WS_E_QUOTA_EXCEEDED;
+        else set_output_buffer( writer, xmlbuf );
         break;
     }
     default:
         FIXME( "output type %u not supported\n", output->outputType );
-        return E_NOTIMPL;
+        hr = E_NOTIMPL;
+        goto done;
     }
 
-    if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
-    write_insert_bof( writer, node );
-    return S_OK;
+    if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
+    else write_insert_bof( writer, node );
+
+done:
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 /**************************************************************************
@@ -387,19 +450,30 @@ HRESULT WINAPI WsSetOutputToBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer
 
     if (!writer || !xmlbuf) return E_INVALIDARG;
 
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
     for (i = 0; i < count; i++)
     {
         hr = prop_set( writer->prop, writer->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 = write_init_state( writer )) != S_OK) return hr;
+    if ((hr = init_writer( writer )) != S_OK) goto done;
     set_output_buffer( writer, xmlbuf );
 
-    if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
-    write_insert_bof( writer, node );
-    return S_OK;
+    if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) hr = E_OUTOFMEMORY;
+    else write_insert_bof( writer, node );
+
+done:
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_grow_buffer( struct writer *writer, ULONG size )
@@ -526,25 +600,40 @@ HRESULT WINAPI WsGetPrefixFromNamespace( WS_XML_WRITER *handle, const WS_XML_STR
     struct writer *writer = (struct writer *)handle;
     WS_XML_ELEMENT_NODE *elem;
     BOOL found = FALSE;
+    HRESULT hr = S_OK;
 
     TRACE( "%p %s %d %p %p\n", handle, debugstr_xmlstr(ns), required, prefix, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer || !ns || !prefix) return E_INVALIDARG;
 
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
     elem = &writer->current->hdr;
     if (elem->prefix && is_current_namespace( writer, ns ))
     {
         *prefix = elem->prefix;
         found = TRUE;
     }
+
     if (!found)
     {
-        if (required) return WS_E_INVALID_FORMAT;
-        *prefix = NULL;
-        return S_FALSE;
+        if (required) hr = WS_E_INVALID_FORMAT;
+        else
+        {
+            *prefix = NULL;
+            hr = S_FALSE;
+        }
     }
-    return S_OK;
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING *ns )
@@ -663,7 +752,17 @@ HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
 
     if (!writer) return E_INVALIDARG;
 
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
     writer->state = WRITER_STATE_STARTELEMENT;
+
+    LeaveCriticalSection( &writer->cs );
     return S_OK;
 }
 
@@ -783,12 +882,25 @@ static HRESULT write_endelement_node( struct writer *writer )
 HRESULT WINAPI WsWriteEndElement( WS_XML_WRITER *handle, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
 
     TRACE( "%p %p\n", handle, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    return write_endelement_node( writer );
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    hr = write_endelement_node( writer );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_endstartelement( struct writer *writer )
@@ -811,13 +923,28 @@ HRESULT WINAPI WsWriteEndStartElement( WS_XML_WRITER *handle, WS_ERROR *error )
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
 
-    if ((hr = write_set_element_namespace( writer )) != S_OK) return hr;
-    if ((hr = write_startelement( writer )) != S_OK) return hr;
-    if ((hr = write_endstartelement( writer )) != S_OK) return hr;
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
 
+    if (writer->state != WRITER_STATE_STARTELEMENT)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
+
+    if ((hr = write_set_element_namespace( writer )) != S_OK) goto done;
+    if ((hr = write_startelement( writer )) != S_OK) goto done;
+    if ((hr = write_endstartelement( writer )) != S_OK) goto done;
     writer->state = WRITER_STATE_ENDSTARTELEMENT;
+
+done:
+    LeaveCriticalSection( &writer->cs );
     return S_OK;
 }
 
@@ -873,10 +1000,24 @@ HRESULT WINAPI WsWriteStartAttribute( WS_XML_WRITER *handle, const WS_XML_STRING
 
     if (!writer || !localname || !ns) return E_INVALIDARG;
 
-    if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
+    EnterCriticalSection( &writer->cs );
 
-    if ((hr = write_add_attribute( writer, prefix, localname, ns, single )) != S_OK) return hr;
-    writer->state = WRITER_STATE_STARTATTRIBUTE;
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (writer->state != WRITER_STATE_STARTELEMENT)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
+
+    if ((hr = write_add_attribute( writer, prefix, localname, ns, single )) == S_OK)
+        writer->state = WRITER_STATE_STARTATTRIBUTE;
+
+    LeaveCriticalSection( &writer->cs );
     return S_OK;
 }
 
@@ -937,12 +1078,25 @@ static HRESULT write_cdata_node( struct writer *writer )
 HRESULT WINAPI WsWriteStartCData( WS_XML_WRITER *handle, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
 
     TRACE( "%p %p\n", handle, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    return write_cdata_node( writer );
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    hr = write_cdata_node( writer );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_endcdata( struct writer *writer )
@@ -968,14 +1122,31 @@ static HRESULT write_endcdata_node( struct writer *writer )
 HRESULT WINAPI WsWriteEndCData( WS_XML_WRITER *handle, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
 
     TRACE( "%p %p\n", handle, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    if (writer->state != WRITER_STATE_TEXT) return WS_E_INVALID_OPERATION;
 
-    return write_endcdata_node( writer );
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (writer->state != WRITER_STATE_TEXT)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
+
+    hr = write_endcdata_node( writer );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_add_element_node( struct writer *writer, const WS_XML_STRING *prefix,
@@ -1042,13 +1213,26 @@ HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *
                                     WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
 
     TRACE( "%p %s %s %s %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
            debugstr_xmlstr(ns), error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer || !localname || !ns) return E_INVALIDARG;
-    return write_element_node( writer, prefix, localname, ns );
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    hr = write_element_node( writer, prefix, localname, ns );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static ULONG format_bool( const BOOL *ptr, unsigned char *buf )
@@ -1479,13 +1663,25 @@ static HRESULT write_text_node( struct writer *writer, const WS_XML_TEXT *text )
 HRESULT WINAPI WsWriteText( WS_XML_WRITER *handle, const WS_XML_TEXT *text, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
 
     TRACE( "%p %p %p\n", handle, text, error );
 
     if (!writer || !text) return E_INVALIDARG;
 
-    if (writer->state == WRITER_STATE_STARTATTRIBUTE) return write_set_attribute_value( writer, text );
-    return write_text_node( writer, text );
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (writer->state == WRITER_STATE_STARTATTRIBUTE) hr = write_set_attribute_value( writer, text );
+    else hr = write_text_node( writer, text );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping, const WS_XML_TEXT *text )
@@ -2211,14 +2407,31 @@ HRESULT WINAPI WsWriteAttribute( WS_XML_WRITER *handle, const WS_ATTRIBUTE_DESCR
     if (!writer || !desc || !desc->attributeLocalName || !desc->attributeNs || !value)
         return E_INVALIDARG;
 
-    if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (writer->state != WRITER_STATE_STARTELEMENT)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
 
-    if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs,
-                                   FALSE )) != S_OK) return hr;
+    if ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs, FALSE )) != S_OK)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return hr;
+    }
     writer->state = WRITER_STATE_STARTATTRIBUTE;
 
-    return write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription,
-                       option, value, size );
+    hr = write_type( writer, WS_ATTRIBUTE_TYPE_MAPPING, desc->type, desc->typeDescription, option, value, size );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 /**************************************************************************
@@ -2237,12 +2450,24 @@ HRESULT WINAPI WsWriteElement( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTI
     if (!writer || !desc || !desc->elementLocalName || !desc->elementNs || !value)
         return E_INVALIDARG;
 
-    if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) return hr;
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) goto done;
 
     if ((hr = write_type( writer, WS_ANY_ELEMENT_TYPE_MAPPING, desc->type, desc->typeDescription,
-                          option, value, size )) != S_OK) return hr;
+                          option, value, size )) != S_OK) goto done;
+
+    hr = write_endelement_node( writer );
 
-    return write_endelement_node( writer );
+done:
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 /**************************************************************************
@@ -2261,17 +2486,25 @@ HRESULT WINAPI WsWriteType( WS_XML_WRITER *handle, WS_TYPE_MAPPING mapping, WS_T
 
     if (!writer || !value) return E_INVALIDARG;
 
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
     switch (mapping)
     {
     case WS_ATTRIBUTE_TYPE_MAPPING:
-        if (writer->state != WRITER_STATE_STARTATTRIBUTE) return WS_E_INVALID_FORMAT;
-        hr = write_type( writer, mapping, type, desc, option, value, size );
+        if (writer->state != WRITER_STATE_STARTATTRIBUTE) hr = WS_E_INVALID_FORMAT;
+        else hr = write_type( writer, mapping, type, desc, option, value, size );
         break;
 
     case WS_ELEMENT_TYPE_MAPPING:
     case WS_ELEMENT_CONTENT_TYPE_MAPPING:
-        if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_FORMAT;
-        hr = write_type( writer, mapping, type, desc, option, value, size );
+        if (writer->state != WRITER_STATE_STARTELEMENT) hr = WS_E_INVALID_FORMAT;
+        else hr = write_type( writer, mapping, type, desc, option, value, size );
         break;
 
     case WS_ANY_ELEMENT_TYPE_MAPPING:
@@ -2280,9 +2513,10 @@ HRESULT WINAPI WsWriteType( WS_XML_WRITER *handle, WS_TYPE_MAPPING mapping, WS_T
 
     default:
         FIXME( "mapping %u not implemented\n", mapping );
-        return E_NOTIMPL;
+        hr = E_NOTIMPL;
     }
 
+    LeaveCriticalSection( &writer->cs );
     return hr;
 }
 
@@ -2319,6 +2553,7 @@ HRESULT WINAPI WsWriteValue( WS_XML_WRITER *handle, WS_VALUE_TYPE value_type, co
 {
     struct writer *writer = (struct writer *)handle;
     WS_TYPE_MAPPING mapping;
+    HRESULT hr = S_OK;
     WS_TYPE type;
 
     TRACE( "%p %u %p %u %p\n", handle, value_type, value, size, error );
@@ -2326,6 +2561,14 @@ HRESULT WINAPI WsWriteValue( WS_XML_WRITER *handle, WS_VALUE_TYPE value_type, co
 
     if (!writer || !value || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG;
 
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
     switch (writer->state)
     {
     case WRITER_STATE_STARTATTRIBUTE:
@@ -2337,10 +2580,13 @@ HRESULT WINAPI WsWriteValue( WS_XML_WRITER *handle, WS_VALUE_TYPE value_type, co
         break;
 
     default:
-        return WS_E_INVALID_FORMAT;
+        hr = WS_E_INVALID_FORMAT;
     }
 
-    return write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size );
+    if (hr == S_OK) hr = write_type( writer, mapping, type, NULL, WS_WRITE_REQUIRED_VALUE, value, size );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 /**************************************************************************
@@ -2360,22 +2606,46 @@ HRESULT WINAPI WsWriteArray( WS_XML_WRITER *handle, const WS_XML_STRING *localna
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    if (!writer->output_type) return WS_E_INVALID_OPERATION;
-    if (!localname || !ns || (type = map_value_type( value_type )) == ~0u) return E_INVALIDARG;
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (!writer->output_type)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
+
+    if (!localname || !ns || (type = map_value_type( value_type )) == ~0u)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
 
     type_size = get_type_size( type, NULL );
-    if (size % type_size || (offset + count) * type_size > size || (count && !array)) return E_INVALIDARG;
+    if (size % type_size || (offset + count) * type_size > size || (count && !array))
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
 
     for (i = offset; i < count; i++)
     {
         const char *ptr = (const char *)array + (offset + i) * type_size;
-        if ((hr = write_element_node( writer, NULL, localname, ns )) != S_OK) return hr;
+        if ((hr = write_element_node( writer, NULL, localname, ns )) != S_OK) goto done;
         if ((hr = write_type( writer, WS_ELEMENT_TYPE_MAPPING, type, NULL, WS_WRITE_REQUIRED_POINTER,
-                              &ptr, sizeof(ptr) )) != S_OK) return hr;
-        if ((hr = write_endelement_node( writer )) != S_OK) return hr;
+                              &ptr, sizeof(ptr) )) != S_OK) goto done;
+        if ((hr = write_endelement_node( writer )) != S_OK) goto done;
     }
 
-    return S_OK;
+done:
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 /**************************************************************************
@@ -2392,9 +2662,20 @@ HRESULT WINAPI WsWriteXmlBuffer( WS_XML_WRITER *handle, WS_XML_BUFFER *buffer, W
 
     if (!writer || !xmlbuf) return E_INVALIDARG;
 
-    if ((hr = write_flush( writer )) != S_OK) return hr;
-    if ((hr = write_grow_buffer( writer, xmlbuf->size )) != S_OK) return hr;
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if ((hr = write_flush( writer )) != S_OK) goto done;
+    if ((hr = write_grow_buffer( writer, xmlbuf->size )) != S_OK) goto done;
     write_bytes( writer, xmlbuf->ptr, xmlbuf->size );
+
+done:
+    LeaveCriticalSection( &writer->cs );
     return S_OK;
 }
 
@@ -2408,7 +2689,7 @@ HRESULT WINAPI WsWriteXmlBufferToBytes( WS_XML_WRITER *handle, WS_XML_BUFFER *bu
 {
     struct writer *writer = (struct writer *)handle;
     struct xmlbuf *xmlbuf = (struct xmlbuf *)buffer;
-    HRESULT hr;
+    HRESULT hr = S_OK;
     char *buf;
     ULONG i;
 
@@ -2424,18 +2705,32 @@ HRESULT WINAPI WsWriteXmlBufferToBytes( WS_XML_WRITER *handle, WS_XML_BUFFER *bu
         return E_NOTIMPL;
     }
 
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
     for (i = 0; i < count; i++)
     {
         hr = prop_set( writer->prop, writer->prop_count, properties[i].id, properties[i].value,
                        properties[i].valueSize );
-        if (hr != S_OK) return hr;
+        if (hr != S_OK) goto done;
     }
 
-    if (!(buf = ws_alloc( heap, xmlbuf->size ))) return WS_E_QUOTA_EXCEEDED;
-    memcpy( buf, xmlbuf->ptr, xmlbuf->size );
-    *bytes = buf;
-    *size = xmlbuf->size;
-    return S_OK;
+    if (!(buf = ws_alloc( heap, xmlbuf->size ))) hr = WS_E_QUOTA_EXCEEDED;
+    else
+    {
+        memcpy( buf, xmlbuf->ptr, xmlbuf->size );
+        *bytes = buf;
+        *size = xmlbuf->size;
+    }
+
+done:
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 /**************************************************************************
@@ -2445,16 +2740,33 @@ HRESULT WINAPI WsWriteXmlnsAttribute( WS_XML_WRITER *handle, const WS_XML_STRING
                                       const WS_XML_STRING *ns, BOOL single, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr = S_OK;
 
     TRACE( "%p %s %s %d %p\n", handle, debugstr_xmlstr(prefix), debugstr_xmlstr(ns),
            single, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer || !ns) return E_INVALIDARG;
-    if (writer->state != WRITER_STATE_STARTELEMENT) return WS_E_INVALID_OPERATION;
 
-    if (namespace_in_scope( &writer->current->hdr, prefix, ns )) return S_OK;
-    return write_add_namespace_attribute( writer, prefix, ns, single );
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (writer->state != WRITER_STATE_STARTELEMENT)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
+
+    if (!namespace_in_scope( &writer->current->hdr, prefix, ns ))
+        hr = write_add_namespace_attribute( writer, prefix, ns, single );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_move_to( struct writer *writer, WS_MOVE_TO move, BOOL *found )
@@ -2534,14 +2846,31 @@ static HRESULT write_move_to( struct writer *writer, WS_MOVE_TO move, BOOL *foun
 HRESULT WINAPI WsMoveWriter( WS_XML_WRITER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
 
     TRACE( "%p %u %p %p\n", handle, move, found, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    if (!writer->output_type) return WS_E_INVALID_OPERATION;
 
-    return write_move_to( writer, move, found );
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (!writer->output_type)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
+
+    hr = write_move_to( writer, move, found );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 /**************************************************************************
@@ -2555,10 +2884,25 @@ HRESULT WINAPI WsGetWriterPosition( WS_XML_WRITER *handle, WS_XML_NODE_POSITION
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer || !pos) return E_INVALIDARG;
-    if (!writer->output_type) return WS_E_INVALID_OPERATION;
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (!writer->output_type)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
 
     pos->buffer = (WS_XML_BUFFER *)writer->output_buf;
     pos->node   = writer->current;
+
+    LeaveCriticalSection( &writer->cs );
     return S_OK;
 }
 
@@ -2572,10 +2916,25 @@ HRESULT WINAPI WsSetWriterPosition( WS_XML_WRITER *handle, const WS_XML_NODE_POS
     TRACE( "%p %p %p\n", handle, pos, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
-    if (!writer || !pos || (struct xmlbuf *)pos->buffer != writer->output_buf) return E_INVALIDARG;
-    if (!writer->output_type) return WS_E_INVALID_OPERATION;
+    if (!writer || !pos) return E_INVALIDARG;
+
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC || (struct xmlbuf *)pos->buffer != writer->output_buf)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (!writer->output_type)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
 
     writer->current = pos->node;
+
+    LeaveCriticalSection( &writer->cs );
     return S_OK;
 }
 
@@ -2683,14 +3042,31 @@ static HRESULT write_node( struct writer *writer, const WS_XML_NODE *node )
 HRESULT WINAPI WsWriteNode( WS_XML_WRITER *handle, const WS_XML_NODE *node, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
+    HRESULT hr;
 
     TRACE( "%p %p %p\n", handle, node, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer || !node) return E_INVALIDARG;
-    if (!writer->output_type) return WS_E_INVALID_OPERATION;
 
-    return write_node( writer, node );
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (!writer->output_type)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_OPERATION;
+    }
+
+    hr = write_node( writer, node );
+
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_tree_node( struct writer *writer )
@@ -2788,23 +3164,39 @@ static void write_rewind( struct writer *writer )
 HRESULT WINAPI WsCopyNode( WS_XML_WRITER *handle, WS_XML_READER *reader, WS_ERROR *error )
 {
     struct writer *writer = (struct writer *)handle;
-    struct node *parent, *current = writer->current, *node = NULL;
+    struct node *parent, *current, *node = NULL;
     HRESULT hr;
 
     TRACE( "%p %p %p\n", handle, reader, error );
     if (error) FIXME( "ignoring error parameter\n" );
 
     if (!writer) return E_INVALIDARG;
-    if (!(parent = find_parent( writer ))) return WS_E_INVALID_FORMAT;
 
-    if ((hr = copy_node( reader, &node )) != S_OK) return hr;
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if (!(parent = find_parent( writer )))
+    {
+        LeaveCriticalSection( &writer->cs );
+        return WS_E_INVALID_FORMAT;
+    }
+
+    if ((hr = copy_node( reader, &node )) != S_OK) goto done;
+    current = writer->current;
     write_insert_node( writer, parent, node );
 
     write_rewind( writer );
-    if ((hr = write_tree( writer )) != S_OK) return hr;
-
+    if ((hr = write_tree( writer )) != S_OK) goto done;
     writer->current = current;
-    return S_OK;
+
+done:
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
 
 static HRESULT write_param( struct writer *writer, const WS_FIELD_DESCRIPTION *desc, const void *value )
@@ -2842,7 +3234,15 @@ HRESULT write_input_params( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION
 
     if (desc->type != WS_STRUCT_TYPE || !(desc_struct = desc->typeDescription)) return E_INVALIDARG;
 
-    if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) return hr;
+    EnterCriticalSection( &writer->cs );
+
+    if (writer->magic != WRITER_MAGIC)
+    {
+        LeaveCriticalSection( &writer->cs );
+        return E_INVALIDARG;
+    }
+
+    if ((hr = write_element_node( writer, NULL, desc->elementLocalName, desc->elementNs )) != S_OK) goto done;
 
     for (i = 0; i < count; i++)
     {
@@ -2850,20 +3250,25 @@ HRESULT write_input_params( WS_XML_WRITER *handle, const WS_ELEMENT_DESCRIPTION
         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].inputMessageIndex, &desc_field )) != S_OK) return hr;
+        if ((hr = get_param_desc( desc_struct, params[i].inputMessageIndex, &desc_field )) != S_OK) goto done;
         if (params[i].parameterType == WS_PARAMETER_TYPE_NORMAL)
         {
-            if ((hr = write_param( writer, desc_field, args[i] )) != S_OK) return hr;
+            if ((hr = write_param( writer, desc_field, args[i] )) != S_OK) goto done;
         }
         else if (params[i].parameterType == WS_PARAMETER_TYPE_ARRAY)
         {
             const void *ptr = *(const void **)args[i];
             ULONG len = get_array_len( params, count, params[i].inputMessageIndex, args );
-            if ((hr = write_param_array( writer, desc_field, ptr, len )) != S_OK) return hr;
+            if ((hr = write_param_array( writer, desc_field, ptr, len )) != S_OK) goto done;
         }
     }
 
-    return write_endelement_node( writer );
+    hr = write_endelement_node( writer );
+
+done:
+    LeaveCriticalSection( &writer->cs );
+    return hr;
 }
-- 
2.1.4




More information about the wine-patches mailing list