diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index 852cfdbfcd4..20cbacef376 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 ((hr = write_add_attribute( writer, NULL, desc->attributeLocalName, desc->attributeNs, - FALSE )) != S_OK) return hr; + 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) + { + 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; - return write_endelement_node( writer ); + hr = 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; }