[2/8] webservices: Fix corner cases in write option handling.
Hans Leidekker
hans at codeweavers.com
Wed Sep 28 05:38:00 CDT 2016
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/tests/writer.c | 113 +++++++++++
dlls/webservices/writer.c | 401 ++++++++++++++++++++++------------------
2 files changed, 339 insertions(+), 175 deletions(-)
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 326aed2..2309ab5 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -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();
}
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 2f74f75..cc734d2 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -1403,235 +1403,369 @@ static HRESULT write_type_text( struct writer *writer, WS_TYPE_MAPPING mapping,
}
}
+static HRESULT write_add_nil_attribute( struct writer *writer )
+{
+ static const WS_XML_STRING prefix = {1, (BYTE *)"a"};
+ static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
+ static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
+ static const WS_XML_UTF8_TEXT value = {{WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"true"}};
+ HRESULT hr;
+
+ if ((hr = write_add_attribute( writer, &prefix, &localname, &ns, FALSE )) != S_OK) return hr;
+ if ((hr = write_set_attribute_value( writer, &value.text )) != S_OK) return hr;
+ 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, const BOOL *value )
+ 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( value, 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, const INT8 *value )
+ 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( value, 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, const INT16 *value )
+ 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( value, 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, const INT32 *value )
+ 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( value, 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, const INT64 *value )
+ 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( value, 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, const UINT8 *value )
+ 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( value, 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, const UINT16 *value )
+ 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( value, 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, const UINT32 *value )
+ 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( value, 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, const UINT64 *value )
+ 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( value, 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, const GUID *value )
+ 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( value, 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, const WS_STRING *value )
+ 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 *)value->chars;
- utf16.byteCount = value->length * sizeof(WCHAR);
+ 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, const WCHAR *value )
+ 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 *)value;
- utf16.byteCount = strlenW( value ) * sizeof(WCHAR);
+ 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, const WS_XML_STRING *value )
+ 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;
}
- 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"};
- static const WS_XML_STRING localname = {3, (BYTE *)"nil"};
- static const WS_XML_STRING ns = {41, (BYTE *)"http://www.w3.org/2001/XMLSchema-instance"};
- static const WS_XML_UTF8_TEXT value = {{WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"true"}};
- HRESULT hr;
+ 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;
- if ((hr = write_add_attribute( writer, &prefix, &localname, &ns, FALSE )) != S_OK) return hr;
- if ((hr = write_set_attribute_value( writer, &value.text )) != S_OK) return hr;
- return write_add_namespace_attribute( writer, &prefix, &ns, FALSE );
+ 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,
@@ -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 );
- }
- case WS_WSZ_TYPE:
- {
- const WCHAR *ptr;
+ return write_type_string( writer, mapping, desc, option, value, size );
- if (option == WS_WRITE_REQUIRED_VALUE) return E_INVALIDARG;
+ case WS_WSZ_TYPE:
+ return write_type_wsz( writer, mapping, desc, option, value, size );
- 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;
--
2.1.4
More information about the wine-patches
mailing list