webservices: Store all text in native format in binary mode.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2017-07-10 11:02:33 +02:00 committed by Alexandre Julliard
parent b9a464f76d
commit 387061881c
3 changed files with 616 additions and 174 deletions

View File

@ -787,7 +787,19 @@ WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *data, ULONG len )
return ret;
}
static WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
WS_XML_UTF16_TEXT *alloc_utf16_text( const BYTE *data, ULONG len )
{
WS_XML_UTF16_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) + len ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_UTF16;
ret->byteCount = len;
ret->bytes = len ? (BYTE *)(ret + 1) : NULL;
if (data) memcpy( ret->bytes, data, len );
return ret;
}
WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
{
WS_XML_BASE64_TEXT *ret;
@ -799,6 +811,86 @@ static WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *data, ULONG len )
return ret;
}
WS_XML_BOOL_TEXT *alloc_bool_text( BOOL value )
{
WS_XML_BOOL_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_BOOL;
ret->value = value;
return ret;
}
WS_XML_INT32_TEXT *alloc_int32_text( INT32 value )
{
WS_XML_INT32_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_INT32;
ret->value = value;
return ret;
}
WS_XML_INT64_TEXT *alloc_int64_text( INT64 value )
{
WS_XML_INT64_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_INT64;
ret->value = value;
return ret;
}
WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 value )
{
WS_XML_UINT64_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_UINT64;
ret->value = value;
return ret;
}
WS_XML_DOUBLE_TEXT *alloc_double_text( double value )
{
WS_XML_DOUBLE_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_DOUBLE;
ret->value = value;
return ret;
}
WS_XML_GUID_TEXT *alloc_guid_text( const GUID *value )
{
WS_XML_GUID_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_GUID;
ret->value = *value;
return ret;
}
WS_XML_UNIQUE_ID_TEXT *alloc_unique_id_text( const GUID *value )
{
WS_XML_UNIQUE_ID_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_UNIQUE_ID;
ret->value = *value;
return ret;
}
WS_XML_DATETIME_TEXT *alloc_datetime_text( const WS_DATETIME *value )
{
WS_XML_DATETIME_TEXT *ret;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
ret->text.textType = WS_XML_TEXT_TYPE_DATETIME;
ret->value = *value;
return ret;
}
static inline BOOL read_end_of_data( struct reader *reader )
{
return reader->read_pos >= reader->read_size;
@ -1300,24 +1392,18 @@ static HRESULT lookup_string( struct reader *reader, ULONG id, const WS_XML_STRI
static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
{
static const unsigned char zero[] = {'0'}, one[] = {'1'};
static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
WS_XML_UTF8_TEXT *utf8 = NULL;
WS_XML_BASE64_TEXT *base64;
WS_XML_UTF8_TEXT *text_utf8 = NULL;
WS_XML_BASE64_TEXT *text_base64 = NULL;
WS_XML_INT32_TEXT *text_int32;
WS_XML_INT64_TEXT *text_int64;
WS_XML_BOOL_TEXT *text_bool;
const WS_XML_STRING *str;
unsigned char type, buf[46];
BOOL val_bool;
INT8 val_int8;
INT16 val_int16;
INT32 val_int32;
INT64 val_int64;
double val_double;
unsigned char type;
UINT8 val_uint8;
UINT16 val_uint16;
UINT64 val_uint64;
WS_DATETIME datetime;
ULONG len, id;
GUID uuid;
INT32 val_int32;
ULONG len = 0, id;
GUID guid;
HRESULT hr;
if ((hr = read_byte( reader, &type )) != S_OK) return hr;
@ -1326,57 +1412,79 @@ static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE
switch (type)
{
case RECORD_ZERO_TEXT:
if (!(utf8 = alloc_utf8_text( zero, sizeof(zero) ))) return E_OUTOFMEMORY;
break;
{
if (!(text_int32 = alloc_int32_text( 0 ))) return E_OUTOFMEMORY;
attr->value = &text_int32->text;
return S_OK;
}
case RECORD_ONE_TEXT:
if (!(utf8 = alloc_utf8_text( one, sizeof(one) ))) return E_OUTOFMEMORY;
break;
{
if (!(text_int32 = alloc_int32_text( 1 ))) return E_OUTOFMEMORY;
attr->value = &text_int32->text;
return S_OK;
}
case RECORD_FALSE_TEXT:
if (!(utf8 = alloc_utf8_text( false, sizeof(false) ))) return E_OUTOFMEMORY;
break;
{
if (!(text_bool = alloc_bool_text( FALSE ))) return E_OUTOFMEMORY;
attr->value = &text_bool->text;
return S_OK;
}
case RECORD_TRUE_TEXT:
if (!(utf8 = alloc_utf8_text( true, sizeof(true) ))) return E_OUTOFMEMORY;
break;
{
if (!(text_bool = alloc_bool_text( TRUE ))) return E_OUTOFMEMORY;
attr->value = &text_bool->text;
return S_OK;
}
case RECORD_INT8_TEXT:
{
INT8 val_int8;
if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
len = format_int8( &val_int8, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
if (!(text_int64 = alloc_int64_text( val_int8 ))) return E_OUTOFMEMORY;
attr->value = &text_int64->text;
return S_OK;
}
case RECORD_INT16_TEXT:
{
INT16 val_int16;
if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
len = format_int16( &val_int16, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
if (!(text_int64 = alloc_int64_text( val_int16 ))) return E_OUTOFMEMORY;
attr->value = &text_int64->text;
return S_OK;
}
case RECORD_INT32_TEXT:
if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
len = format_int32( &val_int32, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
if (!(text_int64 = alloc_int64_text( val_int32 ))) return E_OUTOFMEMORY;
attr->value = &text_int64->text;
return S_OK;
case RECORD_INT64_TEXT:
{
INT64 val_int64;
if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
len = format_int64( &val_int64, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
if (!(text_int64 = alloc_int64_text( val_int64 ))) return E_OUTOFMEMORY;
attr->value = &text_int64->text;
return S_OK;
}
case RECORD_DOUBLE_TEXT:
{
WS_XML_DOUBLE_TEXT *text_double;
double val_double;
if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
len = format_double( &val_double, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
if (!(text_double = alloc_double_text( val_double ))) return E_OUTOFMEMORY;
attr->value = &text_double->text;
return S_OK;
}
case RECORD_DATETIME_TEXT:
if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
len = format_datetime( &datetime, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
{
WS_XML_DATETIME_TEXT *text_datetime;
WS_DATETIME datetime;
if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
if (!(text_datetime = alloc_datetime_text( &datetime ))) return E_OUTOFMEMORY;
attr->value = &text_datetime->text;
return S_OK;
}
case RECORD_CHARS8_TEXT:
if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
len = val_uint8;
@ -1395,20 +1503,20 @@ static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE
case RECORD_BYTES8_TEXT:
if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
if (!(base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
if ((hr = read_bytes( reader, base64->bytes, val_uint8 )) != S_OK)
if (!(text_base64 = alloc_base64_text( NULL, val_uint8 ))) return E_OUTOFMEMORY;
if ((hr = read_bytes( reader, text_base64->bytes, val_uint8 )) != S_OK)
{
heap_free( base64 );
heap_free( text_base64 );
return hr;
}
break;
case RECORD_BYTES16_TEXT:
if ((hr = read_bytes( reader, (unsigned char *)&val_uint16, sizeof(val_uint16) )) != S_OK) return hr;
if (!(base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
if ((hr = read_bytes( reader, base64->bytes, val_uint16 )) != S_OK)
if (!(text_base64 = alloc_base64_text( NULL, val_uint16 ))) return E_OUTOFMEMORY;
if ((hr = read_bytes( reader, text_base64->bytes, val_uint16 )) != S_OK)
{
heap_free( base64 );
heap_free( text_base64 );
return hr;
}
break;
@ -1416,71 +1524,87 @@ static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE
case RECORD_BYTES32_TEXT:
if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
if (val_int32 < 0) return WS_E_INVALID_FORMAT;
if (!(base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
if ((hr = read_bytes( reader, base64->bytes, val_int32 )) != S_OK)
if (!(text_base64 = alloc_base64_text( NULL, val_int32 ))) return E_OUTOFMEMORY;
if ((hr = read_bytes( reader, text_base64->bytes, val_int32 )) != S_OK)
{
heap_free( base64 );
heap_free( text_base64 );
return hr;
}
break;
case RECORD_EMPTY_TEXT:
len = 0;
break;
case RECORD_DICTIONARY_TEXT:
if ((hr = read_int31( reader, &id )) != S_OK) return hr;
if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
if (!(utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
if (!(text_utf8 = alloc_utf8_text( str->bytes, str->length ))) return E_OUTOFMEMORY;
break;
case RECORD_UNIQUEID_TEXT:
if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
len = format_urn( &uuid, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
{
WS_XML_UNIQUE_ID_TEXT *text_unique_id;
if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
if (!(text_unique_id = alloc_unique_id_text( &guid ))) return E_OUTOFMEMORY;
attr->value = &text_unique_id->text;
return S_OK;
}
case RECORD_UUID_TEXT:
if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
len = format_guid( &uuid, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
{
WS_XML_GUID_TEXT *guid_text;
if ((hr = read_bytes( reader, (unsigned char *)&guid, sizeof(guid) )) != S_OK) return hr;
if (!(guid_text = alloc_guid_text( &guid ))) return E_OUTOFMEMORY;
attr->value = &guid_text->text;
return S_OK;
}
case RECORD_UINT64_TEXT:
{
WS_XML_UINT64_TEXT *text_uint64;
UINT64 val_uint64;
if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
len = format_uint64( &val_uint64, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
if (!(text_uint64 = alloc_uint64_text( val_uint64 ))) return E_OUTOFMEMORY;
attr->value = &text_uint64->text;
return S_OK;
}
case RECORD_BOOL_TEXT:
if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
len = format_bool( &val_bool, buf );
if (!(utf8 = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
break;
{
WS_XML_BOOL_TEXT *text_bool;
BOOL val_bool;
if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
if (!(text_bool = alloc_bool_text( !!val_bool ))) return E_OUTOFMEMORY;
attr->value = &text_bool->text;
return S_OK;
}
default:
ERR( "unhandled record type %02x\n", type );
return WS_E_NOT_SUPPORTED;
}
if (type >= RECORD_INT8_TEXT && type <= RECORD_INT64_TEXT)
{
attr->value = &text_int64->text;
return S_OK;
}
if (type >= RECORD_BYTES8_TEXT && type <= RECORD_BYTES32_TEXT)
{
attr->value = &base64->text;
attr->value = &text_base64->text;
return S_OK;
}
if (!utf8)
if (!text_utf8)
{
if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
if (!(text_utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
if (!len) text_utf8->value.bytes = (BYTE *)(text_utf8 + 1); /* quirk */
if ((hr = read_bytes( reader, text_utf8->value.bytes, len )) != S_OK)
{
heap_free( utf8 );
heap_free( text_utf8 );
return hr;
}
}
attr->value = &utf8->text;
attr->value = &text_utf8->text;
return S_OK;
}
@ -1975,6 +2099,142 @@ static struct node *alloc_base64_text_node( const BYTE *data, ULONG len, WS_XML_
return node;
}
static struct node *alloc_bool_text_node( BOOL value )
{
struct node *node;
WS_XML_BOOL_TEXT *text_bool;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_bool = alloc_bool_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_bool->text;
return node;
}
static struct node *alloc_int32_text_node( INT32 value )
{
struct node *node;
WS_XML_INT32_TEXT *text_int32;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_int32 = alloc_int32_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_int32->text;
return node;
}
static struct node *alloc_int64_text_node( INT64 value )
{
struct node *node;
WS_XML_INT64_TEXT *text_int64;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_int64 = alloc_int64_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_int64->text;
return node;
}
static struct node *alloc_double_text_node( double value )
{
struct node *node;
WS_XML_DOUBLE_TEXT *text_double;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_double = alloc_double_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_double->text;
return node;
}
static struct node *alloc_datetime_text_node( const WS_DATETIME *value )
{
struct node *node;
WS_XML_DATETIME_TEXT *text_datetime;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_datetime = alloc_datetime_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_datetime->text;
return node;
}
static struct node *alloc_unique_id_text_node( const GUID *value )
{
struct node *node;
WS_XML_UNIQUE_ID_TEXT *text_unique_id;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_unique_id = alloc_unique_id_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_unique_id->text;
return node;
}
static struct node *alloc_guid_text_node( const GUID *value )
{
struct node *node;
WS_XML_GUID_TEXT *text_guid;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_guid = alloc_guid_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_guid->text;
return node;
}
static struct node *alloc_uint64_text_node( UINT64 value )
{
struct node *node;
WS_XML_UINT64_TEXT *text_uint64;
WS_XML_TEXT_NODE *text;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
if (!(text_uint64 = alloc_uint64_text( value )))
{
heap_free( node );
return NULL;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &text_uint64->text;
return node;
}
static HRESULT append_text_bytes( struct reader *reader, WS_XML_TEXT_NODE *node, ULONG len )
{
WS_XML_BASE64_TEXT *new, *old = (WS_XML_BASE64_TEXT *)node->text;
@ -2064,22 +2324,12 @@ error:
static HRESULT read_text_bin( struct reader *reader )
{
static const unsigned char zero[] = {'0'}, one[] = {'1'};
static const unsigned char false[] = {'f','a','l','s','e'}, true[] = {'t','r','u','e'};
unsigned char type, buf[46];
struct node *node = NULL, *parent;
unsigned char type;
WS_XML_UTF8_TEXT *utf8;
const WS_XML_STRING *str;
BOOL val_bool;
INT8 val_int8;
INT16 val_int16;
INT32 val_int32;
INT64 val_int64;
double val_double;
UINT8 val_uint8;
UINT16 val_uint16;
UINT64 val_uint64;
WS_DATETIME datetime;
ULONG len, id;
GUID uuid;
HRESULT hr;
@ -2091,66 +2341,70 @@ static HRESULT read_text_bin( struct reader *reader )
{
case RECORD_ZERO_TEXT:
case RECORD_ZERO_TEXT_WITH_ENDELEMENT:
if (!(node = alloc_utf8_text_node( zero, sizeof(zero), NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_int32_text_node( 0 ))) return E_OUTOFMEMORY;
break;
case RECORD_ONE_TEXT:
case RECORD_ONE_TEXT_WITH_ENDELEMENT:
if (!(node = alloc_utf8_text_node( one, sizeof(one), NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_int32_text_node( 1 ))) return E_OUTOFMEMORY;
break;
case RECORD_FALSE_TEXT:
case RECORD_FALSE_TEXT_WITH_ENDELEMENT:
if (!(node = alloc_utf8_text_node( false, sizeof(false), NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_bool_text_node( FALSE ))) return E_OUTOFMEMORY;
break;
case RECORD_TRUE_TEXT:
case RECORD_TRUE_TEXT_WITH_ENDELEMENT:
if (!(node = alloc_utf8_text_node( true, sizeof(true), NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_bool_text_node( TRUE ))) return E_OUTOFMEMORY;
break;
case RECORD_INT8_TEXT:
case RECORD_INT8_TEXT_WITH_ENDELEMENT:
{
INT8 val_int8;
if ((hr = read_byte( reader, (unsigned char *)&val_int8 )) != S_OK) return hr;
len = format_int8( &val_int8, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_int32_text_node( val_int8 ))) return E_OUTOFMEMORY;
break;
}
case RECORD_INT16_TEXT:
case RECORD_INT16_TEXT_WITH_ENDELEMENT:
{
INT16 val_int16;
if ((hr = read_bytes( reader, (unsigned char *)&val_int16, sizeof(val_int16) )) != S_OK) return hr;
len = format_int16( &val_int16, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_int32_text_node( val_int16 ))) return E_OUTOFMEMORY;
break;
}
case RECORD_INT32_TEXT:
case RECORD_INT32_TEXT_WITH_ENDELEMENT:
if ((hr = read_bytes( reader, (unsigned char *)&val_int32, sizeof(val_int32) )) != S_OK) return hr;
len = format_int32( &val_int32, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_int32_text_node( val_int32 ))) return E_OUTOFMEMORY;
break;
case RECORD_INT64_TEXT:
case RECORD_INT64_TEXT_WITH_ENDELEMENT:
{
INT64 val_int64;
if ((hr = read_bytes( reader, (unsigned char *)&val_int64, sizeof(val_int64) )) != S_OK) return hr;
len = format_int64( &val_int64, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_int64_text_node( val_int64 ))) return E_OUTOFMEMORY;
break;
}
case RECORD_DOUBLE_TEXT:
case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
{
double val_double;
if ((hr = read_bytes( reader, (unsigned char *)&val_double, sizeof(val_double) )) != S_OK) return hr;
len = format_double( &val_double, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_double_text_node( val_double ))) return E_OUTOFMEMORY;
break;
}
case RECORD_DATETIME_TEXT:
case RECORD_DATETIME_TEXT_WITH_ENDELEMENT:
{
WS_DATETIME datetime;
if ((hr = read_datetime( reader, &datetime )) != S_OK) return hr;
len = format_datetime( &datetime, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_datetime_text_node( &datetime ))) return E_OUTOFMEMORY;
break;
}
case RECORD_CHARS8_TEXT:
case RECORD_CHARS8_TEXT_WITH_ENDELEMENT:
if ((hr = read_byte( reader, (unsigned char *)&val_uint8 )) != S_OK) return hr;
@ -2185,39 +2439,41 @@ static HRESULT read_text_bin( struct reader *reader )
case RECORD_DICTIONARY_TEXT:
case RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT:
{
const WS_XML_STRING *str;
if ((hr = read_int31( reader, &id )) != S_OK) return hr;
if ((hr = lookup_string( reader, id, &str )) != S_OK) return hr;
if (!(node = alloc_utf8_text_node( str->bytes, str->length, NULL ))) return E_OUTOFMEMORY;
break;
}
case RECORD_UNIQUEID_TEXT:
case RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT:
if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
len = format_urn( &uuid, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_unique_id_text_node( &uuid ))) return E_OUTOFMEMORY;
break;
case RECORD_UUID_TEXT:
case RECORD_UUID_TEXT_WITH_ENDELEMENT:
if ((hr = read_bytes( reader, (unsigned char *)&uuid, sizeof(uuid) )) != S_OK) return hr;
len = format_guid( &uuid, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_guid_text_node( &uuid ))) return E_OUTOFMEMORY;
break;
case RECORD_UINT64_TEXT:
case RECORD_UINT64_TEXT_WITH_ENDELEMENT:
{
UINT64 val_uint64;
if ((hr = read_bytes( reader, (unsigned char *)&val_uint64, sizeof(val_uint64) )) != S_OK) return hr;
len = format_uint64( &val_uint64, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_uint64_text_node( val_uint64 ))) return E_OUTOFMEMORY;
break;
}
case RECORD_BOOL_TEXT:
case RECORD_BOOL_TEXT_WITH_ENDELEMENT:
{
BOOL val_bool;
if ((hr = read_bytes( reader, (unsigned char *)&val_bool, sizeof(val_bool) )) != S_OK) return hr;
len = format_bool( &val_bool, buf );
if (!(node = alloc_utf8_text_node( buf, len, NULL ))) return E_OUTOFMEMORY;
if (!(node = alloc_bool_text_node( !!val_bool ))) return E_OUTOFMEMORY;
break;
}
default:
ERR( "unhandled record type %02x\n", type );
return WS_E_NOT_SUPPORTED;
@ -2226,6 +2482,7 @@ static HRESULT read_text_bin( struct reader *reader )
if (!node)
{
if (!(node = alloc_utf8_text_node( NULL, len, &utf8 ))) return E_OUTOFMEMORY;
if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
{
free_node( node );

View File

@ -44,23 +44,11 @@ struct dictionary
struct dictionary dict_builtin DECLSPEC_HIDDEN;
const struct dictionary dict_builtin_static DECLSPEC_HIDDEN;
ULONG format_bool( const BOOL *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_int8( const INT8 *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_int16( const INT16 *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_int32( const INT32 *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_int64( const INT64 *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_uint64( const UINT64 *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_double( const double *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_datetime( const WS_DATETIME *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_guid( const GUID *, unsigned char * ) DECLSPEC_HIDDEN;
ULONG format_urn( const GUID *, unsigned char * ) DECLSPEC_HIDDEN;
const char *debugstr_xmlstr( const WS_XML_STRING * ) DECLSPEC_HIDDEN;
WS_XML_STRING *alloc_xml_string( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
WS_XML_STRING *dup_xml_string( const WS_XML_STRING * ) DECLSPEC_HIDDEN;
HRESULT add_xml_string( WS_XML_STRING * ) DECLSPEC_HIDDEN;
void free_xml_string( WS_XML_STRING * ) DECLSPEC_HIDDEN;
WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
HRESULT append_attribute( WS_XML_ELEMENT_NODE *, WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
void free_attribute( WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
WS_TYPE map_value_type( WS_VALUE_TYPE ) DECLSPEC_HIDDEN;
@ -71,6 +59,18 @@ ULONG get_type_size( WS_TYPE, const void * ) DECLSPEC_HIDDEN;
HRESULT read_header( WS_XML_READER *, const WS_XML_STRING *, const WS_XML_STRING *, WS_TYPE,
const void *, WS_READ_OPTION, WS_HEAP *, void *, ULONG ) DECLSPEC_HIDDEN;
WS_XML_UTF8_TEXT *alloc_utf8_text( const BYTE *, ULONG ) DECLSPEC_HIDDEN;
WS_XML_UTF16_TEXT *alloc_utf16_text( const BYTE *, ULONG ) DECLSPEC_HIDDEN;
WS_XML_BASE64_TEXT *alloc_base64_text( const BYTE *, ULONG ) DECLSPEC_HIDDEN;
WS_XML_BOOL_TEXT *alloc_bool_text( BOOL ) DECLSPEC_HIDDEN;
WS_XML_INT32_TEXT *alloc_int32_text( INT32 ) DECLSPEC_HIDDEN;
WS_XML_INT64_TEXT *alloc_int64_text( INT64 ) DECLSPEC_HIDDEN;
WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 ) DECLSPEC_HIDDEN;
WS_XML_DOUBLE_TEXT *alloc_double_text( double ) DECLSPEC_HIDDEN;
WS_XML_GUID_TEXT *alloc_guid_text( const GUID * ) DECLSPEC_HIDDEN;
WS_XML_UNIQUE_ID_TEXT *alloc_unique_id_text( const GUID * ) DECLSPEC_HIDDEN;
WS_XML_DATETIME_TEXT *alloc_datetime_text( const WS_DATETIME * ) DECLSPEC_HIDDEN;
#define INVALID_PARAMETER_INDEX 0xffff
HRESULT get_param_desc( const WS_STRUCT_DESCRIPTION *, USHORT, const WS_FIELD_DESCRIPTION ** ) DECLSPEC_HIDDEN;
HRESULT write_input_params( WS_XML_WRITER *, const WS_ELEMENT_DESCRIPTION *,

View File

@ -1609,7 +1609,7 @@ HRESULT WINAPI WsWriteStartElement( WS_XML_WRITER *handle, const WS_XML_STRING *
return hr;
}
ULONG format_bool( const BOOL *ptr, unsigned char *buf )
static ULONG format_bool( const BOOL *ptr, unsigned char *buf )
{
static const unsigned char bool_true[] = {'t','r','u','e'}, bool_false[] = {'f','a','l','s','e'};
if (*ptr)
@ -1621,22 +1621,22 @@ ULONG format_bool( const BOOL *ptr, unsigned char *buf )
return sizeof(bool_false);
}
ULONG format_int8( const INT8 *ptr, unsigned char *buf )
static ULONG format_int8( const INT8 *ptr, unsigned char *buf )
{
return wsprintfA( (char *)buf, "%d", *ptr );
}
ULONG format_int16( const INT16 *ptr, unsigned char *buf )
static ULONG format_int16( const INT16 *ptr, unsigned char *buf )
{
return wsprintfA( (char *)buf, "%d", *ptr );
}
ULONG format_int32( const INT32 *ptr, unsigned char *buf )
static ULONG format_int32( const INT32 *ptr, unsigned char *buf )
{
return wsprintfA( (char *)buf, "%d", *ptr );
}
ULONG format_int64( const INT64 *ptr, unsigned char *buf )
static ULONG format_int64( const INT64 *ptr, unsigned char *buf )
{
return wsprintfA( (char *)buf, "%I64d", *ptr );
}
@ -1656,12 +1656,12 @@ static ULONG format_uint32( const UINT32 *ptr, unsigned char *buf )
return wsprintfA( (char *)buf, "%u", *ptr );
}
ULONG format_uint64( const UINT64 *ptr, unsigned char *buf )
static ULONG format_uint64( const UINT64 *ptr, unsigned char *buf )
{
return wsprintfA( (char *)buf, "%I64u", *ptr );
}
ULONG format_double( const double *ptr, unsigned char *buf )
static ULONG format_double( const double *ptr, unsigned char *buf )
{
#ifdef HAVE_POWL
static const long double precision = 0.0000000000000001;
@ -1758,7 +1758,7 @@ static inline int year_size( int year )
}
#define TZ_OFFSET 8
ULONG format_datetime( const WS_DATETIME *ptr, unsigned char *buf )
static ULONG format_datetime( const WS_DATETIME *ptr, unsigned char *buf )
{
static const char fmt[] = "%04u-%02u-%02uT%02u:%02u:%02u";
int day, hour, min, sec, sec_frac, month = 0, year = 1, tz_hour;
@ -1814,7 +1814,7 @@ ULONG format_datetime( const WS_DATETIME *ptr, unsigned char *buf )
return len;
}
ULONG format_guid( const GUID *ptr, unsigned char *buf )
static ULONG format_guid( const GUID *ptr, unsigned char *buf )
{
static const char fmt[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
return sprintf( (char *)buf, fmt, ptr->Data1, ptr->Data2, ptr->Data3,
@ -1822,7 +1822,7 @@ ULONG format_guid( const GUID *ptr, unsigned char *buf )
ptr->Data4[4], ptr->Data4[5], ptr->Data4[6], ptr->Data4[7] );
}
ULONG format_urn( const GUID *ptr, unsigned char *buf )
static ULONG format_urn( const GUID *ptr, unsigned char *buf )
{
static const char fmt[] = "urn:uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
return sprintf( (char *)buf, fmt, ptr->Data1, ptr->Data2, ptr->Data3,
@ -1875,9 +1875,11 @@ static ULONG encode_base64( const unsigned char *bin, ULONG len, unsigned char *
return i;
}
static HRESULT text_to_utf8text( const WS_XML_TEXT *text, const WS_XML_UTF8_TEXT *old, WS_XML_UTF8_TEXT **ret )
static HRESULT text_to_utf8text( const WS_XML_TEXT *text, const WS_XML_UTF8_TEXT *old, ULONG *offset,
WS_XML_UTF8_TEXT **ret )
{
ULONG len_old = old ? old->value.length : 0;
if (offset) *offset = len_old;
switch (text->textType)
{
@ -2016,10 +2018,136 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, const WS_XML_UTF8_TEXT
}
}
static HRESULT text_to_text( const WS_XML_TEXT *text, const WS_XML_TEXT *old, ULONG *offset, WS_XML_TEXT **ret )
{
if (offset) *offset = 0;
switch (text->textType)
{
case WS_XML_TEXT_TYPE_UTF8:
{
const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
const WS_XML_UTF8_TEXT *utf8_old = (const WS_XML_UTF8_TEXT *)old;
WS_XML_UTF8_TEXT *new;
ULONG len = utf8->value.length, len_old = utf8_old ? utf8_old->value.length : 0;
if (!(new = alloc_utf8_text( NULL, len_old + len ))) return E_OUTOFMEMORY;
if (utf8_old) memcpy( new->value.bytes, utf8_old->value.bytes, len_old );
memcpy( new->value.bytes + len_old, utf8->value.bytes, len );
if (offset) *offset = len_old;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_UTF16:
{
const WS_XML_UTF16_TEXT *utf16 = (const WS_XML_UTF16_TEXT *)text;
const WS_XML_UTF16_TEXT *utf16_old = (const WS_XML_UTF16_TEXT *)old;
WS_XML_UTF16_TEXT *new;
ULONG len = utf16->byteCount / sizeof(WCHAR);
ULONG len_old = utf16_old ? utf16_old->byteCount / sizeof(WCHAR) : 0;
if (len % sizeof(WCHAR)) return E_INVALIDARG;
if (!(new = alloc_utf16_text( NULL, len_old + len ))) return E_OUTOFMEMORY;
if (old) memcpy( new->bytes, utf16_old->bytes, len_old );
memcpy( new->bytes + len_old, utf16->bytes, len );
if (offset) *offset = len_old;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_BASE64:
{
const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text;
const WS_XML_BASE64_TEXT *base64_old = (const WS_XML_BASE64_TEXT *)old;
WS_XML_BASE64_TEXT *new;
ULONG len = base64->length, len_old = base64_old ? base64_old->length : 0;
if (!(new = alloc_base64_text( NULL, len_old + len ))) return E_OUTOFMEMORY;
if (base64_old) memcpy( new->bytes, base64_old->bytes, len_old );
memcpy( new->bytes + len_old, base64->bytes, len );
if (offset) *offset = len_old;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_BOOL:
{
const WS_XML_BOOL_TEXT *bool_text = (const WS_XML_BOOL_TEXT *)text;
WS_XML_BOOL_TEXT *new;
if (!(new = alloc_bool_text( bool_text->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_INT32:
{
const WS_XML_INT32_TEXT *int32_text = (const WS_XML_INT32_TEXT *)text;
WS_XML_INT32_TEXT *new;
if (!(new = alloc_int32_text( int32_text->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_INT64:
{
const WS_XML_INT64_TEXT *int64_text = (const WS_XML_INT64_TEXT *)text;
WS_XML_INT64_TEXT *new;
if (!(new = alloc_int64_text( int64_text->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_UINT64:
{
const WS_XML_UINT64_TEXT *uint64_text = (const WS_XML_UINT64_TEXT *)text;
WS_XML_UINT64_TEXT *new;
if (!(new = alloc_uint64_text( uint64_text->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_DOUBLE:
{
const WS_XML_DOUBLE_TEXT *double_text = (const WS_XML_DOUBLE_TEXT *)text;
WS_XML_DOUBLE_TEXT *new;
if (!(new = alloc_double_text( double_text->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_GUID:
{
const WS_XML_GUID_TEXT *id = (const WS_XML_GUID_TEXT *)text;
WS_XML_GUID_TEXT *new;
if (!(new = alloc_guid_text( &id->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_UNIQUE_ID:
{
const WS_XML_UNIQUE_ID_TEXT *id = (const WS_XML_UNIQUE_ID_TEXT *)text;
WS_XML_UNIQUE_ID_TEXT *new;
if (!(new = alloc_unique_id_text( &id->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
case WS_XML_TEXT_TYPE_DATETIME:
{
const WS_XML_DATETIME_TEXT *dt = (const WS_XML_DATETIME_TEXT *)text;
WS_XML_DATETIME_TEXT *new;
if (!(new = alloc_datetime_text( &dt->value ))) return E_OUTOFMEMORY;
*ret = &new->text;
return S_OK;
}
default:
FIXME( "unhandled text type %u\n", text->textType );
return E_NOTIMPL;
}
}
static HRESULT write_set_attribute_value( struct writer *writer, const WS_XML_TEXT *value )
{
WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
WS_XML_UTF8_TEXT *new, *old = (WS_XML_UTF8_TEXT *)elem->attributes[elem->attributeCount - 1]->value;
HRESULT hr;
switch (value->textType)
@ -2037,7 +2165,7 @@ static HRESULT write_set_attribute_value( struct writer *writer, const WS_XML_TE
case WS_XML_TEXT_TYPE_GUID:
case WS_XML_TEXT_TYPE_UNIQUE_ID:
case WS_XML_TEXT_TYPE_DATETIME:
if (old) return WS_E_INVALID_OPERATION;
if (elem->attributes[elem->attributeCount - 1]->value) return WS_E_INVALID_OPERATION;
break;
default:
@ -2045,10 +2173,28 @@ static HRESULT write_set_attribute_value( struct writer *writer, const WS_XML_TE
return E_NOTIMPL;
}
if ((hr = text_to_utf8text( value, old, &new )) != S_OK) return hr;
heap_free( old );
elem->attributes[elem->attributeCount - 1]->value = &new->text;
switch (writer->output_enc)
{
case WS_XML_WRITER_ENCODING_TYPE_TEXT:
{
WS_XML_UTF8_TEXT *new, *old = (WS_XML_UTF8_TEXT *)elem->attributes[elem->attributeCount - 1]->value;
if ((hr = text_to_utf8text( value, old, NULL, &new )) != S_OK) return hr;
heap_free( old );
elem->attributes[elem->attributeCount - 1]->value = &new->text;
break;
}
case WS_XML_WRITER_ENCODING_TYPE_BINARY:
{
WS_XML_TEXT *new, *old = elem->attributes[elem->attributeCount - 1]->value;
if ((hr = text_to_text( value, old, NULL, &new )) != S_OK) return hr;
heap_free( old );
elem->attributes[elem->attributeCount - 1]->value = new;
break;
}
default:
FIXME( "unhandled output encoding %u\n", writer->output_enc );
return E_NOTIMPL;
}
return S_OK;
}
@ -2057,7 +2203,6 @@ static HRESULT write_add_text_node( struct writer *writer, const WS_XML_TEXT *va
{
struct node *node;
WS_XML_TEXT_NODE *text;
WS_XML_UTF8_TEXT *utf8;
HRESULT hr;
if (node_type( writer->current ) != WS_XML_NODE_TYPE_ELEMENT &&
@ -2065,13 +2210,37 @@ static HRESULT write_add_text_node( struct writer *writer, const WS_XML_TEXT *va
node_type( writer->current ) != WS_XML_NODE_TYPE_CDATA) return WS_E_INVALID_FORMAT;
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return E_OUTOFMEMORY;
if ((hr = text_to_utf8text( value, NULL, &utf8 )) != S_OK)
{
heap_free( node );
return hr;
}
text = (WS_XML_TEXT_NODE *)node;
text->text = &utf8->text;
switch (writer->output_enc)
{
case WS_XML_WRITER_ENCODING_TYPE_TEXT:
{
WS_XML_UTF8_TEXT *new;
if ((hr = text_to_utf8text( value, NULL, NULL, &new )) != S_OK)
{
heap_free( node );
return hr;
}
text->text = &new->text;
break;
}
case WS_XML_WRITER_ENCODING_TYPE_BINARY:
{
WS_XML_TEXT *new;
if ((hr = text_to_text( value, NULL, NULL, &new )) != S_OK)
{
heap_free( node );
return hr;
}
text->text = new;
break;
}
default:
FIXME( "unhandled output encoding %u\n", writer->output_enc );
heap_free( node );
return E_NOTIMPL;
}
write_insert_node( writer, writer->current, node );
return S_OK;
@ -2146,24 +2315,40 @@ static HRESULT write_text( struct writer *writer, const WS_XML_TEXT *text, ULONG
static HRESULT write_text_node( struct writer *writer, const WS_XML_TEXT *text )
{
WS_XML_TEXT_NODE *node = (WS_XML_TEXT_NODE *)writer->current;
ULONG offset;
ULONG offset = 0;
HRESULT hr;
if ((hr = write_flush( writer )) != S_OK) return hr;
if (node_type( writer->current ) != WS_XML_NODE_TYPE_TEXT)
{
offset = 0;
if ((hr = write_add_text_node( writer, text )) != S_OK) return hr;
node = (WS_XML_TEXT_NODE *)writer->current;
}
else
{
WS_XML_UTF8_TEXT *new, *old = (WS_XML_UTF8_TEXT *)node->text;
offset = old->value.length;
if ((hr = text_to_utf8text( text, old, &new )) != S_OK) return hr;
heap_free( old );
node->text = &new->text;
switch (writer->output_enc)
{
case WS_XML_WRITER_ENCODING_TYPE_TEXT:
{
WS_XML_UTF8_TEXT *new, *old = (WS_XML_UTF8_TEXT *)node->text;
offset = old->value.length;
if ((hr = text_to_utf8text( text, old, &offset, &new )) != S_OK) return hr;
heap_free( old );
node->text = &new->text;
break;
}
case WS_XML_WRITER_ENCODING_TYPE_BINARY:
{
WS_XML_TEXT *new, *old = node->text;
if ((hr = text_to_text( text, old, &offset, &new )) != S_OK) return hr;
heap_free( old );
node->text = new;
break;
}
default:
FIXME( "unhandled output encoding %u\n", writer->output_enc );
return E_NOTIMPL;
}
}
if ((hr = write_text( writer, node->text, offset )) != S_OK) return hr;