Commit 42980ed2 authored by Shaun Ren's avatar Shaun Ren Committed by Alexandre Julliard

webservices: Add support for reading WS_FAULT values.

parent fa359ed9
......@@ -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;
......
......@@ -1355,6 +1355,40 @@ static void test_WsReadNode(void)
WsFreeReader( reader );
}
static HRESULT set_output( WS_XML_WRITER *writer )
{
WS_XML_WRITER_TEXT_ENCODING text = {{WS_XML_WRITER_ENCODING_TYPE_TEXT}, WS_CHARSET_UTF8};
WS_XML_WRITER_BUFFER_OUTPUT buf = {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER}};
return WsSetOutput( writer, &text.encoding, &buf.output, NULL, 0, NULL );
}
static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line )
{
WS_XML_WRITER *writer;
WS_BYTES bytes;
ULONG size = sizeof(bytes);
int len = strlen(expected);
HRESULT hr;
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %#lx\n", hr );
hr = set_output( writer );
ok( hr == S_OK, "got %#lx\n", hr );
hr = WsWriteXmlBuffer( writer, buffer, NULL );
ok( hr == S_OK, "got %#lx\n", hr );
memset( &bytes, 0, sizeof(bytes) );
hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
ok( hr == S_OK, "%u: got %#lx\n", line, hr );
ok( bytes.length == len, "%u: got %lu expected %d\n", line, bytes.length, len );
if (bytes.length != len) return;
ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
WsFreeWriter( writer );
}
static void prepare_type_test( WS_XML_READER *reader, const char *data, ULONG size )
{
HRESULT hr;
......@@ -1373,6 +1407,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/\"><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 +1439,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 +1965,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 );
}
......@@ -6235,40 +6307,6 @@ static void test_dictionary(void)
WsFreeReader( reader );
}
static HRESULT set_output( WS_XML_WRITER *writer )
{
WS_XML_WRITER_TEXT_ENCODING text = {{WS_XML_WRITER_ENCODING_TYPE_TEXT}, WS_CHARSET_UTF8};
WS_XML_WRITER_BUFFER_OUTPUT buf = {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER}};
return WsSetOutput( writer, &text.encoding, &buf.output, NULL, 0, NULL );
}
static void check_output_buffer( WS_XML_BUFFER *buffer, const char *expected, unsigned int line )
{
WS_XML_WRITER *writer;
WS_BYTES bytes;
ULONG size = sizeof(bytes);
int len = strlen(expected);
HRESULT hr;
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %#lx\n", hr );
hr = set_output( writer );
ok( hr == S_OK, "got %#lx\n", hr );
hr = WsWriteXmlBuffer( writer, buffer, NULL );
ok( hr == S_OK, "got %#lx\n", hr );
memset( &bytes, 0, sizeof(bytes) );
hr = WsGetWriterProperty( writer, WS_XML_WRITER_PROPERTY_BYTES, &bytes, size, NULL );
ok( hr == S_OK, "%u: got %#lx\n", line, hr );
ok( bytes.length == len, "%u: got %lu expected %d\n", line, bytes.length, len );
if (bytes.length != len) return;
ok( !memcmp( bytes.bytes, expected, len ), "%u: got %s expected %s\n", line, bytes.bytes, expected );
WsFreeWriter( writer );
}
static HRESULT prepare_xml_buffer_test( WS_XML_READER *reader, WS_HEAP *heap )
{
WS_XML_STRING localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"}, ns = {0, NULL};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment