webservices: Add support for writing WS_BYTES values.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8ce55bc98f
commit
c8a90e5de9
|
@ -574,6 +574,17 @@ static void test_WsWriteType(void)
|
||||||
WsFreeWriter( writer );
|
WsFreeWriter( writer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void prepare_basic_type_test( WS_XML_WRITER *writer )
|
||||||
|
{
|
||||||
|
WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = set_output( writer );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
}
|
||||||
|
|
||||||
static void test_basic_type(void)
|
static void test_basic_type(void)
|
||||||
{
|
{
|
||||||
static WCHAR testW[] = {'t','e','s','t',0};
|
static WCHAR testW[] = {'t','e','s','t',0};
|
||||||
|
@ -583,6 +594,7 @@ static void test_basic_type(void)
|
||||||
GUID guid;
|
GUID guid;
|
||||||
WCHAR *str;
|
WCHAR *str;
|
||||||
WS_STRING string;
|
WS_STRING string;
|
||||||
|
WS_BYTES bytes;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
static const struct
|
static const struct
|
||||||
{
|
{
|
||||||
|
@ -615,12 +627,7 @@ static void test_basic_type(void)
|
||||||
/* element content type mapping */
|
/* element content type mapping */
|
||||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
|
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
|
||||||
{
|
{
|
||||||
hr = set_output( writer );
|
prepare_basic_type_test( writer );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
|
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
|
||||||
WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
|
WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
|
||||||
ok( hr == S_OK, "%u: got %08x\n", i, hr );
|
ok( hr == S_OK, "%u: got %08x\n", i, hr );
|
||||||
|
@ -635,12 +642,7 @@ static void test_basic_type(void)
|
||||||
{
|
{
|
||||||
const INT64 *ptr = &tests[i].val;
|
const INT64 *ptr = &tests[i].val;
|
||||||
|
|
||||||
hr = set_output( writer );
|
prepare_basic_type_test( writer );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
|
||||||
WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
|
WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
|
||||||
ok( hr == S_OK, "%u: got %08x\n", i, hr );
|
ok( hr == S_OK, "%u: got %08x\n", i, hr );
|
||||||
|
@ -653,12 +655,7 @@ static void test_basic_type(void)
|
||||||
/* attribute type mapping */
|
/* attribute type mapping */
|
||||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
|
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
|
||||||
{
|
{
|
||||||
hr = set_output( writer );
|
prepare_basic_type_test( writer );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
|
hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
|
@ -674,68 +671,81 @@ static void test_basic_type(void)
|
||||||
check_output( writer, tests[i].result2, __LINE__ );
|
check_output( writer, tests[i].result2, __LINE__ );
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = set_output( writer );
|
prepare_basic_type_test( writer );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
memset( &guid, 0, sizeof(guid) );
|
memset( &guid, 0, sizeof(guid) );
|
||||||
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
||||||
&guid, sizeof(guid), NULL );
|
&guid, sizeof(guid), NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
hr = WsWriteEndElement( writer, NULL );
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
|
check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
|
||||||
|
|
||||||
hr = set_output( writer );
|
prepare_basic_type_test( writer );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
string.chars = testW;
|
string.chars = testW;
|
||||||
string.length = 4;
|
string.length = 4;
|
||||||
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
||||||
&string, sizeof(string), NULL );
|
&string, sizeof(string), NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
hr = WsWriteEndElement( writer, NULL );
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
check_output( writer, "<t>test</t>", __LINE__ );
|
check_output( writer, "<t>test</t>", __LINE__ );
|
||||||
|
|
||||||
hr = set_output( writer );
|
prepare_basic_type_test( writer );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
str = testW;
|
str = testW;
|
||||||
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
|
||||||
&str, sizeof(str), NULL );
|
&str, sizeof(str), NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
hr = WsWriteEndElement( writer, NULL );
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
check_output( writer, "<t>test</t>", __LINE__ );
|
check_output( writer, "<t>test</t>", __LINE__ );
|
||||||
|
|
||||||
hr = set_output( writer );
|
prepare_basic_type_test( writer );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
|
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
|
||||||
|
|
||||||
xmlstr.bytes = (BYTE *)"test";
|
xmlstr.bytes = (BYTE *)"test";
|
||||||
xmlstr.length = 4;
|
xmlstr.length = 4;
|
||||||
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
||||||
&xmlstr, sizeof(xmlstr), NULL );
|
&xmlstr, sizeof(xmlstr), NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
|
||||||
hr = WsWriteEndElement( writer, NULL );
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
ok( hr == S_OK, "got %08x\n", hr );
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
check_output( writer, "<t>test</t>", __LINE__ );
|
check_output( writer, "<t>test</t>", __LINE__ );
|
||||||
|
|
||||||
|
prepare_basic_type_test( writer );
|
||||||
|
bytes.bytes = (BYTE *)"test";
|
||||||
|
bytes.length = 4;
|
||||||
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
||||||
|
&bytes, sizeof(bytes), NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
check_output( writer, "<t>dGVzdA==</t>", __LINE__ );
|
||||||
|
|
||||||
|
prepare_basic_type_test( writer );
|
||||||
|
bytes.length = 0;
|
||||||
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
||||||
|
&bytes, sizeof(bytes), NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
check_output( writer, "<t/>", __LINE__ );
|
||||||
|
|
||||||
|
prepare_basic_type_test( writer );
|
||||||
|
bytes.bytes = NULL;
|
||||||
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
|
||||||
|
&bytes, sizeof(bytes), NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
check_output( writer, "<t/>", __LINE__ );
|
||||||
|
|
||||||
|
prepare_basic_type_test( writer );
|
||||||
|
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_NILLABLE_VALUE,
|
||||||
|
&bytes, sizeof(bytes), NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
hr = WsWriteEndElement( writer, NULL );
|
||||||
|
ok( hr == S_OK, "got %08x\n", hr );
|
||||||
|
check_output( writer, "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>",
|
||||||
|
__LINE__ );
|
||||||
|
|
||||||
WsFreeWriter( writer );
|
WsFreeWriter( writer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1265,6 +1265,38 @@ static ULONG format_urn( const GUID *ptr, unsigned char *buf )
|
||||||
ptr->Data4[4], ptr->Data4[5], ptr->Data4[6], ptr->Data4[7] );
|
ptr->Data4[4], ptr->Data4[5], ptr->Data4[6], ptr->Data4[7] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ULONG encode_base64( const unsigned char *bin, ULONG len, unsigned char *buf )
|
||||||
|
{
|
||||||
|
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
ULONG i = 0, x;
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
buf[i++] = base64[(bin[0] & 0xfc) >> 2];
|
||||||
|
x = (bin[0] & 3) << 4;
|
||||||
|
if (len == 1)
|
||||||
|
{
|
||||||
|
buf[i++] = base64[x];
|
||||||
|
buf[i++] = '=';
|
||||||
|
buf[i++] = '=';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[i++] = base64[x | ((bin[1] & 0xf0) >> 4)];
|
||||||
|
x = (bin[1] & 0x0f) << 2;
|
||||||
|
if (len == 2)
|
||||||
|
{
|
||||||
|
buf[i++] = base64[x];
|
||||||
|
buf[i++] = '=';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[i++] = base64[x | ((bin[2] & 0xc0) >> 6)];
|
||||||
|
buf[i++] = base64[bin[2] & 0x3f];
|
||||||
|
bin += 3;
|
||||||
|
len -= 3;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret )
|
static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret )
|
||||||
{
|
{
|
||||||
switch (text->textType)
|
switch (text->textType)
|
||||||
|
@ -1287,6 +1319,14 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret
|
||||||
WideCharToMultiByte( CP_UTF8, 0, str, len, (char *)(*ret)->value.bytes, (*ret)->value.length, NULL, NULL );
|
WideCharToMultiByte( CP_UTF8, 0, str, len, (char *)(*ret)->value.bytes, (*ret)->value.length, NULL, NULL );
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
case WS_XML_TEXT_TYPE_BASE64:
|
||||||
|
{
|
||||||
|
const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text;
|
||||||
|
ULONG len = ((4 * base64->length / 3) + 3) & ~3;
|
||||||
|
if (!(*ret = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
|
||||||
|
(*ret)->value.length = encode_base64( base64->bytes, base64->length, (*ret)->value.bytes );
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
case WS_XML_TEXT_TYPE_BOOL:
|
case WS_XML_TEXT_TYPE_BOOL:
|
||||||
{
|
{
|
||||||
const WS_XML_BOOL_TEXT *bool_text = (const WS_XML_BOOL_TEXT *)text;
|
const WS_XML_BOOL_TEXT *bool_text = (const WS_XML_BOOL_TEXT *)text;
|
||||||
|
@ -1837,6 +1877,32 @@ static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
|
||||||
return write_type_text( writer, mapping, &utf16.text );
|
return write_type_text( writer, mapping, &utf16.text );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT write_type_bytes( struct writer *writer, WS_TYPE_MAPPING mapping,
|
||||||
|
const WS_BYTES_DESCRIPTION *desc, WS_WRITE_OPTION option,
|
||||||
|
const void *value, ULONG size )
|
||||||
|
{
|
||||||
|
WS_XML_BASE64_TEXT base64;
|
||||||
|
const WS_BYTES *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_BYTES), (const void **)&ptr )) != S_OK) return hr;
|
||||||
|
if ((option == WS_WRITE_NILLABLE_VALUE && is_nil_value( value, size )) ||
|
||||||
|
(option == WS_WRITE_NILLABLE_POINTER && !ptr)) return write_add_nil_attribute( writer );
|
||||||
|
if (!ptr->length) return S_OK;
|
||||||
|
|
||||||
|
base64.text.textType = WS_XML_TEXT_TYPE_BASE64;
|
||||||
|
base64.bytes = ptr->bytes;
|
||||||
|
base64.length = ptr->length;
|
||||||
|
return write_type_text( writer, mapping, &base64.text );
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING mapping,
|
static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING mapping,
|
||||||
const WS_XML_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option,
|
const WS_XML_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option,
|
||||||
const void *value, ULONG size )
|
const void *value, ULONG size )
|
||||||
|
@ -1996,9 +2062,6 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case WS_STRUCT_TYPE:
|
|
||||||
return write_type_struct( writer, mapping, desc, option, value, size );
|
|
||||||
|
|
||||||
case WS_BOOL_TYPE:
|
case WS_BOOL_TYPE:
|
||||||
return write_type_bool( writer, mapping, desc, option, value, size );
|
return write_type_bool( writer, mapping, desc, option, value, size );
|
||||||
|
|
||||||
|
@ -2038,9 +2101,15 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
|
||||||
case WS_WSZ_TYPE:
|
case WS_WSZ_TYPE:
|
||||||
return write_type_wsz( writer, mapping, desc, option, value, size );
|
return write_type_wsz( writer, mapping, desc, option, value, size );
|
||||||
|
|
||||||
|
case WS_BYTES_TYPE:
|
||||||
|
return write_type_bytes( writer, mapping, desc, option, value, size );
|
||||||
|
|
||||||
case WS_XML_STRING_TYPE:
|
case WS_XML_STRING_TYPE:
|
||||||
return write_type_xml_string( writer, mapping, desc, option, value, size );
|
return write_type_xml_string( writer, mapping, desc, option, value, size );
|
||||||
|
|
||||||
|
case WS_STRUCT_TYPE:
|
||||||
|
return write_type_struct( writer, mapping, desc, option, value, size );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FIXME( "type %u not supported\n", type );
|
FIXME( "type %u not supported\n", type );
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
|
|
Loading…
Reference in New Issue