diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index bf05352d8c9..5bc862e5bf1 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -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 ); diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index 68837db642b..38d57862887 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -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 *, diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c index b4793f91a5b..8ce59a1e1cc 100644 --- a/dlls/webservices/writer.c +++ b/dlls/webservices/writer.c @@ -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;