From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/reader.c | 164 +++++++++++++++++++++++++++++++- dlls/webservices/tests/reader.c | 40 ++++++++ 2 files changed, 203 insertions(+), 1 deletion(-)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index b22bcbd51b1..b28a5cc107c 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -4312,7 +4312,7 @@ static BOOL match_element( const struct node *node, const WS_XML_STRING *localna const WS_XML_ELEMENT_NODE *elem = (const WS_XML_ELEMENT_NODE *)node; if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE; return WsXmlStringEquals( localname, elem->localName, NULL ) == S_OK && - WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK; + (!ns || WsXmlStringEquals( ns, elem->ns, NULL ) == S_OK); }
static HRESULT read_next_node( struct reader *reader ) @@ -6507,6 +6507,164 @@ static HRESULT read_type_struct( struct reader *reader, WS_TYPE_MAPPING mapping, return S_OK; }
+static HRESULT read_type_fault( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname, + const WS_XML_STRING *ns, const WS_FAULT_DESCRIPTION *desc, WS_READ_OPTION option, + WS_HEAP *heap, void *ret, ULONG size, BOOL *found ) +{ + static const WS_XML_STRING faultcode = {9, (BYTE *)"faultcode"}, faultstring = {11, (BYTE *)"faultstring"}; + static const WS_XML_STRING faultactor = {10, (BYTE *)"faultactor"}, detail = {6, (BYTE *)"detail"}; + + const struct node *root = reader->current; + WS_FAULT *fault; + HRESULT hr = S_OK; + + if (mapping != WS_ELEMENT_TYPE_MAPPING || !desc || !ret) + return E_INVALIDARG; + if (desc->envelopeVersion < WS_ENVELOPE_VERSION_SOAP_1_1 || desc->envelopeVersion >= WS_ENVELOPE_VERSION_NONE) + return E_INVALIDARG; + else if (desc->envelopeVersion != WS_ENVELOPE_VERSION_SOAP_1_1) + { + FIXME( "unhandled envelopeVersion %u\n", desc->envelopeVersion ); + return E_NOTIMPL; + } + + switch (option) + { + case WS_READ_REQUIRED_VALUE: + if (size != sizeof(*fault)) + return E_INVALIDARG; + fault = ret; + memset( fault, 0, sizeof(*fault) ); + break; + + case WS_READ_REQUIRED_POINTER: + case WS_READ_OPTIONAL_POINTER: + case WS_READ_NILLABLE_POINTER: + if (size != sizeof(void *)) + return E_INVALIDARG; + if (!(fault = ws_alloc_zero( heap, sizeof(*fault) ))) + return WS_E_QUOTA_EXCEEDED; + break; + + case WS_READ_NILLABLE_VALUE: + return E_INVALIDARG; + + default: + FIXME( "unhandled read option %u\n", option ); + return E_NOTIMPL; + } + + if ((hr = read_type_next_node( reader )) != S_OK) goto done; + for (;;) + { + if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT && reader->current->parent == root) + break; + + if (match_element( reader->current, &faultcode, ns )) + { + if (fault->code) + { + hr = WS_E_INVALID_FORMAT; + break; + } + if (!(fault->code = ws_alloc_zero( heap, sizeof(*fault->code) ))) + { + hr = WS_E_QUOTA_EXCEEDED; + break; + } + if ((hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, WS_XML_QNAME_TYPE, NULL, NULL, + NULL, WS_READ_REQUIRED_VALUE, heap, &fault->code->value, + sizeof(fault->code->value), found )) != S_OK) + break; + + } + else if (match_element( reader->current, &faultstring, ns )) + { + if (fault->reasons) + { + hr = WS_E_INVALID_FORMAT; + break; + } + if (!(fault->reasons = ws_alloc_zero( heap, sizeof(*fault->reasons) ))) + { + hr = WS_E_QUOTA_EXCEEDED; + break; + } + fault->reasonCount = 1; + /* FIXME: parse optional xml:lang attribute */ + if ((hr = read_next_node( reader )) != S_OK || + (hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, NULL, + NULL, WS_READ_REQUIRED_VALUE, heap, &fault->reasons->text, + sizeof(fault->reasons->text), found )) != S_OK) + break; + } + else if (match_element( reader->current, &faultactor, ns )) + { + if (fault->actor.length > 0) + { + hr = WS_E_INVALID_FORMAT; + break; + } + if ((hr = read_next_node( reader )) != S_OK || + (hr = read_type( reader, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, NULL, + NULL, WS_READ_REQUIRED_VALUE, heap, &fault->actor, + sizeof(fault->actor), found )) != S_OK) + break; + } + else if (match_element( reader->current, &detail, ns )) + { + if (fault->detail) + { + hr = WS_E_INVALID_FORMAT; + break; + } + if ((hr = WsReadXmlBuffer( (WS_XML_READER *)reader, heap, &fault->detail, NULL )) != S_OK) + break; + } + else if ((hr = read_type_next_node( reader )) != S_OK) + break; + } + +done: + if ((!fault->code || !fault->reasons) && hr == S_OK) + hr = WS_E_INVALID_FORMAT; + + if (hr != S_OK) + { + free_fault_fields( heap, fault ); + + switch (option) + { + case WS_READ_REQUIRED_VALUE: + case WS_READ_REQUIRED_POINTER: + memset( fault, 0, sizeof(*fault) ); + break; + + case WS_READ_OPTIONAL_POINTER: + case WS_READ_NILLABLE_POINTER: + if (hr == WS_E_INVALID_FORMAT && is_nil_value( (const char *)fault, sizeof(*fault) )) + { + ws_free( heap, fault, sizeof(*fault) ); + fault = NULL; + hr = S_OK; + } + else + memset( fault, 0, sizeof(*fault) ); + break; + + default: + ERR( "unhandled option %u\n", option ); + return E_NOTIMPL; + } + } + + if (option != WS_READ_REQUIRED_VALUE) + *(WS_FAULT **)ret = fault; + + *found = TRUE; + return hr; +} + static HRESULT start_mapping( struct reader *reader, WS_TYPE_MAPPING mapping, const WS_XML_STRING *localname, const WS_XML_STRING *ns ) { @@ -6698,6 +6856,10 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size, found ); break;
+ case WS_FAULT_TYPE: + hr = read_type_fault( reader, mapping, localname, ns, desc, option, heap, value, size, found ); + break; + case WS_ENUM_TYPE: hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size, found ); break; diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c index 2ade3c3d4b1..d370c2ebe75 100644 --- a/dlls/webservices/tests/reader.c +++ b/dlls/webservices/tests/reader.c @@ -1355,6 +1355,8 @@ static void test_WsReadNode(void) WsFreeReader( reader ); }
+static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line ); + static void prepare_type_test( WS_XML_READER *reader, const char *data, ULONG size ) { HRESULT hr; @@ -1373,6 +1375,15 @@ static void test_WsReadType(void) { static const GUID guid = {0,0,0,{0,0,0,0,0,0,0,0xa1}}; static const char utf8[] = {'<','t','>',0xe2,0x80,0x99,'<','/','t','>'}; + static const char faultxml[] = + "<s:Body xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Fault>" + "<faultcode>s:Client</faultcode><faultstring>Example Fault</faultstring>" + "<faultactor>http://example.com/fault</faultactor>" + "<detail><ErrorCode>1030</ErrorCode></detail></s:Fault></s:Body>"; + static const char faultcode[] = "Client"; + static const WCHAR faultstring[] = L"Example Fault"; + static const WCHAR faultactor[] = L"http://example.com/fault"; + static const char faultdetail[] = "<detail><ErrorCode>1030</ErrorCode></detail>"; HRESULT hr; WS_XML_READER *reader; WS_HEAP *heap; @@ -1396,6 +1407,8 @@ static void test_WsReadType(void) WS_STRING val_string, *ptr_string; WS_UNIQUE_ID val_id, *ptr_id; WS_XML_QNAME val_qname, *ptr_qname; + WS_FAULT_DESCRIPTION fault_desc; + WS_FAULT fault;
hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL ); ok( hr == S_OK, "got %#lx\n", hr ); @@ -1920,6 +1933,33 @@ static void test_WsReadType(void) WS_READ_REQUIRED_POINTER, heap, &ptr_qname, sizeof(ptr_qname), NULL ); ok( hr == WS_E_INVALID_FORMAT, "got %#lx\n", hr );
+ prepare_type_test( reader, faultxml, sizeof(faultxml) - 1 ); + hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + memset( &fault, 0, sizeof(fault) ); + + fault_desc.envelopeVersion = WS_ENVELOPE_VERSION_SOAP_1_1; + hr = WsReadType( reader, WS_ELEMENT_TYPE_MAPPING, WS_FAULT_TYPE, &fault_desc, + WS_READ_REQUIRED_VALUE, heap, &fault, sizeof(fault), NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + ok( fault.code->value.localName.length == sizeof(faultcode) - 1, "got %lu\n", fault.code->value.localName.length ); + ok( !memcmp( fault.code->value.localName.bytes, faultcode, sizeof(faultcode) - 1 ), "wrong fault code\n" ); + ok( !fault.code->subCode, "subcode is not NULL\n" ); + ok( fault.reasonCount == 1, "got %lu\n", fault.reasonCount ); + ok( fault.reasons[0].text.length == ARRAY_SIZE(faultstring) - 1, "got %lu\n", fault.reasons[0].text.length ); + ok( !memcmp( fault.reasons[0].text.chars, faultstring, (ARRAY_SIZE(faultstring) - 1) * sizeof(WCHAR) ), + "wrong fault string\n" ); + ok( fault.actor.length == ARRAY_SIZE(faultactor) - 1, "got %lu\n", fault.actor.length ); + ok( !memcmp( fault.actor.chars, faultactor, ARRAY_SIZE(faultactor) - 1 ), "wrong fault actor\n" ); + ok( !fault.node.length, "fault node not empty\n" ); + ok( fault.detail != NULL, "fault detail not set\n" ); + check_output_buffer( fault.detail, faultdetail, __LINE__ ); + + fault_desc.envelopeVersion = WS_ENVELOPE_VERSION_NONE; + hr = WsReadType( reader, WS_ELEMENT_TYPE_MAPPING, WS_FAULT_TYPE, &fault_desc, + WS_READ_REQUIRED_VALUE, heap, &fault, sizeof(fault), NULL ); + ok( hr == E_INVALIDARG, "got %#lx\n", hr ); + WsFreeReader( reader ); WsFreeHeap( heap ); }
From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/msg.c | 36 +++++++++++++++++++++++++++++++++++- dlls/webservices/tests/msg.c | 21 ++++++++++++++++++++- include/webservices.h | 15 +++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c index 98d43660957..f61fc337f0f 100644 --- a/dlls/webservices/msg.c +++ b/dlls/webservices/msg.c @@ -42,6 +42,10 @@ static const struct prop_desc msg_props[] = { sizeof(WS_XML_READER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_READER */ { sizeof(WS_XML_WRITER *), TRUE }, /* WS_MESSAGE_PROPERTY_BODY_WRITER */ { sizeof(BOOL), TRUE }, /* WS_MESSAGE_PROPERTY_IS_ADDRESSED */ + { sizeof(WS_HEAP_PROPERTIES), TRUE }, /* WS_MESSAGE_PROPERTY_HEAP_PROPERTIES */ + { sizeof(WS_XML_READER_PROPERTIES), TRUE }, /* WS_MESSAGE_PROPERTY_XML_READER_PROPERTIES */ + { sizeof(WS_XML_WRITER_PROPERTIES), TRUE }, /* WS_MESSAGE_PROPERTY_XML_WRITER_PROPERTIES */ + { sizeof(BOOL), FALSE }, /* WS_MESSAGE_PROPERTY_IS_FAULT */ };
struct header @@ -122,6 +126,7 @@ static void free_header( struct header *header )
static void reset_msg( struct msg *msg ) { + BOOL isfault = FALSE; ULONG i;
msg->state = WS_MESSAGE_STATE_EMPTY; @@ -150,6 +155,8 @@ static void reset_msg( struct msg *msg )
memset( &msg->ctx_send, 0, sizeof(msg->ctx_send) ); memset( &msg->ctx_receive, 0, sizeof(msg->ctx_receive) ); + + prop_set( msg->prop, msg->prop_count, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(BOOL) ); }
static void free_msg( struct msg *msg ) @@ -375,6 +382,13 @@ HRESULT WINAPI WsGetMessageProperty( WS_MESSAGE *handle, WS_MESSAGE_PROPERTY_ID else *(BOOL *)buf = msg->is_addressed; break;
+ case WS_MESSAGE_PROPERTY_HEAP_PROPERTIES: + case WS_MESSAGE_PROPERTY_XML_READER_PROPERTIES: + case WS_MESSAGE_PROPERTY_XML_WRITER_PROPERTIES: + FIXME( "property %u not supported\n", id ); + hr = E_NOTIMPL; + break; + default: hr = prop_get( msg->prop, msg->prop_count, id, buf, size ); } @@ -877,6 +891,18 @@ static BOOL match_current_element( WS_XML_READER *reader, const WS_XML_STRING *l return WsXmlStringEquals( elem->localName, localname, NULL ) == S_OK; }
+static BOOL match_current_element_with_ns( WS_XML_READER *reader, const WS_XML_STRING *localname, const WS_XML_STRING *ns ) +{ + const WS_XML_NODE *node; + const WS_XML_ELEMENT_NODE *elem; + + if (WsGetReaderNode( reader, &node, NULL ) != S_OK) return FALSE; + if (node->nodeType != WS_XML_NODE_TYPE_ELEMENT) return FALSE; + elem = (const WS_XML_ELEMENT_NODE *)node; + return WsXmlStringEquals( elem->localName, localname, NULL ) == S_OK && + WsXmlStringEquals( elem->ns, ns, NULL ) == S_OK; +} + static HRESULT read_message_id( WS_XML_READER *reader, GUID *ret ) { const WS_XML_NODE *node; @@ -914,6 +940,9 @@ static HRESULT read_envelope_start( struct msg *msg, WS_XML_READER *reader ) { static const WS_XML_STRING envelope = {8, (BYTE *)"Envelope"}, body = {4, (BYTE *)"Body"}; static const WS_XML_STRING header = {6, (BYTE *)"Header"}, msgid = {9, (BYTE *)"MessageID"}; + static const WS_XML_STRING fault = {5, (BYTE *)"Fault"}; + const WS_XML_STRING *ns_env = get_env_namespace( msg->version_env ); + BOOL isfault; HRESULT hr;
if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr; @@ -930,7 +959,12 @@ static HRESULT read_envelope_start( struct msg *msg, WS_XML_READER *reader ) } } if (!match_current_element( reader, &body )) return WS_E_INVALID_FORMAT; - return WsReadNode( reader, NULL ); + if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr; + + isfault = match_current_element_with_ns( reader, &fault, ns_env ); + hr = prop_set( msg->prop, msg->prop_count, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(BOOL) ); + + return hr; }
/************************************************************************** diff --git a/dlls/webservices/tests/msg.c b/dlls/webservices/tests/msg.c index 2af2dd334e7..feeedc940d5 100644 --- a/dlls/webservices/tests/msg.c +++ b/dlls/webservices/tests/msg.c @@ -1071,10 +1071,14 @@ static void test_WsReadEnvelopeStart(void) { static const char xml[] = "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body/></s:Envelope>"; - WS_MESSAGE *msg, *msg2; + static const char faultxml[] = + "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body>" + "<s:Fault/></s:Body></s:Envelope>"; + WS_MESSAGE *msg, *msg2, *msg3; WS_XML_READER *reader; WS_MESSAGE_STATE state; const WS_XML_NODE *node; + BOOL isfault; HRESULT hr;
hr = WsReadEnvelopeStart( NULL, NULL, NULL, NULL, NULL ); @@ -1127,8 +1131,23 @@ static void test_WsReadEnvelopeStart(void) ok( hr == S_OK, "got %#lx\n", hr ); ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
+ hr = WsCreateMessage( WS_ENVELOPE_VERSION_SOAP_1_1, WS_ADDRESSING_VERSION_0_9, NULL, 0, &msg3, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = set_input( reader, faultxml, strlen(faultxml) ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = WsReadEnvelopeStart( msg3, reader, NULL, NULL, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + isfault = FALSE; + hr = WsGetMessageProperty( msg3, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(isfault), NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + ok( isfault, "isfault == FALSE\n" ); + WsFreeMessage( msg ); WsFreeMessage( msg2 ); + WsFreeMessage( msg3 ); WsFreeReader( reader ); }
diff --git a/include/webservices.h b/include/webservices.h index 6657ee84201..bda09e06bc8 100644 --- a/include/webservices.h +++ b/include/webservices.h @@ -113,6 +113,11 @@ typedef struct _WS_HEAP_PROPERTY { ULONG valueSize; } WS_HEAP_PROPERTY;
+typedef struct _WS_HEAP_PROPERTIES { + WS_HEAP_PROPERTY *properties; + ULONG propertyCount; +} WS_HEAP_PROPERTIES; + typedef ULONG WS_XML_BUFFER_PROPERTY_ID;
typedef struct _WS_XML_BUFFER_PROPERTY { @@ -145,6 +150,11 @@ typedef struct _WS_XML_READER_PROPERTY { ULONG valueSize; } WS_XML_READER_PROPERTY;
+typedef struct _WS_XML_READER_PROPERTIES { + WS_XML_READER_PROPERTY *properties; + ULONG propertyCount; +} WS_XML_READER_PROPERTIES; + typedef enum { WS_XML_WRITER_PROPERTY_MAX_DEPTH, WS_XML_WRITER_PROPERTY_ALLOW_FRAGMENT, @@ -173,6 +183,11 @@ typedef struct _WS_XML_WRITER_PROPERTY { ULONG valueSize; } WS_XML_WRITER_PROPERTY;
+typedef struct _WS_XML_WRITER_PROPERTIES { + WS_XML_WRITER_PROPERTY *properties; + ULONG propertyCount; +} WS_XML_WRITER_PROPERTIES; + typedef struct _WS_BYTES { ULONG length; BYTE *bytes;
From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/msg.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c index f61fc337f0f..37d40c423d4 100644 --- a/dlls/webservices/msg.c +++ b/dlls/webservices/msg.c @@ -1044,6 +1044,8 @@ HRESULT WINAPI WsReadBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *des WS_HEAP *heap, void *value, ULONG size, WS_ERROR *error ) { struct msg *msg = (struct msg *)handle; + WS_ELEMENT_DESCRIPTION tmp; + WS_FAULT_DESCRIPTION fault_desc; HRESULT hr;
TRACE( "%p %p %u %p %p %lu %p\n", handle, desc, option, heap, value, size, error ); @@ -1060,7 +1062,23 @@ HRESULT WINAPI WsReadBody( WS_MESSAGE *handle, const WS_ELEMENT_DESCRIPTION *des }
if (msg->state != WS_MESSAGE_STATE_READING) hr = WS_E_INVALID_OPERATION; - else hr = WsReadElement( msg->reader_body, desc, option, heap, value, size, NULL ); + else + { + if (!desc->typeDescription) + { + if (desc->type == WS_FAULT_TYPE) + { + memcpy( &tmp, desc, sizeof(*desc) ); + fault_desc.envelopeVersion = msg->version_env; + tmp.typeDescription = &fault_desc; + desc = &tmp; + } + else if (desc->type == WS_ENDPOINT_ADDRESS_TYPE) + FIXME( "!desc->typeDescription with WS_ENDPOINT_ADDRESS_TYPE\n" ); + } + + hr = WsReadElement( msg->reader_body, desc, option, heap, value, size, NULL ); + }
LeaveCriticalSection( &msg->cs ); TRACE( "returning %#lx\n", hr );
From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/tests/msg.c | 47 ++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/dlls/webservices/tests/msg.c b/dlls/webservices/tests/msg.c index feeedc940d5..b1c0237dc3f 100644 --- a/dlls/webservices/tests/msg.c +++ b/dlls/webservices/tests/msg.c @@ -1202,19 +1202,27 @@ static void test_WsReadBody(void) static const char xml[] = "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body>" "<u xmlns="ns"><val>1</val></u></s:Body></s:Envelope>"; + static const char faultxml[] = + "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body>" + "<s:Fault><faultcode>s:Client</faultcode><faultstring>OLS Exception</faultstring></s:Fault>" + "</s:Body></s:Envelope>"; + static const WS_XML_STRING faultcode = { 6, (BYTE *)"Client" }; + static const WS_STRING faultstring = { 13, (WCHAR *)L"OLS Exception" }; WS_HEAP *heap; - WS_MESSAGE *msg, *msg2; + WS_MESSAGE *msg, *msg2, *msg3; WS_XML_READER *reader; WS_MESSAGE_STATE state; + BOOL isfault; WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}; WS_XML_STRING val = {3, (BYTE *)"val"}, ns = {2, (BYTE *)"ns"}; - WS_ELEMENT_DESCRIPTION desc; + WS_ELEMENT_DESCRIPTION desc, faultdesc; WS_STRUCT_DESCRIPTION s; WS_FIELD_DESCRIPTION f, *fields[1]; struct test { UINT32 val; } test; + WS_FAULT fault; HRESULT hr;
hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL ); @@ -1280,8 +1288,43 @@ static void test_WsReadBody(void) hr = WsReadEnvelopeEnd( msg2, NULL ); ok( hr == S_OK, "got %#lx\n", hr );
+ hr = WsCreateMessage( WS_ENVELOPE_VERSION_SOAP_1_1, WS_ADDRESSING_VERSION_0_9, NULL, 0, &msg3, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = set_input( reader, faultxml, strlen(faultxml) ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = WsReadEnvelopeStart( msg3, reader, NULL, NULL, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + isfault = FALSE; + hr = WsGetMessageProperty( msg3, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(isfault), NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + ok( isfault, "isfault == FALSE\n" ); + + faultdesc.elementLocalName = NULL; + faultdesc.elementNs = NULL; + faultdesc.type = WS_FAULT_TYPE; + faultdesc.typeDescription = NULL; + + memset( &fault, 0, sizeof(fault) ); + hr = WsReadBody( msg3, &faultdesc, WS_READ_REQUIRED_VALUE, heap, &fault, sizeof(fault), NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + ok( fault.code->value.localName.length == faultcode.length, "got %lu\n", fault.code->value.localName.length ); + ok( !memcmp( fault.code->value.localName.bytes, faultcode.bytes, faultcode.length ), "wrong fault code\n" ); + ok( !fault.code->subCode, "subcode is not NULL\n" ); + ok( fault.reasonCount == 1, "got %lu\n", fault.reasonCount ); + ok( fault.reasons[0].text.length == faultstring.length, "got %lu\n", fault.reasons[0].text.length ); + ok( !memcmp( fault.reasons[0].text.chars, faultstring.chars, faultstring.length * sizeof(WCHAR) ), + "wrong fault string\n" ); + + hr = WsReadEnvelopeEnd( msg3, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + WsFreeMessage( msg ); WsFreeMessage( msg2 ); + WsFreeMessage( msg3 ); WsFreeReader( reader ); WsFreeHeap( heap ); }
From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/channel.c | 6 ++++++ dlls/webservices/proxy.c | 1 + dlls/webservices/webservices_private.h | 1 + 3 files changed, 8 insertions(+)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index 4c9f9c4ccff..968110d56bd 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -3041,3 +3041,9 @@ HRESULT channel_accept_udp( SOCKET socket, HANDLE wait, HANDLE cancel, WS_CHANNE LeaveCriticalSection( &channel->cs ); return hr; } + +HRESULT channel_address_message( WS_CHANNEL *handle, WS_MESSAGE *msg ) +{ + struct channel *channel = (struct channel *)handle; + return WsAddressMessage( msg, &channel->addr, NULL ); +} diff --git a/dlls/webservices/proxy.c b/dlls/webservices/proxy.c index 09f6e2bee00..3a8baade8dd 100644 --- a/dlls/webservices/proxy.c +++ b/dlls/webservices/proxy.c @@ -426,6 +426,7 @@ static HRESULT send_message( WS_CHANNEL *channel, WS_MESSAGE *msg, WS_MESSAGE_DE WS_XML_WRITER *writer; HRESULT hr;
+ if ((hr = channel_address_message( channel, msg )) != S_OK) return hr; if ((hr = message_set_action( msg, desc->action )) != S_OK) return hr; if ((hr = WsCreateWriter( NULL, 0, &writer, NULL )) != S_OK) return hr; if ((hr = set_output( writer )) != S_OK) goto done; diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index d7f62c3d8a6..a2f89d47d7a 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -168,6 +168,7 @@ HRESULT message_map_http_response_headers( WS_MESSAGE *, HINTERNET, const WS_HTT HRESULT channel_send_message( WS_CHANNEL *, WS_MESSAGE * ) DECLSPEC_HIDDEN; HRESULT channel_receive_message( WS_CHANNEL *, WS_MESSAGE * ) DECLSPEC_HIDDEN; HRESULT channel_get_reader( WS_CHANNEL *, WS_XML_READER ** ) DECLSPEC_HIDDEN; +HRESULT channel_address_message( WS_CHANNEL *, WS_MESSAGE * ) DECLSPEC_HIDDEN;
HRESULT parse_url( const WS_STRING *, WS_URL_SCHEME_TYPE *, WCHAR **, USHORT * ) DECLSPEC_HIDDEN;
From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/msg.c | 41 ++++++++++++++++++++++++++ dlls/webservices/webservices_private.h | 1 + 2 files changed, 42 insertions(+)
diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c index 37d40c423d4..996a47f1cd5 100644 --- a/dlls/webservices/msg.c +++ b/dlls/webservices/msg.c @@ -2261,3 +2261,44 @@ HRESULT message_set_request_id( WS_MESSAGE *handle, const GUID *id ) LeaveCriticalSection( &msg->cs ); return hr; } + +/* Attempt to read a fault message. If the message is a fault, WS_E_ENDPOINT_FAULT_RECEIVED will be returned. */ +HRESULT message_read_fault( WS_MESSAGE *handle, WS_HEAP *heap, WS_ERROR *error ) +{ + static const WS_ELEMENT_DESCRIPTION desc = { NULL, NULL, WS_FAULT_TYPE, NULL }; + BOOL isfault; + WS_FAULT fault = {0}; + WS_XML_STRING action; + HRESULT hr; + + if ((hr = WsGetMessageProperty( handle, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(isfault), NULL )) != S_OK) + return hr; + if (!isfault) + return S_OK; + + if ((hr = WsReadBody( handle, &desc, WS_READ_REQUIRED_VALUE, heap, &fault, sizeof(fault), NULL )) != S_OK || + (hr = WsReadEnvelopeEnd( handle, NULL )) != S_OK) + goto done; + + if (!error) goto done; + + if ((hr = WsSetFaultErrorProperty( error, WS_FAULT_ERROR_PROPERTY_FAULT, &fault, sizeof(fault) )) != S_OK) + goto done; + + if ((hr = WsGetHeader( handle, WS_ACTION_HEADER, WS_XML_STRING_TYPE, WS_READ_REQUIRED_VALUE, + heap, &action, sizeof(action), NULL )) != S_OK) + { + if (hr == WS_E_INVALID_FORMAT) + { + memset( &action, 0, sizeof(action) ); + hr = S_OK; + } + else + goto done; + } + hr = WsSetFaultErrorProperty( error, WS_FAULT_ERROR_PROPERTY_ACTION, &action, sizeof(action) ); + +done: + free_fault_fields( heap, &fault ); + return hr != S_OK ? hr : WS_E_ENDPOINT_FAULT_RECEIVED; +} diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index a2f89d47d7a..478f1aa00f3 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -164,6 +164,7 @@ void message_do_send_callback( WS_MESSAGE * ) DECLSPEC_HIDDEN; void message_do_receive_callback( WS_MESSAGE * ) DECLSPEC_HIDDEN; HRESULT message_insert_http_headers( WS_MESSAGE *, HINTERNET ) DECLSPEC_HIDDEN; HRESULT message_map_http_response_headers( WS_MESSAGE *, HINTERNET, const WS_HTTP_MESSAGE_MAPPING * ) DECLSPEC_HIDDEN; +HRESULT message_read_fault( WS_MESSAGE *, WS_HEAP *, WS_ERROR * ) DECLSPEC_HIDDEN;
HRESULT channel_send_message( WS_CHANNEL *, WS_MESSAGE * ) DECLSPEC_HIDDEN; HRESULT channel_receive_message( WS_CHANNEL *, WS_MESSAGE * ) DECLSPEC_HIDDEN;
From: Shaun Ren sren@codeweavers.com
Signed-off-by: Shaun Ren sren@codeweavers.com --- dlls/webservices/channel.c | 30 ++++++----- dlls/webservices/proxy.c | 12 ++--- dlls/webservices/tests/proxy.c | 96 ++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 19 deletions(-)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c index 968110d56bd..5851fd9d4af 100644 --- a/dlls/webservices/channel.c +++ b/dlls/webservices/channel.c @@ -2354,17 +2354,18 @@ HRESULT channel_get_reader( WS_CHANNEL *handle, WS_XML_READER **reader ) }
static HRESULT read_message( WS_MESSAGE *handle, WS_XML_READER *reader, const WS_ELEMENT_DESCRIPTION *desc, - WS_READ_OPTION option, WS_HEAP *heap, void *body, ULONG size ) + WS_READ_OPTION option, WS_HEAP *heap, void *body, ULONG size, WS_ERROR *error ) { HRESULT hr; if ((hr = WsReadEnvelopeStart( handle, reader, NULL, NULL, NULL )) != S_OK) return hr; + if ((hr = message_read_fault( handle, heap, error )) != S_OK) return hr; if ((hr = WsReadBody( handle, desc, option, heap, body, size, NULL )) != S_OK) return hr; return WsReadEnvelopeEnd( handle, NULL ); }
static HRESULT receive_message( struct channel *channel, WS_MESSAGE *msg, const WS_MESSAGE_DESCRIPTION **desc, ULONG count, WS_RECEIVE_OPTION option, WS_READ_OPTION read_option, WS_HEAP *heap, - void *value, ULONG size, ULONG *index ) + void *value, ULONG size, ULONG *index, WS_ERROR *error ) { HRESULT hr; ULONG i; @@ -2375,7 +2376,7 @@ static HRESULT receive_message( struct channel *channel, WS_MESSAGE *msg, const for (i = 0; i < count; i++) { const WS_ELEMENT_DESCRIPTION *body = desc[i]->bodyElementDescription; - if ((hr = read_message( msg, channel->reader, body, read_option, heap, value, size )) == S_OK) + if ((hr = read_message( msg, channel->reader, body, read_option, heap, value, size, error )) == S_OK) { if (index) *index = i; break; @@ -2404,6 +2405,7 @@ struct receive_message ULONG size; ULONG *index; WS_ASYNC_CONTEXT ctx; + WS_ERROR *error; };
static void receive_message_proc( struct task *task ) @@ -2412,7 +2414,7 @@ static void receive_message_proc( struct task *task ) HRESULT hr;
hr = receive_message( r->channel, r->msg, r->desc, r->count, r->option, r->read_option, r->heap, r->value, - r->size, r->index ); + r->size, r->index, r->error );
TRACE( "calling %p(%#lx)\n", r->ctx.callback, hr ); r->ctx.callback( hr, WS_LONG_CALLBACK, r->ctx.callbackState ); @@ -2422,7 +2424,7 @@ static void receive_message_proc( struct task *task ) static HRESULT queue_receive_message( struct channel *channel, WS_MESSAGE *msg, const WS_MESSAGE_DESCRIPTION **desc, ULONG count, WS_RECEIVE_OPTION option, WS_READ_OPTION read_option, WS_HEAP *heap, void *value, ULONG size, ULONG *index, - const WS_ASYNC_CONTEXT *ctx ) + const WS_ASYNC_CONTEXT *ctx, WS_ERROR *error ) { struct receive_message *r;
@@ -2439,6 +2441,7 @@ static HRESULT queue_receive_message( struct channel *channel, WS_MESSAGE *msg, r->size = size; r->index = index; r->ctx = *ctx; + r->error = error; return queue_task( &channel->recv_q, &r->task ); }
@@ -2456,7 +2459,6 @@ HRESULT WINAPI WsReceiveMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_M
TRACE( "%p %p %p %lu %u %u %p %p %lu %p %p %p\n", handle, msg, desc, count, option, read_option, heap, value, size, index, ctx, error ); - if (error) FIXME( "ignoring error parameter\n" );
if (!channel || !msg || !desc || !count) return E_INVALIDARG;
@@ -2475,7 +2477,7 @@ HRESULT WINAPI WsReceiveMessage( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_M
if (!ctx) async_init( &async, &ctx_local ); hr = queue_receive_message( channel, msg, desc, count, option, read_option, heap, value, size, index, - ctx ? ctx : &ctx_local ); + ctx ? ctx : &ctx_local, error ); if (!ctx) { if (hr == WS_S_ASYNC) hr = async_wait( &async ); @@ -2491,7 +2493,7 @@ static HRESULT request_reply( struct channel *channel, WS_MESSAGE *request, const WS_MESSAGE_DESCRIPTION *request_desc, WS_WRITE_OPTION write_option, const void *request_body, ULONG request_size, WS_MESSAGE *reply, const WS_MESSAGE_DESCRIPTION *reply_desc, WS_READ_OPTION read_option, - WS_HEAP *heap, void *value, ULONG size ) + WS_HEAP *heap, void *value, ULONG size, WS_ERROR *error ) { HRESULT hr;
@@ -2499,7 +2501,7 @@ static HRESULT request_reply( struct channel *channel, WS_MESSAGE *request, return hr;
return receive_message( channel, reply, &reply_desc, 1, WS_RECEIVE_OPTIONAL_MESSAGE, read_option, heap, - value, size, NULL ); + value, size, NULL, error ); }
struct request_reply @@ -2518,6 +2520,7 @@ struct request_reply void *value; ULONG size; WS_ASYNC_CONTEXT ctx; + WS_ERROR *error; };
static void request_reply_proc( struct task *task ) @@ -2526,7 +2529,7 @@ static void request_reply_proc( struct task *task ) HRESULT hr;
hr = request_reply( r->channel, r->request, r->request_desc, r->write_option, r->request_body, r->request_size, - r->reply, r->reply_desc, r->read_option, r->heap, r->value, r->size ); + r->reply, r->reply_desc, r->read_option, r->heap, r->value, r->size, r->error );
TRACE( "calling %p(%#lx)\n", r->ctx.callback, hr ); r->ctx.callback( hr, WS_LONG_CALLBACK, r->ctx.callbackState ); @@ -2537,7 +2540,8 @@ static HRESULT queue_request_reply( struct channel *channel, WS_MESSAGE *request const WS_MESSAGE_DESCRIPTION *request_desc, WS_WRITE_OPTION write_option, const void *request_body, ULONG request_size, WS_MESSAGE *reply, const WS_MESSAGE_DESCRIPTION *reply_desc, WS_READ_OPTION read_option, - WS_HEAP *heap, void *value, ULONG size, const WS_ASYNC_CONTEXT *ctx ) + WS_HEAP *heap, void *value, ULONG size, const WS_ASYNC_CONTEXT *ctx, + WS_ERROR *error ) { struct request_reply *r;
@@ -2556,6 +2560,7 @@ static HRESULT queue_request_reply( struct channel *channel, WS_MESSAGE *request r->value = value; r->size = size; r->ctx = *ctx; + r->error = error; return queue_task( &channel->recv_q, &r->task ); }
@@ -2574,7 +2579,6 @@ HRESULT WINAPI WsRequestReply( WS_CHANNEL *handle, WS_MESSAGE *request, const WS
TRACE( "%p %p %p %u %p %lu %p %p %u %p %p %lu %p %p\n", handle, request, request_desc, write_option, request_body, request_size, reply, reply_desc, read_option, heap, value, size, ctx, error ); - if (error) FIXME( "ignoring error parameter\n" );
if (!channel || !request || !reply) return E_INVALIDARG;
@@ -2595,7 +2599,7 @@ HRESULT WINAPI WsRequestReply( WS_CHANNEL *handle, WS_MESSAGE *request, const WS
if (!ctx) async_init( &async, &ctx_local ); hr = queue_request_reply( channel, request, request_desc, write_option, request_body, request_size, reply, - reply_desc, read_option, heap, value, size, ctx ? ctx : &ctx_local ); + reply_desc, read_option, heap, value, size, ctx ? ctx : &ctx_local, error ); if (!ctx) { if (hr == WS_S_ASYNC) hr = async_wait( &async ); diff --git a/dlls/webservices/proxy.c b/dlls/webservices/proxy.c index 3a8baade8dd..bde4cdb168f 100644 --- a/dlls/webservices/proxy.c +++ b/dlls/webservices/proxy.c @@ -440,17 +440,19 @@ done:
static HRESULT read_message( WS_MESSAGE *msg, WS_XML_READER *reader, WS_HEAP *heap, const WS_ELEMENT_DESCRIPTION *desc, const WS_PARAMETER_DESCRIPTION *params, - ULONG count, const void **args ) + ULONG count, const void **args, WS_ERROR *error ) { HRESULT hr; if ((hr = WsReadEnvelopeStart( msg, reader, NULL, NULL, NULL )) != S_OK) return hr; message_do_receive_callback( msg ); + if ((hr = message_read_fault( msg, heap, error )) != S_OK) return hr; if ((hr = read_output_params( reader, heap, desc, params, count, args )) != S_OK) return hr; return WsReadEnvelopeEnd( msg, NULL ); }
static HRESULT receive_message( WS_CHANNEL *channel, WS_MESSAGE *msg, WS_MESSAGE_DESCRIPTION *desc, - WS_PARAMETER_DESCRIPTION *params, ULONG count, WS_HEAP *heap, const void **args ) + WS_PARAMETER_DESCRIPTION *params, ULONG count, + WS_HEAP *heap, const void **args, WS_ERROR *error ) { WS_XML_READER *reader; HRESULT hr; @@ -458,7 +460,7 @@ static HRESULT receive_message( WS_CHANNEL *channel, WS_MESSAGE *msg, WS_MESSAGE if ((hr = message_set_action( msg, desc->action )) != S_OK) return hr; if ((hr = channel_receive_message( channel, msg )) != S_OK) return hr; if ((hr = channel_get_reader( channel, &reader )) != S_OK) return hr; - return read_message( msg, reader, heap, desc->bodyElementDescription, params, count, args ); + return read_message( msg, reader, heap, desc->bodyElementDescription, params, count, args, error ); }
static HRESULT create_input_message( WS_CHANNEL *channel, const WS_CALL_PROPERTY *properties, @@ -507,7 +509,6 @@ HRESULT WINAPI WsCall( WS_SERVICE_PROXY *handle, const WS_OPERATION_DESCRIPTION ULONG i;
TRACE( "%p %p %p %p %p %lu %p %p\n", handle, desc, args, heap, properties, count, ctx, error ); - if (error) FIXME( "ignoring error parameter\n" ); if (ctx) FIXME( "ignoring ctx parameter\n" ); for (i = 0; i < count; i++) { @@ -532,13 +533,12 @@ HRESULT WINAPI WsCall( WS_SERVICE_PROXY *handle, const WS_OPERATION_DESCRIPTION if ((hr = create_input_message( proxy->channel, properties, count, &msg )) != S_OK) goto done; if ((hr = send_message( proxy->channel, msg, desc->inputMessageDescription, desc->parameterDescription, desc->parameterCount, args )) != S_OK) goto done; - WsFreeMessage( msg ); msg = NULL;
if ((hr = create_output_message( proxy->channel, properties, count, &msg )) != S_OK) goto done; hr = receive_message( proxy->channel, msg, desc->outputMessageDescription, desc->parameterDescription, - desc->parameterCount, heap, args ); + desc->parameterCount, heap, args, error );
done: WsFreeMessage( msg ); diff --git a/dlls/webservices/tests/proxy.c b/dlls/webservices/tests/proxy.c index f03ae7b9844..59d571fb5c3 100644 --- a/dlls/webservices/tests/proxy.c +++ b/dlls/webservices/tests/proxy.c @@ -796,7 +796,101 @@ static void test_inout_params( int port ) WsFreeHeap( heap ); }
+static const char req_test5[] = + "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body>" + "<req_test5 xmlns="ns"><val>1</val></req_test5>" + "</s:Body></s:Envelope>"; + +static const char resp_test5[] = + "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/%5C%22%3E<s:Body>" + "<s:Fault><faultcode>s:Client</faultcode><faultstring>OLS Exception</faultstring><detail>" + "<ServerFault xmlns="http://schemas.microsoft.com/office/licensingservice/API/2012/01/ClientApi%5..." " + "xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Office.LicensingService%5C" " + "xmlns:i="http://www.w3.org/2001/XMLSchema-instance%5C%22%3E<a:ErrorCode>1030</a:ErrorCode><a:Message/>" + "<a:Url>https://portal.office.com/Account/#installs</a:Url></ServerFault></detail>" + "</s:Fault></s:Body></s:Envelope>"; + +static void test_fault_response( int port ) +{ + WS_XML_STRING faultcode = {6, (BYTE *)"Client"}; + WS_STRING faultstring = {13, (WCHAR *)L"OLS Exception"}; + WS_XML_STRING req = {3, (BYTE *)"req"}; + WS_XML_STRING resp = {4, (BYTE *)"resp"}; + WS_XML_STRING req_action = {9, (BYTE *)"req_test5"}; + WS_XML_STRING resp_action = {10, (BYTE *)"resp_test5"}; + WS_XML_STRING req_elem = {9, (BYTE *)"req_test5"}; + WS_XML_STRING resp_elem = {10, (BYTE *)"resp_test5"}; + WS_XML_STRING ns = {2, (BYTE *)"ns"}; + WS_XML_STRING ns2 = {0, (BYTE *)""}; + WS_XML_STRING val = {3, (BYTE *)"val"}; + HRESULT hr; + WS_SERVICE_PROXY *proxy; + WS_FIELD_DESCRIPTION f, *fields[1]; + WS_STRUCT_DESCRIPTION input_struct, output_struct; + WS_ELEMENT_DESCRIPTION input_elem, output_elem; + WS_MESSAGE_DESCRIPTION input_msg, output_msg; + WS_PARAMETER_DESCRIPTION param[1]; + WS_OPERATION_DESCRIPTION op; + const void *args[1]; + WS_HEAP *heap; + struct input + { + INT32 val; + } in; + WS_ERROR *error; + WS_FAULT *fault; + + hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = create_proxy( port, &proxy ); + ok( hr == S_OK, "got %#lx\n", hr ); + + set_field_desc( &f, WS_ELEMENT_FIELD_MAPPING, &val, &ns, WS_INT32_TYPE, NULL, 0, 0, 0, NULL, NULL ); + fields[0] = &f; + + set_struct_desc( &input_struct, sizeof(struct input), TYPE_ALIGNMENT(struct input), fields, 1, &req, &ns, 0 ); + set_elem_desc( &input_elem, &req_elem, &ns, WS_STRUCT_TYPE, &input_struct ); + set_msg_desc( &input_msg, &req_action, &input_elem ); + + set_struct_desc( &output_struct, 0, 1, NULL, 0, &resp, &ns2, 0x6 ); + set_elem_desc( &output_elem, &resp_elem, &ns, WS_STRUCT_TYPE, &output_struct ); + set_msg_desc( &output_msg, &resp_action, &output_elem ); + + set_param_desc( param, WS_PARAMETER_TYPE_NORMAL, 0, 0xffff ); + set_op_desc( &op, &input_msg, &output_msg, 1, param ); + + in.val = 1; + args[0] = &in.val; + + hr = WsCreateError( NULL, 0, &error ); + ok( hr == S_OK, "got %#lx\n", hr ); + + hr = WsCall( proxy, &op, args, heap, NULL, 0, NULL, error ); + ok( hr == WS_E_ENDPOINT_FAULT_RECEIVED, "got %#lx\n", hr ); + + hr = WsGetFaultErrorProperty( error, WS_FAULT_ERROR_PROPERTY_FAULT, &fault, sizeof(fault) ); + ok( hr == S_OK, "got %#lx\n", hr ); + ok( fault != NULL, "fault not set\n" ); + ok( fault->code->value.localName.length == faultcode.length, "got %lu\n", fault->code->value.localName.length ); + ok( !memcmp( fault->code->value.localName.bytes, faultcode.bytes, faultcode.length ), "wrong fault code\n" ); + ok( !fault->code->subCode, "subcode is not NULL\n" ); + ok( fault->reasonCount == 1, "got %lu\n", fault->reasonCount ); + ok( fault->reasons[0].text.length == faultstring.length, "got %lu\n", fault->reasons[0].text.length ); + ok( !memcmp( fault->reasons[0].text.chars, faultstring.chars, faultstring.length * sizeof(WCHAR) ), + "wrong fault string\n" ); + ok( fault->detail != NULL, "fault detail not set\n" ); + + hr = WsCloseServiceProxy( proxy, NULL, NULL ); + ok( hr == S_OK, "got %#lx\n", hr ); + + WsFreeError( error ); + WsFreeServiceProxy( proxy ); + WsFreeHeap( heap ); +} + static const char status_200[] = "HTTP/1.1 200 OK\r\n"; +static const char status_500[] = "HTTP/1.1 500 Internal Server Error\r\n";
static const struct { @@ -813,6 +907,7 @@ tests[] = { "req_test2", req_test2, sizeof(req_test2)-1, status_200, resp_test2, sizeof(resp_test2)-1 }, { "req_test3", req_test3, sizeof(req_test3)-1, status_200, resp_test3, sizeof(resp_test3)-1 }, { "req_test4", req_test4, sizeof(req_test4)-1, status_200, resp_test4, sizeof(resp_test4)-1 }, + { "req_test5", req_test5, sizeof(req_test5)-1, status_500, resp_test5, sizeof(resp_test5)-1 }, };
static void send_response( int c, const char *status, const char *data, unsigned int len ) @@ -947,6 +1042,7 @@ START_TEST(proxy) test_WsCall( info.port ); test_empty_response( info.port ); test_inout_params( info.port ); + test_fault_response( info.port );
test_WsSendMessage( info.port, &quit ); WaitForSingleObject( thread, 3000 );
Hans Leidekker (@hans) commented about dlls/webservices/tests/reader.c:
WsFreeReader( reader );
}
+static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line );
Please move check_output_buffer() up instead of adding a forward declaration.
Hans Leidekker (@hans) commented about dlls/webservices/msg.c:
memset( &msg->ctx_send, 0, sizeof(msg->ctx_send) ); memset( &msg->ctx_receive, 0, sizeof(msg->ctx_receive) );
- prop_set( msg->prop, msg->prop_count, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(BOOL) );
sizeof(isfault) is slightly better.
Hans Leidekker (@hans) commented about dlls/webservices/msg.c:
} } if (!match_current_element( reader, &body )) return WS_E_INVALID_FORMAT;
- return WsReadNode( reader, NULL );
- if ((hr = WsReadNode( reader, NULL )) != S_OK) return hr;
- isfault = match_current_element_with_ns( reader, &fault, ns_env );
- hr = prop_set( msg->prop, msg->prop_count, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(BOOL) );
- return hr;
`` return prop_set( msg->prop, msg->prop_count, WS_MESSAGE_PROPERTY_IS_FAULT, &isfault, sizeof(isfault) ); ``
Hans Leidekker (@hans) commented about dlls/webservices/msg.c:
LeaveCriticalSection( &msg->cs ); return hr;
}
+/* Attempt to read a fault message. If the message is a fault, WS_E_ENDPOINT_FAULT_RECEIVED will be returned. */ +HRESULT message_read_fault( WS_MESSAGE *handle, WS_HEAP *heap, WS_ERROR *error )
This commit should be merged with the next. It's better to include helpers in the commit where they are used.