webservices: Fix corner cases in write option handling.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
oldstable
Hans Leidekker 2016-09-28 12:38:00 +02:00 committed by Alexandre Julliard
parent 517638695e
commit e4fd90596d
2 changed files with 515 additions and 351 deletions

View File

@ -2435,6 +2435,118 @@ static void test_escapes(void)
WsFreeWriter( writer );
}
static void test_write_option(void)
{
static const WCHAR sW[] = {'s',0};
static const WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
WS_XML_WRITER *writer;
int val_int = -1, val_int_zero = 0, *ptr_int = &val_int, *ptr_int_null = NULL;
const WCHAR *ptr_wsz = sW, *ptr_wsz_null = NULL;
static const WS_XML_STRING val_xmlstr = {1, (BYTE *)"x"}, val_xmlstr_zero = {0, NULL};
const WS_XML_STRING *ptr_xmlstr = &val_xmlstr, *ptr_xmlstr_null = NULL;
struct
{
WS_TYPE type;
WS_WRITE_OPTION option;
const void *value;
ULONG size;
HRESULT hr;
const char *result;
}
tests[] =
{
{ WS_INT32_TYPE, 0, NULL, 0, E_INVALIDARG },
{ WS_INT32_TYPE, 0, "str", 0, E_INVALIDARG },
{ WS_INT32_TYPE, 0, NULL, sizeof(val_int), E_INVALIDARG },
{ WS_INT32_TYPE, 0, &val_int, sizeof(val_int), E_INVALIDARG },
{ WS_INT32_TYPE, 0, &val_int_zero, sizeof(val_int_zero), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, sizeof(val_int), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int, sizeof(val_int), S_OK, "<t>-1</t>" },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_VALUE, &val_int_zero, sizeof(val_int_zero), S_OK, "<t>0</t>" },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, sizeof(val_int), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int, sizeof(val_int), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_VALUE, &val_int_zero, sizeof(val_int_zero), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_int), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int, sizeof(ptr_int), S_OK, "<t>-1</t>" },
{ WS_INT32_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_int_null, sizeof(ptr_int_null), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int, 0, E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_int), E_INVALIDARG },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int, sizeof(ptr_int), S_OK, "<t>-1</t>" },
{ WS_INT32_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_int_null, sizeof(ptr_int_null), S_OK,
"<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
{ WS_XML_STRING_TYPE, 0, NULL, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, 0, &val_xmlstr, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, 0, NULL, sizeof(val_xmlstr), E_INVALIDARG },
{ WS_XML_STRING_TYPE, 0, &val_xmlstr, sizeof(val_xmlstr), E_INVALIDARG },
{ WS_XML_STRING_TYPE, 0, &val_xmlstr_zero, sizeof(val_xmlstr_zero), E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, NULL, sizeof(&val_xmlstr), E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr, sizeof(val_xmlstr), S_OK, "<t>x</t>" },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_VALUE, &val_xmlstr_zero, sizeof(val_xmlstr_zero), S_OK, "<t/>" },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, NULL, sizeof(&val_xmlstr), E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr, sizeof(&val_xmlstr), E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_VALUE, &val_xmlstr_zero, sizeof(val_xmlstr_zero), S_OK,
"<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_xmlstr), E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr, sizeof(ptr_xmlstr), S_OK, "<t>x</t>" },
{ WS_XML_STRING_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_xmlstr_null, sizeof(ptr_xmlstr_null), E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr, 0, E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_xmlstr), E_INVALIDARG },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr, sizeof(ptr_xmlstr), S_OK, "<t>x</t>" },
{ WS_XML_STRING_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_xmlstr_null, sizeof(ptr_xmlstr_null), S_OK,
"<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
{ WS_WSZ_TYPE, 0, NULL, 0, E_INVALIDARG },
{ WS_WSZ_TYPE, 0, &ptr_wsz, 0, E_INVALIDARG },
{ WS_WSZ_TYPE, 0, NULL, sizeof(ptr_wsz), E_INVALIDARG },
{ WS_WSZ_TYPE, 0, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
{ WS_WSZ_TYPE, 0, &ptr_wsz_null, sizeof(ptr_wsz_null), E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_REQUIRED_VALUE, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_NILLABLE_VALUE, &ptr_wsz, sizeof(ptr_wsz), E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, 0, E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz, 0, E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, NULL, sizeof(ptr_wsz), E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz, sizeof(ptr_wsz), S_OK, "<t>s</t>" },
{ WS_WSZ_TYPE, WS_WRITE_REQUIRED_POINTER, &ptr_wsz_null, sizeof(ptr_wsz_null), E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, 0, E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz, 0, E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, NULL, sizeof(ptr_wsz), E_INVALIDARG },
{ WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz, sizeof(ptr_wsz), S_OK, "<t>s</t>" },
{ WS_WSZ_TYPE, WS_WRITE_NILLABLE_POINTER, &ptr_wsz_null, sizeof(ptr_wsz_null), S_OK,
"<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>" },
};
HRESULT hr;
ULONG i;
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL, tests[i].option, tests[i].value,
tests[i].size, NULL );
ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
WsWriteEndElement( writer, NULL );
if (hr == S_OK) check_output( writer, tests[i].result, __LINE__ );
}
WsFreeWriter( writer );
}
START_TEST(writer)
{
test_WsCreateWriter();
@ -2465,4 +2577,5 @@ START_TEST(writer)
test_WsWriteText();
test_WsWriteArray();
test_escapes();
test_write_option();
}

