diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index 79d431f2797..5963faf00de 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -1009,22 +1009,26 @@ static inline ULONG size_length( ULONG size ) return 5; } -static ULONG string_table_size( const WS_XML_DICTIONARY *dict ) +static ULONG string_table_size( const struct dictionary *dict ) { ULONG i, size = 0; - for (i = 0; i < dict->stringCount; i++) - size += size_length( dict->strings[i].length ) + dict->strings[i].length; + for (i = 0; i < dict->dict.stringCount; i++) + { + if (dict->sequence[i] == dict->current_sequence) + size += size_length( dict->dict.strings[i].length ) + dict->dict.strings[i].length; + } return size; } -static HRESULT send_string_table( SOCKET socket, const WS_XML_DICTIONARY *dict ) +static HRESULT send_string_table( SOCKET socket, const struct dictionary *dict ) { ULONG i; HRESULT hr; - for (i = 0; i < dict->stringCount; i++) + for (i = 0; i < dict->dict.stringCount; i++) { - if ((hr = send_size( socket, dict->strings[i].length )) != S_OK) return hr; - if ((hr = send_bytes( socket, dict->strings[i].bytes, dict->strings[i].length )) != S_OK) return hr; + if (dict->sequence[i] != dict->current_sequence) continue; + if ((hr = send_size( socket, dict->dict.strings[i].length )) != S_OK) return hr; + if ((hr = send_bytes( socket, dict->dict.strings[i].bytes, dict->dict.strings[i].length )) != S_OK) return hr; } return S_OK; } @@ -1154,13 +1158,13 @@ static HRESULT receive_preamble_ack( struct channel *channel ) static HRESULT send_sized_envelope( struct channel *channel, BYTE *data, ULONG len ) { - ULONG table_size = string_table_size( &channel->dict_send.dict ); + ULONG table_size = string_table_size( &channel->dict_send ); HRESULT hr; if ((hr = send_byte( channel->u.tcp.socket, FRAME_RECORD_TYPE_SIZED_ENVELOPE )) != S_OK) return hr; if ((hr = send_size( channel->u.tcp.socket, size_length(table_size) + table_size + len )) != S_OK) return hr; if ((hr = send_size( channel->u.tcp.socket, table_size )) != S_OK) return hr; - if ((hr = send_string_table( channel->u.tcp.socket, &channel->dict_send.dict )) != S_OK) return hr; + if ((hr = send_string_table( channel->u.tcp.socket, &channel->dict_send )) != S_OK) return hr; return send_bytes( channel->u.tcp.socket, data, len ); } @@ -1285,11 +1289,8 @@ static HRESULT init_writer( struct channel *channel ) return WsSetOutput( channel->writer, &text.encoding, &buf.output, NULL, 0, NULL ); case WS_ENCODING_XML_BINARY_SESSION_1: - clear_dict( &channel->dict_send ); - bin.staticDictionary = (WS_XML_DICTIONARY *)&dict_builtin_static.dict; - bin.dynamicStringCallback = dict_cb; - bin.dynamicStringCallbackState = &channel->dict_send; - return WsSetOutput( channel->writer, &bin.encoding, &buf.output, NULL, 0, NULL ); + bin.staticDictionary = (WS_XML_DICTIONARY *)&dict_builtin_static.dict; + /* fall through */ case WS_ENCODING_XML_BINARY_1: return WsSetOutput( channel->writer, &bin.encoding, &buf.output, NULL, 0, NULL ); @@ -1307,6 +1308,8 @@ static HRESULT write_message( struct channel *channel, WS_MESSAGE *msg, const WS if ((hr = writer_set_lookup( channel->writer, TRUE )) != S_OK) return hr; if ((hr = WsWriteEnvelopeStart( msg, channel->writer, NULL, NULL, NULL )) != S_OK) return hr; if ((hr = writer_set_lookup( channel->writer, FALSE )) != S_OK) return hr; + channel->dict_send.current_sequence++; + if ((hr = writer_set_dict_callback( channel->writer, dict_cb, &channel->dict_send )) != S_OK) return hr; if ((hr = WsWriteBody( msg, desc, option, body, size, NULL )) != S_OK) return hr; return WsWriteEnvelopeEnd( msg, NULL ); } diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c index 18c55e3833f..0bb77df9463 100644 --- a/dlls/webservices/string.c +++ b/dlls/webservices/string.c @@ -91,7 +91,7 @@ int find_string( const struct dictionary *dict, const unsigned char *data, ULONG static HRESULT grow_dict( struct dictionary *dict, ULONG size ) { WS_XML_STRING *tmp; - ULONG new_size, *tmp_sorted; + ULONG new_size, *tmp_sorted, *tmp_sequence; assert( !dict->dict.isConst ); if (dict->size >= dict->dict.stringCount + size) return S_OK; @@ -107,6 +107,14 @@ static HRESULT grow_dict( struct dictionary *dict, ULONG size ) dict->dict.strings = NULL; return E_OUTOFMEMORY; } + if (!(dict->sequence = heap_alloc( new_size * sizeof(*dict->sequence) ))) + { + heap_free( dict->dict.strings ); + dict->dict.strings = NULL; + heap_free( dict->sorted ); + dict->sorted = NULL; + return E_OUTOFMEMORY; + } dict->size = new_size; return S_OK; } @@ -116,6 +124,8 @@ static HRESULT grow_dict( struct dictionary *dict, ULONG size ) dict->dict.strings = tmp; if (!(tmp_sorted = heap_realloc( dict->sorted, new_size * sizeof(*tmp_sorted) ))) return E_OUTOFMEMORY; dict->sorted = tmp_sorted; + if (!(tmp_sequence = heap_realloc( dict->sequence, new_size * sizeof(*tmp_sequence) ))) return E_OUTOFMEMORY; + dict->sequence = tmp_sequence; dict->size = new_size; return S_OK; @@ -131,6 +141,9 @@ void clear_dict( struct dictionary *dict ) dict->dict.stringCount = 0; heap_free( dict->sorted ); dict->sorted = NULL; + heap_free( dict->sequence ); + dict->sequence = NULL; + dict->current_sequence = 0; dict->size = 0; } @@ -149,6 +162,9 @@ HRESULT insert_string( struct dictionary *dict, unsigned char *data, ULONG len, dict->dict.strings[id].dictionary = &dict->dict; dict->dict.strings[id].id = id; dict->dict.stringCount++; + + dict->sequence[id] = dict->current_sequence; + if (ret_id) *ret_id = id; return S_OK; } diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index bfc3202a640..d981527bb24 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -43,6 +43,8 @@ struct dictionary WS_XML_DICTIONARY dict; ULONG *sorted; ULONG size; + ULONG current_sequence; + ULONG *sequence; }; struct dictionary dict_builtin DECLSPEC_HIDDEN; const struct dictionary dict_builtin_static DECLSPEC_HIDDEN; @@ -51,6 +53,7 @@ int find_string( const struct dictionary *, const unsigned char *, ULONG, ULONG HRESULT insert_string( struct dictionary *, unsigned char *, ULONG, int, ULONG * ) DECLSPEC_HIDDEN; void clear_dict( struct dictionary * ) DECLSPEC_HIDDEN; HRESULT writer_set_lookup( WS_XML_WRITER *, BOOL ) DECLSPEC_HIDDEN; +HRESULT writer_set_dict_callback( WS_XML_WRITER *, WS_DYNAMIC_STRING_CALLBACK, void * ) DECLSPEC_HIDDEN; const char *debugstr_xmlstr( const WS_XML_STRING * ) DECLSPEC_HIDDEN; WS_XML_STRING *alloc_xml_string( const unsigned char *, ULONG ) DECLSPEC_HIDDEN; diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index b3d130a52cb..95d4caddb9c 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -4866,3 +4866,22 @@ HRESULT writer_set_lookup( WS_XML_WRITER *handle, BOOL enable ) LeaveCriticalSection( &writer->cs ); return S_OK; } + +HRESULT writer_set_dict_callback( WS_XML_WRITER *handle, WS_DYNAMIC_STRING_CALLBACK cb, void *state ) +{ + struct writer *writer = (struct writer *)handle; + + EnterCriticalSection( &writer->cs ); + + if (writer->magic != WRITER_MAGIC) + { + LeaveCriticalSection( &writer->cs ); + return E_INVALIDARG; + } + + writer->dict_cb = cb; + writer->dict_cb_state = state; + + LeaveCriticalSection( &writer->cs ); + return S_OK; +}