Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/webservices/reader.c | 18 ++++++++++++------ dlls/webservices/tests/reader.c | 15 ++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index 7da0c8335ea..b22bcbd51b1 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -1486,8 +1486,9 @@ static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE GUID guid; HRESULT hr;
- if ((hr = read_byte( reader, &type )) != S_OK) return hr; + if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr; if (!is_text_type( type )) return WS_E_INVALID_FORMAT; + read_skip( reader, 1 );
switch (type) { @@ -1771,9 +1772,10 @@ static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret unsigned char type = 0; HRESULT hr;
- if ((hr = read_byte( reader, &type )) != S_OK) return hr; + if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr; if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT; if (!(attr = calloc( 1, sizeof(*attr) ))) return E_OUTOFMEMORY; + read_skip( reader, 1 );
if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z) { @@ -2068,8 +2070,9 @@ static HRESULT read_element_bin( struct reader *reader ) unsigned char type; HRESULT hr;
- if ((hr = read_byte( reader, &type )) != S_OK) return hr; + if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr; if (!is_element_type( type )) return WS_E_INVALID_FORMAT; + read_skip( reader, 1 );
if (!(elem = alloc_element_pair())) return E_OUTOFMEMORY; node = (struct node *)elem; @@ -2480,8 +2483,9 @@ static HRESULT read_text_bin( struct reader *reader ) GUID uuid; HRESULT hr;
- if ((hr = read_byte( reader, &type )) != S_OK) return hr; + if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr; if (!is_text_type( type ) || !(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT; + read_skip( reader, 1 );
switch (type) { @@ -2835,8 +2839,9 @@ static HRESULT read_endelement_bin( struct reader *reader )
if (!(reader->current->flags & NODE_FLAG_TEXT_WITH_IMPLICIT_END_ELEMENT)) { - if ((hr = read_byte( reader, &type )) != S_OK) return hr; + if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr; if (type != RECORD_ENDELEMENT) return WS_E_INVALID_FORMAT; + read_skip( reader, 1 ); } if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT;
@@ -2917,8 +2922,9 @@ static HRESULT read_comment_bin( struct reader *reader ) ULONG len; HRESULT hr;
- if ((hr = read_byte( reader, &type )) != S_OK) return hr; + if ((hr = read_peek( reader, &type, 1 )) != S_OK) return hr; if (type != RECORD_COMMENT) return WS_E_INVALID_FORMAT; + read_skip( reader, 1 ); if ((hr = read_int31( reader, &len )) != S_OK) return hr;
if (!(parent = find_parent( reader ))) return WS_E_INVALID_FORMAT; diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c index 1a2cd1fe420..f62697b9662 100644 --- a/dlls/webservices/tests/reader.c +++ b/dlls/webservices/tests/reader.c @@ -5764,15 +5764,12 @@ static void test_binary_encoding(void)
hr = WsReadType( reader, WS_ELEMENT_TYPE_MAPPING, WS_STRUCT_TYPE, &s, WS_READ_REQUIRED_POINTER, heap, &test_struct, sizeof(test_struct), NULL ); - todo_wine ok( hr == S_OK, "got %#lx\n", hr ); - if (SUCCEEDED(hr)) - { - ok( test_struct->a == 1, "got %d\n", test_struct->a ); - ok( !!test_struct->s, "s is not set\n" ); - ok( test_struct->s->s_a == 1, "got %d\n", test_struct->s->s_a ); - ok( test_struct->s->s_b == 0, "got %d\n", test_struct->s->s_b ); - ok( test_struct->b == 1, "got %d\n", test_struct->b ); - } + ok( hr == S_OK, "got %#lx\n", hr ); + ok( test_struct->a == 1, "got %d\n", test_struct->a ); + ok( !!test_struct->s, "s is not set\n" ); + ok( test_struct->s->s_a == 1, "got %d\n", test_struct->s->s_a ); + ok( test_struct->s->s_b == 0, "got %d\n", test_struct->s->s_b ); + ok( test_struct->b == 1, "got %d\n", test_struct->b );
WsFreeHeap( heap ); WsFreeReader( reader );
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/webservices/channel.c | 5 +++++ dlls/webservices/tests/channel.c | 28 +++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index 1148744346c..cfb6566921d 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -2415,6 +2415,11 @@ HRESULT WINAPI WsReceiveMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_M LeaveCriticalSection( &channel->cs ); return E_INVALIDARG; } + if (channel->state != WS_CHANNEL_STATE_OPEN) + { + LeaveCriticalSection( &channel->cs ); + return WS_E_INVALID_OPERATION; + }
if (!ctx) async_init( &async, &ctx_local ); hr = queue_receive_message( channel, msg, desc, count, option, read_option, heap, value, size, index, diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c index e3cadc7d344..f70eafaecc8 100644 --- a/dlls/webservices/tests/channel.c +++ b/dlls/webservices/tests/channel.c @@ -626,6 +626,7 @@ static void server_duplex_session( WS_CHANNEL *channel ) static void client_duplex_session( const struct listener_info *info ) { WS_XML_STRING action = {6, (BYTE *)"action"}, localname = {9, (BYTE *)"localname"}, ns = {2, (BYTE *)"ns"}; + const WS_MESSAGE_DESCRIPTION *descs[1]; WS_ELEMENT_DESCRIPTION desc_body; WS_MESSAGE_DESCRIPTION desc; WS_ENDPOINT_ADDRESS addr; @@ -645,6 +646,26 @@ static void client_duplex_session( const struct listener_info *info ) hr = WsShutdownSessionChannel( channel, NULL, NULL ); ok( hr == WS_E_INVALID_OPERATION, "got %#lx\n", hr );
+ desc_body.elementLocalName = &localname; + desc_body.elementNs = &ns; + desc_body.type = WS_INT32_TYPE; + desc_body.typeDescription = NULL; + desc.action = &action; + desc.bodyElementDescription = &desc_body; + descs[0] = &desc; + + hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = WsReceiveMessage( channel, msg, descs, 1, WS_RECEIVE_REQUIRED_MESSAGE, WS_READ_REQUIRED_VALUE, + NULL, &val, sizeof(val), NULL, NULL, NULL ); + ok( hr == WS_E_INVALID_OPERATION, "got %#lx\n", hr); + + hr = WsSendMessage( channel, msg, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL ); + ok( hr == WS_E_INVALID_OPERATION, "got %#lx\n", hr ); + + WsFreeMessage( msg ); + memset( &addr, 0, sizeof(addr) ); addr.url.length = wsprintfW( buf, L"net.tcp://localhost:%u", info->port ); addr.url.chars = buf; @@ -654,13 +675,6 @@ static void client_duplex_session( const struct listener_info *info ) hr = WsCreateMessageForChannel( channel, NULL, 0, &msg, NULL ); ok( hr == S_OK, "got %#lx\n", hr );
- desc_body.elementLocalName = &localname; - desc_body.elementNs = &ns; - desc_body.type = WS_INT32_TYPE; - desc_body.typeDescription = NULL; - desc.action = &action; - desc.bodyElementDescription = &desc_body; - hr = WsSendMessage( channel, msg, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL ); ok( hr == S_OK, "got %#lx\n", hr );
Treat WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE as a read-only property, and only allow it to be set upon channel creation.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/webservices/channel.c | 23 ++++++++++++++++++++++- dlls/webservices/tests/channel.c | 11 ++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index cfb6566921d..c78fd949f7b 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -40,7 +40,7 @@ static const struct prop_desc channel_props[] = { sizeof(WS_ENCODING), TRUE }, /* WS_CHANNEL_PROPERTY_ENCODING */ { sizeof(WS_ENVELOPE_VERSION), FALSE }, /* WS_CHANNEL_PROPERTY_ENVELOPE_VERSION */ { sizeof(WS_ADDRESSING_VERSION), FALSE }, /* WS_CHANNEL_PROPERTY_ADDRESSING_VERSION */ - { sizeof(ULONG), FALSE }, /* WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE */ + { sizeof(ULONG), TRUE }, /* WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE */ { sizeof(WS_CHANNEL_STATE), TRUE }, /* WS_CHANNEL_PROPERTY_STATE */ { sizeof(WS_CALLBACK_MODEL), FALSE }, /* WS_CHANNEL_PROPERTY_ASYNC_CALLBACK_MODEL */ { sizeof(WS_IP_VERSION), FALSE }, /* WS_CHANNEL_PROPERTY_IP_VERSION */ @@ -238,6 +238,7 @@ struct channel ULONG send_size; ULONG prop_count; struct prop prop[ARRAY_SIZE( channel_props )]; + ULONG session_dict_size; };
#define CHANNEL_MAGIC (('C' << 24) | ('H' << 16) | ('A' << 8) | 'N') @@ -483,6 +484,7 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding, case WS_TCP_CHANNEL_BINDING: channel->u.tcp.socket = -1; channel->encoding = WS_ENCODING_XML_BINARY_SESSION_1; + channel->session_dict_size = 2048; break;
case WS_UDP_CHANNEL_BINDING: @@ -534,6 +536,17 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding, break;
} + case WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE: + if (channel->binding != WS_TCP_CHANNEL_BINDING || !prop->value || + prop->valueSize != sizeof(channel->session_dict_size)) + { + free_channel( channel ); + return E_INVALIDARG; + } + + channel->session_dict_size = *(ULONG *)prop->value; + break; + default: if ((hr = prop_set( channel->prop, channel->prop_count, prop->id, prop->value, prop->valueSize )) != S_OK) { @@ -712,6 +725,14 @@ HRESULT WINAPI WsGetChannelProperty( WS_CHANNEL *handle, WS_CHANNEL_PROPERTY_ID else *(WS_CHANNEL_STATE *)buf = channel->state; break;
+ case WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE: + if (channel->binding != WS_TCP_CHANNEL_BINDING || !buf || + size != sizeof(channel->session_dict_size)) + hr = E_INVALIDARG; + else + *(ULONG *)buf = channel->session_dict_size; + break; + default: hr = prop_get( channel->prop, channel->prop_count, id, buf, size ); } diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c index f70eafaecc8..d5d35904c1c 100644 --- a/dlls/webservices/tests/channel.c +++ b/dlls/webservices/tests/channel.c @@ -66,6 +66,10 @@ static void test_WsCreateChannel(void) ok( hr == S_OK, "got %#lx\n", hr ); ok( addr_version == WS_ADDRESSING_VERSION_1_0, "got %u\n", addr_version );
+ size = 0xdeadbeef; + hr = WsGetChannelProperty( channel, WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE, &size, sizeof(size), NULL ); + ok( hr == E_INVALIDARG, "got %#lx\n", hr ); + /* read-only property */ state = 0xdeadbeef; hr = WsGetChannelProperty( channel, WS_CHANNEL_PROPERTY_STATE, &state, sizeof(state), NULL ); @@ -112,10 +116,15 @@ static void test_WsCreateChannel(void) ok( hr == S_OK, "got %#lx\n", hr ); ok( addr_version == WS_ADDRESSING_VERSION_1_0, "got %u\n", addr_version );
+ /* Read-only, only settable on channel creation. */ + size = 4096; + hr = WsSetChannelProperty( channel, WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE, &size, sizeof(size), NULL ); + ok( hr == E_INVALIDARG, "got %#lx\n", hr ); + size = 0xdeadbeef; hr = WsGetChannelProperty( channel, WS_CHANNEL_PROPERTY_MAX_SESSION_DICTIONARY_SIZE, &size, sizeof(size), NULL ); ok( hr == S_OK, "got %#lx\n", hr ); - todo_wine ok( size == 2048, "got %lu\n", size ); + ok( size == 2048, "got %lu\n", size );
WsFreeChannel( channel ); }
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/webservices/channel.c | 4 ++++ dlls/webservices/string.c | 3 +++ dlls/webservices/webservices_private.h | 2 ++ 3 files changed, 9 insertions(+)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index c78fd949f7b..22312f76aa1 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -485,6 +485,7 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding, channel->u.tcp.socket = -1; channel->encoding = WS_ENCODING_XML_BINARY_SESSION_1; channel->session_dict_size = 2048; + channel->dict_send.max_str_bytes = channel->session_dict_size; break;
case WS_UDP_CHANNEL_BINDING: @@ -545,6 +546,7 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding, }
channel->session_dict_size = *(ULONG *)prop->value; + channel->dict_send.max_str_bytes = channel->session_dict_size; break;
default: @@ -1617,6 +1619,7 @@ static HRESULT CALLBACK dict_cb( void *state, const WS_XML_STRING *str, BOOL *fo return S_OK; }
+ if ((str->length + dict->str_bytes + 1) > dict->max_str_bytes) goto exit; if (!(bytes = malloc( str->length ))) return E_OUTOFMEMORY; memcpy( bytes, str->bytes, str->length ); if ((hr = insert_string( dict, bytes, str->length, index, id )) == S_OK) @@ -1626,6 +1629,7 @@ static HRESULT CALLBACK dict_cb( void *state, const WS_XML_STRING *str, BOOL *fo } free( bytes );
+exit: *found = FALSE; return hr; } diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c index 3ecdcea85a4..c5e494b146a 100644 --- a/dlls/webservices/string.c +++ b/dlls/webservices/string.c @@ -145,6 +145,8 @@ void clear_dict( struct dictionary *dict ) dict->sequence = NULL; dict->current_sequence = 0; dict->size = 0; + dict->str_bytes = 0; + dict->max_str_bytes = 0; }
HRESULT insert_string( struct dictionary *dict, unsigned char *data, ULONG len, int i, ULONG *ret_id ) @@ -162,6 +164,7 @@ 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->str_bytes += len + 1;
dict->sequence[id] = dict->current_sequence;
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index b352aa52d49..46df8bfd1a9 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -49,6 +49,8 @@ struct dictionary ULONG size; ULONG current_sequence; ULONG *sequence; + ULONG str_bytes; + ULONG max_str_bytes; }; extern struct dictionary dict_builtin DECLSPEC_HIDDEN; extern const struct dictionary dict_builtin_static DECLSPEC_HIDDEN;
On Tue, 2022-04-19 at 19:34 -0400, Connor McAdams wrote:
diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c index 3ecdcea85a4..c5e494b146a 100644 --- a/dlls/webservices/string.c +++ b/dlls/webservices/string.c @@ -145,6 +145,8 @@ void clear_dict( struct dictionary *dict ) dict->sequence = NULL; dict->current_sequence = 0; dict->size = 0;
- dict->str_bytes = 0;
- dict->max_str_bytes = 0;
}
This is called indirectly from WsResetChannel(). Setting the maximum to 0 would render the dictionary useless since there's no way to set the maximum again.
On Wed, Apr 20, 2022 at 11:57:28AM +0200, Hans Leidekker wrote:
On Tue, 2022-04-19 at 19:34 -0400, Connor McAdams wrote:
diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c index 3ecdcea85a4..c5e494b146a 100644 --- a/dlls/webservices/string.c +++ b/dlls/webservices/string.c @@ -145,6 +145,8 @@ void clear_dict( struct dictionary *dict ) dict->sequence = NULL; dict->current_sequence = 0; dict->size = 0;
- dict->str_bytes = 0;
- dict->max_str_bytes = 0;
}
This is called indirectly from WsResetChannel(). Setting the maximum to 0 would render the dictionary useless since there's no way to set the maximum again.
Ah, yeah, good point. I guess I was thinking of 'clear_dict' as 'init_dict'. I'll fix this and send a new version of the final two patches.
On Wed, 2022-04-20 at 09:01 -0400, Connor McAdams wrote:
On Wed, Apr 20, 2022 at 11:57:28AM +0200, Hans Leidekker wrote:
On Tue, 2022-04-19 at 19:34 -0400, Connor McAdams wrote:
diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c index 3ecdcea85a4..c5e494b146a 100644 --- a/dlls/webservices/string.c +++ b/dlls/webservices/string.c @@ -145,6 +145,8 @@ void clear_dict( struct dictionary *dict ) dict->sequence = NULL; dict->current_sequence = 0; dict->size = 0;
- dict->str_bytes = 0;
- dict->max_str_bytes = 0;
}
This is called indirectly from WsResetChannel(). Setting the maximum to 0 would render the dictionary useless since there's no way to set the maximum again.
Ah, yeah, good point. I guess I was thinking of 'clear_dict' as 'init_dict'. I'll fix this and send a new version of the final two patches.
Right, then maybe rename it to 'init_dict' while you're at it?
On Wed, Apr 20, 2022 at 03:19:35PM +0200, Hans Leidekker wrote:
On Wed, 2022-04-20 at 09:01 -0400, Connor McAdams wrote:
On Wed, Apr 20, 2022 at 11:57:28AM +0200, Hans Leidekker wrote:
On Tue, 2022-04-19 at 19:34 -0400, Connor McAdams wrote:
diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c index 3ecdcea85a4..c5e494b146a 100644 --- a/dlls/webservices/string.c +++ b/dlls/webservices/string.c @@ -145,6 +145,8 @@ void clear_dict( struct dictionary *dict ) dict->sequence = NULL; dict->current_sequence = 0; dict->size = 0;
- dict->str_bytes = 0;
- dict->max_str_bytes = 0;
}
This is called indirectly from WsResetChannel(). Setting the maximum to 0 would render the dictionary useless since there's no way to set the maximum again.
Ah, yeah, good point. I guess I was thinking of 'clear_dict' as 'init_dict'. I'll fix this and send a new version of the final two patches.
Right, then maybe rename it to 'init_dict' while you're at it?
This makes sense. The only place it feels like it gets confusing is in 'build_dict', where it is used on failure cases.
If I rename it to 'init_dict', it might make sense to just pass the maximum session dictionary size as an argument then.
On Wed, 2022-04-20 at 09:58 -0400, Connor McAdams wrote:
On Wed, Apr 20, 2022 at 03:19:35PM +0200, Hans Leidekker wrote:
On Wed, 2022-04-20 at 09:01 -0400, Connor McAdams wrote:
On Wed, Apr 20, 2022 at 11:57:28AM +0200, Hans Leidekker wrote:
On Tue, 2022-04-19 at 19:34 -0400, Connor McAdams wrote:
diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c index 3ecdcea85a4..c5e494b146a 100644 --- a/dlls/webservices/string.c +++ b/dlls/webservices/string.c @@ -145,6 +145,8 @@ void clear_dict( struct dictionary *dict ) dict->sequence = NULL; dict->current_sequence = 0; dict->size = 0;
- dict->str_bytes = 0;
- dict->max_str_bytes = 0;
}
This is called indirectly from WsResetChannel(). Setting the maximum to 0 would render the dictionary useless since there's no way to set the maximum again.
Ah, yeah, good point. I guess I was thinking of 'clear_dict' as 'init_dict'. I'll fix this and send a new version of the final two patches.
Right, then maybe rename it to 'init_dict' while you're at it?
This makes sense. The only place it feels like it gets confusing is in 'build_dict', where it is used on failure cases.
If I rename it to 'init_dict', it might make sense to just pass the maximum session dictionary size as an argument then.
Yeah.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/webservices/channel.c | 23 ++++++++++++++++++++++- dlls/webservices/tests/channel.c | 17 +++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index 22312f76aa1..d14f9390381 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -486,6 +486,7 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding, channel->encoding = WS_ENCODING_XML_BINARY_SESSION_1; channel->session_dict_size = 2048; channel->dict_send.max_str_bytes = channel->session_dict_size; + channel->dict_recv.max_str_bytes = channel->session_dict_size; break;
case WS_UDP_CHANNEL_BINDING: @@ -547,6 +548,7 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding,
channel->session_dict_size = *(ULONG *)prop->value; channel->dict_send.max_str_bytes = channel->session_dict_size; + channel->dict_recv.max_str_bytes = channel->session_dict_size; break;
default: @@ -899,6 +901,7 @@ HRESULT WINAPI WsShutdownSessionChannel( WS_CHANNEL *handle, const WS_ASYNC_CONT if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -1597,6 +1600,7 @@ HRESULT channel_send_message( WS_CHANNEL *handle, WS_MESSAGE *msg ) if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -1786,6 +1790,7 @@ HRESULT WINAPI WsSendMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_MESS if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -1832,6 +1837,7 @@ HRESULT WINAPI WsSendReplyMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -2198,6 +2204,11 @@ static HRESULT build_dict( const BYTE *buf, ULONG buflen, struct dictionary *dic clear_dict( dict ); return WS_E_INVALID_FORMAT; } + if ((size + dict->str_bytes + 1) > dict->max_str_bytes) + { + hr = WS_E_QUOTA_EXCEEDED; + goto error; + } buflen -= size; if (!(bytes = malloc( size ))) { @@ -2243,7 +2254,11 @@ static HRESULT receive_message_bytes_session( struct channel *channel ) { ULONG size; if ((hr = build_dict( (const BYTE *)channel->read_buf, channel->read_size, &channel->dict_recv, - &size )) != S_OK) return hr; + &size )) != S_OK) + { + if (hr == WS_E_QUOTA_EXCEEDED) channel->state = WS_CHANNEL_STATE_FAULTED; + return hr; + } channel->read_size -= size; memmove( channel->read_buf, channel->read_buf + size, channel->read_size ); } @@ -2303,6 +2318,7 @@ HRESULT channel_receive_message( WS_CHANNEL *handle, WS_MESSAGE *msg ) if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -2443,6 +2459,7 @@ HRESULT WINAPI WsReceiveMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_M if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -2561,6 +2578,7 @@ HRESULT WINAPI WsRequestReply( WS_CHANNEL *handle, WS_MESSAGE *request, const WS if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -2645,6 +2663,7 @@ HRESULT WINAPI WsReadMessageStart( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -2797,6 +2816,7 @@ HRESULT WINAPI WsWriteMessageStart( WS_CHANNEL *handle, WS_MESSAGE *msg, const W if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
@@ -2877,6 +2897,7 @@ HRESULT WINAPI WsWriteMessageEnd( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_ if (channel->state != WS_CHANNEL_STATE_OPEN) { LeaveCriticalSection( &channel->cs ); + if (channel->state == WS_CHANNEL_STATE_FAULTED) return WS_E_OBJECT_FAULTED; return WS_E_INVALID_OPERATION; }
diff --git a/dlls/webservices/tests/channel.c b/dlls/webservices/tests/channel.c index d5d35904c1c..7e0a9becbc5 100644 --- a/dlls/webservices/tests/channel.c +++ b/dlls/webservices/tests/channel.c @@ -822,6 +822,7 @@ static void client_duplex_session_dict( const struct listener_info *info ) WS_MESSAGE_DESCRIPTION desc; WS_ENDPOINT_ADDRESS addr; WS_CHANNEL_PROPERTY prop; + WS_CHANNEL_STATE state; int dict_str_cnt = 0; char elem_name[128]; WS_CHANNEL *channel; @@ -893,12 +894,24 @@ static void client_duplex_session_dict( const struct listener_info *info ) local_name.bytes = (BYTE *)short_dict_str; hr = WsReceiveMessage( channel, msg, descs, 1, WS_RECEIVE_REQUIRED_MESSAGE, WS_READ_REQUIRED_VALUE, NULL, &val, sizeof(val), NULL, NULL, NULL ); - todo_wine ok( hr == WS_E_QUOTA_EXCEEDED, "got %#lx\n", hr); + ok( hr == WS_E_QUOTA_EXCEEDED, "got %#lx\n", hr); + + state = 0xdeadbeef; + hr = WsGetChannelProperty( channel, WS_CHANNEL_PROPERTY_STATE, &state, sizeof(state), NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + ok( state == WS_CHANNEL_STATE_FAULTED, "got %u\n", state ); + + hr = WsReceiveMessage( channel, msg, descs, 1, WS_RECEIVE_REQUIRED_MESSAGE, WS_READ_REQUIRED_VALUE, + NULL, &val, sizeof(val), NULL, NULL, NULL ); + ok( hr == WS_E_OBJECT_FAULTED, "got %#lx\n", hr ); + + hr = WsSendMessage( channel, msg, &desc, WS_WRITE_REQUIRED_VALUE, &val, sizeof(val), NULL, NULL ); + ok( hr == WS_E_OBJECT_FAULTED, "got %#lx\n", hr );
WsFreeMessage( msg );
hr = WsShutdownSessionChannel( channel, NULL, NULL ); - todo_wine ok( hr == WS_E_OBJECT_FAULTED, "got %#lx\n", hr ); + ok( hr == WS_E_OBJECT_FAULTED, "got %#lx\n", hr );
hr = WsCloseChannel( channel, NULL, NULL ); ok( hr == S_OK, "got %#lx\n", hr );