View File

@ -1403,224 +1403,6 @@ static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
}
}
static HRESULT write_type_bool( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_BOOL_DESCRIPTION *desc, const BOOL *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[6]; /* "false" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_bool( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int8( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT8_DESCRIPTION *desc, const INT8 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[5]; /* "-128" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int8( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int16( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT16_DESCRIPTION *desc, const INT16 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[7]; /* "-32768" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int16( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int32( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT32_DESCRIPTION *desc, const INT32 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[12]; /* "-2147483648" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int32( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int64( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT64_DESCRIPTION *desc, const INT64 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[21]; /* "-9223372036854775808" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int64( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint8( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT8_DESCRIPTION *desc, const UINT8 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[4]; /* "255" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint8( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint16( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT16_DESCRIPTION *desc, const UINT16 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[6]; /* "65535" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint16( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint32( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT32_DESCRIPTION *desc, const UINT32 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[11]; /* "4294967295" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint32( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint64( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT64_DESCRIPTION *desc, const UINT64 *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[21]; /* "18446744073709551615" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint64( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_guid( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_GUID_DESCRIPTION *desc, const GUID *value )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[37]; /* "00000000-0000-0000-0000-000000000000" */
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_guid( value, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_string( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_STRING_DESCRIPTION *desc, const WS_STRING *value )
{
WS_XML_UTF16_TEXT utf16;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf16.text.textType = WS_XML_TEXT_TYPE_UTF16;
utf16.bytes = (BYTE *)value->chars;
utf16.byteCount = value->length * sizeof(WCHAR);
return write_type_text( writer, mapping, &utf16.text );
}
static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_WSZ_DESCRIPTION *desc, const WCHAR *value )
{
WS_XML_UTF16_TEXT utf16;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf16.text.textType = WS_XML_TEXT_TYPE_UTF16;
utf16.bytes = (BYTE *)value;
utf16.byteCount = strlenW( value ) * sizeof(WCHAR);
return write_type_text( writer, mapping, &utf16.text );
}
static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_XML_STRING_DESCRIPTION *desc, const WS_XML_STRING *value )
{
WS_XML_UTF8_TEXT utf8;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = value->bytes;
utf8.value.length = value->length;
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_add_nil_attribute( struct writer *writer )
{
static const WS_XML_STRING prefix = {1, (BYTE *)"a"};
@ -1634,6 +1416,358 @@ static HRESULT write_add_nil_attribute( struct writer *writer )
return write_add_namespace_attribute( writer, &prefix, &ns, FALSE );
}
static HRESULT get_value_ptr( WS_WRITE_OPTION option, const void *value, ULONG size, ULONG expected_size,
const void **ptr )
{
switch (option)
{
case WS_WRITE_REQUIRED_VALUE:
case WS_WRITE_NILLABLE_VALUE:
if (!value || size != expected_size) return E_INVALIDARG;
*ptr = value;
return S_OK;
case WS_WRITE_REQUIRED_POINTER:
if (size != sizeof(const void *) || !(*ptr = *(const void **)value)) return E_INVALIDARG;
return S_OK;
case WS_WRITE_NILLABLE_POINTER:
if (size != sizeof(const void *)) return E_INVALIDARG;
*ptr = *(const void **)value;
return S_OK;
default:
return E_INVALIDARG;
}
}
static HRESULT write_type_bool( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_BOOL_DESCRIPTION *desc, WS_WRITE_OPTION option,
const BOOL *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[6]; /* "false" */
const BOOL *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(BOOL), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_bool( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int8( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT8_DESCRIPTION *desc, WS_WRITE_OPTION option,
const BOOL *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[5]; /* "-128" */
const INT8 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(INT8), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int8( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int16( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT16_DESCRIPTION *desc, WS_WRITE_OPTION option,
const BOOL *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[7]; /* "-32768" */
const INT16 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(INT16), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int16( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int32( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT32_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[12]; /* "-2147483648" */
const INT32 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(INT32), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int32( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_int64( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_INT64_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[21]; /* "-9223372036854775808" */
const INT64 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(INT64), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_int64( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint8( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT8_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[4]; /* "255" */
const UINT8 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(UINT8), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint8( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint16( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT16_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[6]; /* "65535" */
const UINT16 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(UINT16), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint16( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint32( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT32_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[11]; /* "4294967295" */
const UINT32 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(UINT32), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint32( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_uint64( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_UINT64_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[21]; /* "18446744073709551615" */
const UINT64 *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(UINT64), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_uint64( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_guid( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_GUID_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
unsigned char buf[37]; /* "00000000-0000-0000-0000-000000000000" */
const GUID *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(GUID), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = buf;
utf8.value.length = format_guid( ptr, buf );
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type_string( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF16_TEXT utf16;
const WS_STRING *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(WS_STRING), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
if (!ptr->length) return S_OK;
utf16.text.textType = WS_XML_TEXT_TYPE_UTF16;
utf16.bytes = (BYTE *)ptr->chars;
utf16.byteCount = ptr->length * sizeof(WCHAR);
return write_type_text( writer, mapping, &utf16.text );
}
static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_WSZ_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF16_TEXT utf16;
const WCHAR *ptr;
HRESULT hr;
int len;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option || option == WS_WRITE_REQUIRED_VALUE || option == WS_WRITE_NILLABLE_VALUE) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, 0, (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
if (!(len = strlenW( ptr ))) return S_OK;
utf16.text.textType = WS_XML_TEXT_TYPE_UTF16;
utf16.bytes = (BYTE *)ptr;
utf16.byteCount = len * sizeof(WCHAR);
return write_type_text( writer, mapping, &utf16.text );
}
static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_XML_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_UTF8_TEXT utf8;
const WS_XML_STRING *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(WS_XML_STRING), (const void **)&ptr )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
if (option == WS_WRITE_NILLABLE_VALUE && is_nil_value( value, size )) return write_add_nil_attribute( writer );
if (!ptr->length) return S_OK;
utf8.text.textType = WS_XML_TEXT_TYPE_UTF8;
utf8.value.bytes = ptr->bytes;
utf8.value.length = ptr->length;
return write_type_text( writer, mapping, &utf8.text );
}
static HRESULT write_type( struct writer *, WS_TYPE_MAPPING, WS_TYPE, const void *, WS_WRITE_OPTION,
const void *, ULONG );
@ -1643,32 +1777,34 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
HRESULT hr;
WS_TYPE_MAPPING mapping;
WS_WRITE_OPTION option;
ULONG field_options = desc->options;
if (desc->options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE))
if (field_options & ~(WS_FIELD_POINTER|WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE))
{
FIXME( "options 0x%x not supported\n", desc->options );
return E_NOTIMPL;
}
/* zero-terminated strings are always pointers */
if (desc->type == WS_WSZ_TYPE) field_options |= WS_FIELD_POINTER;
if (is_nil_value( value, size ))
{
if (desc->options & WS_FIELD_NILLABLE)
if (field_options & WS_FIELD_NILLABLE)
{
if (desc->options & WS_FIELD_POINTER)
option = WS_WRITE_NILLABLE_POINTER;
else
option = WS_WRITE_NILLABLE_VALUE;
if (field_options & WS_FIELD_POINTER) option = WS_WRITE_NILLABLE_POINTER;
else option = WS_WRITE_NILLABLE_VALUE;
}
else
{
if (desc->options & WS_FIELD_OPTIONAL) return S_OK;
if (field_options & WS_FIELD_OPTIONAL) return S_OK;
return E_INVALIDARG;
}
}
else
{
if (desc->options & WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER;
else option = 0;
if (field_options & WS_FIELD_POINTER) option = WS_WRITE_REQUIRED_POINTER;
else option = WS_WRITE_REQUIRED_VALUE;
}
switch (desc->mapping)
@ -1684,10 +1820,6 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
case WS_ELEMENT_FIELD_MAPPING:
if ((hr = write_element_node( writer, NULL, desc->localName, desc->ns )) != S_OK) return hr;
if (option == WS_WRITE_NILLABLE_VALUE || option == WS_WRITE_NILLABLE_POINTER)
{
if ((hr = write_add_nil_attribute( writer )) != S_OK) return hr;
}
mapping = WS_ELEMENT_TYPE_MAPPING;
break;
@ -1713,11 +1845,8 @@ static HRESULT write_type_struct_field( struct writer *writer, const WS_FIELD_DE
return E_NOTIMPL;
}
if (option != WS_WRITE_NILLABLE_VALUE && option != WS_WRITE_NILLABLE_POINTER)
{
if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK)
return hr;
}
if ((hr = write_type( writer, mapping, desc->type, desc->typeDescription, option, value, size )) != S_OK)
return hr;
switch (mapping)
{
@ -1742,156 +1871,78 @@ static ULONG get_field_size( const WS_STRUCT_DESCRIPTION *desc, ULONG index )
}
static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_STRUCT_DESCRIPTION *desc, const void *value )
const WS_STRUCT_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
ULONG i, size;
ULONG i, field_size;
const void *ptr, *field_ptr;
HRESULT hr;
const char *ptr;
if (!desc) return E_INVALIDARG;
if (desc->structOptions) FIXME( "struct options 0x%x not supported\n", desc->structOptions );
if ((hr = get_value_ptr( option, value, size, desc->size, (const void **)&ptr )) != S_OK) return hr;
for (i = 0; i < desc->fieldCount; i++)
{
ptr = (const char *)value + desc->fields[i]->offset;
size = get_field_size( desc, i );
if ((hr = write_type_struct_field( writer, desc->fields[i], ptr, size )) != S_OK)
field_ptr = (const char *)ptr + desc->fields[i]->offset;
field_size = get_field_size( desc, i );
if ((hr = write_type_struct_field( writer, desc->fields[i], field_ptr, field_size )) != S_OK)
return hr;
}
return S_OK;
}
static HRESULT get_value_ptr( WS_WRITE_OPTION option, const void *value, ULONG size, const void **ptr )
{
switch (option)
{
case WS_WRITE_REQUIRED_VALUE:
case WS_WRITE_NILLABLE_VALUE:
if (!value || !size) return E_INVALIDARG;
*ptr = value;
return S_OK;
case WS_WRITE_REQUIRED_POINTER:
case WS_WRITE_NILLABLE_POINTER:
if (size != sizeof(const void *) || !(*ptr = *(const void **)value)) return E_INVALIDARG;
return S_OK;
default:
FIXME( "option %08x not supported\n", option );
return E_NOTIMPL;
}
}
static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TYPE type,
const void *desc, WS_WRITE_OPTION option, const void *value,
ULONG size )
{
HRESULT hr;
switch (type)
{
case WS_STRUCT_TYPE:
{
const void *ptr;
if (!desc) return E_INVALIDARG;
if (!option) option = WS_WRITE_REQUIRED_POINTER;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_struct( writer, mapping, desc, ptr );
}
return write_type_struct( writer, mapping, desc, option, value, size );
case WS_BOOL_TYPE:
{
const BOOL *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_bool( writer, mapping, desc, ptr );
}
return write_type_bool( writer, mapping, desc, option, value, size );
case WS_INT8_TYPE:
{
const INT8 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_int8( writer, mapping, desc, ptr );
}
return write_type_int8( writer, mapping, desc, option, value, size );
case WS_INT16_TYPE:
{
const INT16 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_int16( writer, mapping, desc, ptr );
}
return write_type_int16( writer, mapping, desc, option, value, size );
case WS_INT32_TYPE:
{
const INT32 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_int32( writer, mapping, desc, ptr );
}
return write_type_int32( writer, mapping, desc, option, value, size );
case WS_INT64_TYPE:
{
const INT64 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_int64( writer, mapping, desc, ptr );
}
return write_type_int64( writer, mapping, desc, option, value, size );
case WS_UINT8_TYPE:
{
const UINT8 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_uint8( writer, mapping, desc, ptr );
}
return write_type_uint8( writer, mapping, desc, option, value, size );
case WS_UINT16_TYPE:
{
const UINT16 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_uint16( writer, mapping, desc, ptr );
}
return write_type_uint16( writer, mapping, desc, option, value, size );
case WS_UINT32_TYPE:
{
const UINT32 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_uint32( writer, mapping, desc, ptr );
}
return write_type_uint32( writer, mapping, desc, option, value, size );
case WS_UINT64_TYPE:
{
const UINT64 *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_uint64( writer, mapping, desc, ptr );
}
return write_type_uint64( writer, mapping, desc, option, value, size );
case WS_GUID_TYPE:
{
const GUID *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_guid( writer, mapping, desc, ptr );
}
return write_type_guid( writer, mapping, desc, option, value, size );
case WS_STRING_TYPE:
{
const WS_STRING *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_string( writer, mapping, desc, ptr );
}
return write_type_string( writer, mapping, desc, option, value, size );
case WS_WSZ_TYPE:
{
const WCHAR *ptr;
return write_type_wsz( writer, mapping, desc, option, value, size );
if (option == WS_WRITE_REQUIRED_VALUE) return E_INVALIDARG;
if (!option) option = WS_WRITE_REQUIRED_POINTER;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_wsz( writer, mapping, desc, ptr );
}
case WS_XML_STRING_TYPE:
{
const WS_XML_STRING *ptr;
if (!option) option = WS_WRITE_REQUIRED_VALUE;
if ((hr = get_value_ptr( option, value, size, (const void **)&ptr )) != S_OK) return hr;
return write_type_xml_string( writer, mapping, desc, ptr );
}
return write_type_xml_string( writer, mapping, desc, option, value, size );
default:
FIXME( "type %u not supported\n", type );
return E_NOTIMPL;