[1/4] webservices: Add support for dictionary strings in the writer.

Hans Leidekker hans at codeweavers.com
Tue May 30 03:09:05 CDT 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/msg.c                 |  18 +++--
 dlls/webservices/reader.c              |  26 ++++--
 dlls/webservices/tests/Makefile.in     |   2 +-
 dlls/webservices/tests/writer.c        | 140 +++++++++++++++++++++++++++++++++
 dlls/webservices/webservices_private.h |   1 +
 dlls/webservices/writer.c              | 114 +++++++++++++++++++++------
 6 files changed, 263 insertions(+), 38 deletions(-)

diff --git a/dlls/webservices/msg.c b/dlls/webservices/msg.c
index ac955bd..2c6667a 100644
--- a/dlls/webservices/msg.c
+++ b/dlls/webservices/msg.c
@@ -467,17 +467,21 @@ static HRESULT get_env_namespace( WS_ENVELOPE_VERSION ver, WS_XML_STRING *str )
     case WS_ENVELOPE_VERSION_SOAP_1_1:
         str->bytes  = (BYTE *)ns_env_1_1;
         str->length = sizeof(ns_env_1_1)/sizeof(ns_env_1_1[0]) - 1;
-        return S_OK;
+        break;
 
     case WS_ENVELOPE_VERSION_SOAP_1_2:
         str->bytes  = (BYTE *)ns_env_1_2;
         str->length = sizeof(ns_env_1_2)/sizeof(ns_env_1_2[0]) - 1;
-        return S_OK;
+        break;
 
     default:
         ERR( "unhandled envelope version %u\n", ver );
         return E_NOTIMPL;
     }
+
+    str->dictionary = NULL;
+    str->id         = 0;
+    return S_OK;
 }
 
 static HRESULT get_addr_namespace( WS_ADDRESSING_VERSION ver, WS_XML_STRING *str )
@@ -487,22 +491,26 @@ static HRESULT get_addr_namespace( WS_ADDRESSING_VERSION ver, WS_XML_STRING *str
     case WS_ADDRESSING_VERSION_0_9:
         str->bytes  = (BYTE *)ns_addr_0_9;
         str->length = sizeof(ns_addr_0_9)/sizeof(ns_addr_0_9[0]) - 1;
-        return S_OK;
+        break;
 
     case WS_ADDRESSING_VERSION_1_0:
         str->bytes  = (BYTE *)ns_addr_1_0;
         str->length = sizeof(ns_addr_1_0)/sizeof(ns_addr_1_0[0]) - 1;
-        return S_OK;
+        break;
 
     case WS_ADDRESSING_VERSION_TRANSPORT:
         str->bytes  = NULL;
         str->length = 0;
-        return S_OK;
+        break;
 
     default:
         ERR( "unhandled addressing version %u\n", ver );
         return E_NOTIMPL;
     }
+
+    str->dictionary = NULL;
+    str->id         = 0;
+    return S_OK;
 }
 
 static const WS_XML_STRING *get_header_name( WS_HEADER_TYPE type )
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 7624eb9..6dd6de4 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -161,9 +161,9 @@ static WS_XML_ATTRIBUTE *dup_attribute( const WS_XML_ATTRIBUTE *src )
     dst->isXmlNs     = src->isXmlNs;
 
     if (!prefix) dst->prefix = NULL;
-    else if (!(dst->prefix = alloc_xml_string( prefix->bytes, prefix->length ))) goto error;
-    if (!(dst->localName = alloc_xml_string( localname->bytes, localname->length ))) goto error;
-    if (!(dst->ns = alloc_xml_string( ns->bytes, ns->length ))) goto error;
+    else if (!(dst->prefix = dup_xml_string( prefix ))) goto error;
+    if (!(dst->localName = dup_xml_string( localname ))) goto error;
+    if (!(dst->ns = dup_xml_string( ns ))) goto error;
 
     if (text)
     {
@@ -214,9 +214,9 @@ static struct node *dup_element_node( const WS_XML_ELEMENT_NODE *src )
     if (count && !(dst->attributes = dup_attributes( attrs, count ))) goto error;
     dst->attributeCount = count;
 
-    if (prefix && !(dst->prefix = alloc_xml_string( prefix->bytes, prefix->length ))) goto error;
-    if (localname && !(dst->localName = alloc_xml_string( localname->bytes, localname->length ))) goto error;
-    if (ns && !(dst->ns = alloc_xml_string( ns->bytes, ns->length ))) goto error;
+    if (prefix && !(dst->prefix = dup_xml_string( prefix ))) goto error;
+    if (localname && !(dst->localName = dup_xml_string( localname ))) goto error;
+    if (ns && !(dst->ns = dup_xml_string( ns ))) goto error;
     return node;
 
 error:
@@ -797,6 +797,20 @@ WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
     return ret;
 }
 
+WS_XML_STRING *dup_xml_string( const WS_XML_STRING *src )
+{
+    WS_XML_STRING *ret;
+
+    if (!src->dictionary) return alloc_xml_string( src->bytes, src->length );
+
+    if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
+    ret->length     = src->length;
+    ret->bytes      = src->bytes;
+    ret->dictionary = src->dictionary;
+    ret->id         = src->id;
+    return ret;
+}
+
 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *data, ULONG len )
 {
     WS_XML_UTF8_TEXT *ret;
diff --git a/dlls/webservices/tests/Makefile.in b/dlls/webservices/tests/Makefile.in
index 1adfecc..9b2e688 100644
--- a/dlls/webservices/tests/Makefile.in
+++ b/dlls/webservices/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL   = webservices.dll
-IMPORTS   = webservices user32 ws2_32
+IMPORTS   = webservices user32 rpcrt4 ws2_32
 
 C_SRCS = \
 	channel.c \
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 2102c15..3bf0886 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include "windows.h"
+#include "rpc.h"
 #include "webservices.h"
 #include "wine/test.h"
 
@@ -3592,6 +3593,144 @@ static void test_namespaces(void)
     WsFreeWriter( writer );
 }
 
+static const WS_XML_STRING *init_xmlstring_dict( WS_XML_DICTIONARY *dict, ULONG id, WS_XML_STRING *str )
+{
+    if (id >= dict->stringCount) return NULL;
+    str->length     = dict->strings[id].length;
+    str->bytes      = dict->strings[id].bytes;
+    str->dictionary = dict;
+    str->id         = id;
+    return str;
+}
+
+static void test_dictionary(void)
+{
+    static const char res[] =
+        {0x42,0x04,0x01};
+    static const char res2[] =
+        {0x42,0x06,0x01};
+    static const char res3[] =
+        {0x53,0x06,0x0b,0x01,'p',0x0a,0x01};
+    static const char res4[] =
+        {0x43,0x02,'p','2',0x06,0x0b,0x02,'p','2',0x0a,0x01};
+    static const char res100[] =
+        {0x42,0x06,0x06,0x06,0x98,0x00,0x01};
+    static const char res101[] =
+        {0x42,0x06,0x1b,0x06,0x98,0x00,0x0b,0x01,'p',0x0a,0x01};
+    static const char res102[] =
+        {0x42,0x06,0x07,0x02,'p','2',0x06,0x98,0x00,0x0b,0x02,'p','2',0x0a,0x01};
+    WS_XML_WRITER_BINARY_ENCODING bin = {{WS_XML_WRITER_ENCODING_TYPE_BINARY}};
+    WS_XML_WRITER_BUFFER_OUTPUT buf = {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER}};
+    WS_XML_STRING prefix, localname, ns, strings[6];
+    const WS_XML_STRING *prefix_ptr, *localname_ptr, *ns_ptr;
+    WS_XML_DICTIONARY dict;
+    WS_XML_WRITER *writer;
+    HRESULT hr;
+    ULONG i;
+    static const struct
+    {
+        ULONG       prefix;
+        ULONG       localname;
+        ULONG       ns;
+        const char *result;
+        int         len_result;
+    }
+    elem_tests[] =
+    {
+        { ~0u, 2, 0, res, sizeof(res) },    /* short dictionary element, invalid dict id */
+        { ~0u, 3, 0, res2, sizeof(res2) },  /* short dictionary element */
+        { 1, 3, 5, res3, sizeof(res3) },    /* single character prefix dictionary element */
+        { 4, 3, 5, res4, sizeof(res4) },    /* dictionary element */
+    };
+    static const struct
+    {
+        ULONG       prefix;
+        ULONG       localname;
+        ULONG       ns;
+        const char *result;
+        int         len_result;
+    }
+    attr_tests[] =
+    {
+        { ~0u, 3, 0, res100, sizeof(res100) },  /* short dictionary attribute */
+        { 1, 3, 5, res101, sizeof(res101) },    /* single character prefix dictionary attribute */
+        { 4, 3, 5, res102, sizeof(res102) },    /* dictionary attribute */
+    };
+
+    hr = WsCreateWriter( NULL, 0, &writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    strings[0].length     = 0;
+    strings[0].bytes      = NULL;
+    strings[0].dictionary = &dict;
+    strings[0].id         = 0;
+    strings[1].length     = 1;
+    strings[1].bytes      = (BYTE *)"p";
+    strings[1].dictionary = &dict;
+    strings[1].id         = 1;
+    strings[2].length     = 1;
+    strings[2].bytes      = (BYTE *)"t";
+    strings[2].dictionary = &dict;
+    strings[2].id         = ~0u;
+    strings[3].length     = 1;
+    strings[3].bytes      = (BYTE *)"u";
+    strings[3].dictionary = &dict;
+    strings[3].id         = 3;
+    strings[4].length     = 2;
+    strings[4].bytes      = (BYTE *)"p2";
+    strings[4].dictionary = &dict;
+    strings[4].id         = 4;
+    strings[5].length     = 2;
+    strings[5].bytes      = (BYTE *)"ns";
+    strings[5].dictionary = &dict;
+    strings[5].id         = 5;
+
+    UuidCreate( &dict.guid );
+    dict.strings     = strings;
+    dict.stringCount = sizeof(strings)/sizeof(strings[0]);
+    dict.isConst     = TRUE;
+
+    bin.staticDictionary = &dict;
+
+    for (i = 0; i < sizeof(elem_tests)/sizeof(elem_tests[0]); i++)
+    {
+        hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+        prefix_ptr = init_xmlstring_dict( &dict, elem_tests[i].prefix, &prefix );
+        localname_ptr = init_xmlstring_dict( &dict, elem_tests[i].localname, &localname );
+        ns_ptr = init_xmlstring_dict( &dict, elem_tests[i].ns, &ns );
+
+        hr = WsWriteStartElement( writer, prefix_ptr, localname_ptr, ns_ptr, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        hr = WsWriteEndElement( writer, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        if (hr == S_OK) check_output_bin( writer, elem_tests[i].result, elem_tests[i].len_result, __LINE__ );
+    }
+
+    for (i = 0; i < sizeof(attr_tests)/sizeof(attr_tests[0]); i++)
+    {
+        hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+        prefix_ptr = init_xmlstring_dict( &dict, attr_tests[i].prefix, &prefix );
+        localname_ptr = init_xmlstring_dict( &dict, attr_tests[i].localname, &localname );
+        ns_ptr = init_xmlstring_dict( &dict, attr_tests[i].ns, &ns );
+
+        hr = WsWriteStartElement( writer, NULL, &strings[3], &strings[0], NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        hr = WsWriteStartAttribute( writer, prefix_ptr, localname_ptr, ns_ptr, FALSE, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        hr = WsWriteEndAttribute( writer, NULL );
+        ok( hr == S_OK, "got %08x\n", hr );
+        hr = WsWriteEndElement( writer, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        if (hr == S_OK) check_output_bin( writer, attr_tests[i].result, attr_tests[i].len_result, __LINE__ );
+    }
+
+    WsFreeWriter( writer );
+}
+
 START_TEST(writer)
 {
     test_WsCreateWriter();
@@ -3631,4 +3770,5 @@ START_TEST(writer)
     test_WsWriteCharsUtf8();
     test_binary_encoding();
     test_namespaces();
+    test_dictionary();
 }
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index b1b2caa..d117eba 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -35,6 +35,7 @@ void free_xmlbuf( struct xmlbuf * ) 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;
 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;
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index bbd969d..d22d5e4 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -566,20 +566,12 @@ static HRESULT write_attribute_text( struct writer *writer, const WS_XML_ATTRIBU
     return hr;
 }
 
-static enum record_type get_attr_record_type( const WS_XML_ATTRIBUTE *attr )
-{
-    if (!attr->prefix || !attr->prefix->length) return RECORD_SHORT_ATTRIBUTE;
-    if (attr->prefix->length == 1 && attr->prefix->bytes[0] >= 'a' && attr->prefix->bytes[0] <= 'z')
-    {
-        return RECORD_PREFIX_ATTRIBUTE_A + attr->prefix->bytes[0] - 'a';
-    }
-    return RECORD_ATTRIBUTE;
-};
-
 static HRESULT write_int31( struct writer *writer, ULONG len )
 {
     HRESULT hr;
 
+    if (len > 0x7fffffff) return E_INVALIDARG;
+
     if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
     if (len < 0x80)
     {
@@ -630,6 +622,14 @@ static HRESULT write_string( struct writer *writer, const BYTE *bytes, ULONG len
     return S_OK;
 }
 
+static HRESULT write_dict_string( struct writer *writer, ULONG id )
+{
+    HRESULT hr;
+    if (id > 0x3fffffff) return E_INVALIDARG;
+    if ((hr = write_int31( writer, id << 1 )) != S_OK) return hr;
+    return S_OK;
+}
+
 static enum record_type get_text_record_type( const WS_XML_TEXT *text, BOOL attr )
 {
     const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)text;
@@ -660,11 +660,27 @@ static HRESULT write_attribute_value_bin( struct writer *writer, const WS_XML_TE
         return S_OK;
 
     default:
-        ERR( "unhandled record type %u\n", type );
+        ERR( "unhandled record type %02x\n", type );
         return WS_E_NOT_SUPPORTED;
     }
 }
 
+static enum record_type get_attr_record_type( const WS_XML_ATTRIBUTE *attr )
+{
+    if (!attr->prefix || !attr->prefix->length)
+    {
+        if (attr->localName->dictionary) return RECORD_SHORT_DICTIONARY_ATTRIBUTE;
+        return RECORD_SHORT_ATTRIBUTE;
+    }
+    if (attr->prefix->length == 1 && attr->prefix->bytes[0] >= 'a' && attr->prefix->bytes[0] <= 'z')
+    {
+        if (attr->localName->dictionary) return RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + attr->prefix->bytes[0] - 'a';
+        return RECORD_PREFIX_ATTRIBUTE_A + attr->prefix->bytes[0] - 'a';
+    }
+    if (attr->localName->dictionary) return RECORD_DICTIONARY_ATTRIBUTE;
+    return RECORD_ATTRIBUTE;
+};
+
 static HRESULT write_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUTE *attr )
 {
     enum record_type type = get_attr_record_type( attr );
@@ -678,6 +694,11 @@ static HRESULT write_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUT
         if ((hr = write_string( writer, attr->localName->bytes, attr->localName->length )) != S_OK) return hr;
         return write_attribute_value_bin( writer, attr->value );
     }
+    if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
+    {
+        if ((hr = write_dict_string( writer, attr->localName->id )) != S_OK) return hr;
+        return write_attribute_value_bin( writer, attr->value );
+    }
 
     switch (type)
     {
@@ -690,8 +711,17 @@ static HRESULT write_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUT
         if ((hr = write_string( writer, attr->localName->bytes, attr->localName->length )) != S_OK) return hr;
         break;
 
+    case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
+        if ((hr = write_dict_string( writer, attr->localName->id )) != S_OK) return hr;
+        break;
+
+    case RECORD_DICTIONARY_ATTRIBUTE:
+        if ((hr = write_string( writer, attr->prefix->bytes, attr->prefix->length )) != S_OK) return hr;
+        if ((hr = write_dict_string( writer, attr->localName->id )) != S_OK) return hr;
+        break;
+
     default:
-        ERR( "unhandled record type %u\n", type );
+        ERR( "unhandled record type %02x\n", type );
         return WS_E_NOT_SUPPORTED;
     }
 
@@ -789,7 +819,12 @@ static HRESULT write_namespace_attribute_text( struct writer *writer, const WS_X
 
 static enum record_type get_xmlns_record_type( const WS_XML_ATTRIBUTE *attr )
 {
-    if (!attr->prefix || !attr->prefix->length) return RECORD_SHORT_XMLNS_ATTRIBUTE;
+    if (!attr->prefix || !attr->prefix->length)
+    {
+        if (attr->ns->dictionary) return RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE;
+        return RECORD_SHORT_XMLNS_ATTRIBUTE;
+    }
+    if (attr->ns->dictionary) return RECORD_DICTIONARY_XMLNS_ATTRIBUTE;
     return RECORD_XMLNS_ATTRIBUTE;
 };
 
@@ -810,8 +845,15 @@ static HRESULT write_namespace_attribute_bin( struct writer *writer, const WS_XM
         if ((hr = write_string( writer, attr->prefix->bytes, attr->prefix->length )) != S_OK) return hr;
         break;
 
+    case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
+        return write_dict_string( writer, attr->ns->id );
+
+    case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
+        if ((hr = write_string( writer, attr->prefix->bytes, attr->prefix->length )) != S_OK) return hr;
+        return write_dict_string( writer, attr->ns->id );
+
     default:
-        ERR( "unhandled record type %u\n", type );
+        ERR( "unhandled record type %02x\n", type );
         return WS_E_NOT_SUPPORTED;
     }
 
@@ -841,12 +883,12 @@ static HRESULT add_namespace_attribute( struct writer *writer, const WS_XML_STRI
 
     attr->singleQuote = !!single;
     attr->isXmlNs = 1;
-    if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
+    if (prefix && !(attr->prefix = dup_xml_string( prefix )))
     {
         free_attribute( attr );
         return E_OUTOFMEMORY;
     }
-    if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
+    if (!(attr->ns = dup_xml_string( ns )))
     {
         free_attribute( attr );
         return E_OUTOFMEMORY;
@@ -889,7 +931,7 @@ static BOOL namespace_in_scope( const WS_XML_ELEMENT_NODE *elem, const WS_XML_ST
 static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING *ns )
 {
     WS_XML_STRING *str;
-    if (!(str = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
+    if (!(str = dup_xml_string( ns ))) return E_OUTOFMEMORY;
     heap_free( writer->current_ns );
     writer->current_ns = str;
     return S_OK;
@@ -989,11 +1031,17 @@ static HRESULT write_startelement_text( struct writer *writer )
 
 static enum record_type get_elem_record_type( const WS_XML_ELEMENT_NODE *elem )
 {
-    if (!elem->prefix || !elem->prefix->length) return RECORD_SHORT_ELEMENT;
+    if (!elem->prefix || !elem->prefix->length)
+    {
+        if (elem->localName->dictionary) return RECORD_SHORT_DICTIONARY_ELEMENT;
+        return RECORD_SHORT_ELEMENT;
+    }
     if (elem->prefix->length == 1 && elem->prefix->bytes[0] >= 'a' && elem->prefix->bytes[0] <= 'z')
     {
+        if (elem->localName->dictionary) return RECORD_PREFIX_DICTIONARY_ELEMENT_A + elem->prefix->bytes[0] - 'a';
         return RECORD_PREFIX_ELEMENT_A + elem->prefix->bytes[0] - 'a';
     }
+    if (elem->localName->dictionary) return RECORD_DICTIONARY_ELEMENT;
     return RECORD_ELEMENT;
 };
 
@@ -1011,6 +1059,11 @@ static HRESULT write_startelement_bin( struct writer *writer )
         if ((hr = write_string( writer, elem->localName->bytes, elem->localName->length )) != S_OK) return hr;
         return write_attributes( writer, elem );
     }
+    if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
+    {
+        if ((hr = write_dict_string( writer, elem->localName->id )) != S_OK) return hr;
+        return write_attributes( writer, elem );
+    }
 
     switch (type)
     {
@@ -1023,8 +1076,17 @@ static HRESULT write_startelement_bin( struct writer *writer )
         if ((hr = write_string( writer, elem->localName->bytes, elem->localName->length )) != S_OK) return hr;
         break;
 
+    case RECORD_SHORT_DICTIONARY_ELEMENT:
+        if ((hr = write_dict_string( writer, elem->localName->id )) != S_OK) return hr;
+        break;
+
+    case RECORD_DICTIONARY_ELEMENT:
+        if ((hr = write_string( writer, elem->prefix->bytes, elem->prefix->length )) != S_OK) return hr;
+        if ((hr = write_dict_string( writer, elem->localName->id )) != S_OK) return hr;
+        break;
+
     default:
-        ERR( "unhandled record type %u\n", type );
+        ERR( "unhandled record type %02x\n", type );
         return WS_E_NOT_SUPPORTED;
     }
 
@@ -1234,17 +1296,17 @@ static HRESULT write_add_attribute( struct writer *writer, const WS_XML_STRING *
     if (!prefix && ns->length) prefix = elem->prefix;
 
     attr->singleQuote = !!single;
-    if (prefix && !(attr->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
+    if (prefix && !(attr->prefix = dup_xml_string( prefix )))
     {
         free_attribute( attr );
         return E_OUTOFMEMORY;
     }
-    if (!(attr->localName = alloc_xml_string( localname->bytes, localname->length )))
+    if (!(attr->localName = dup_xml_string( localname )))
     {
         free_attribute( attr );
         return E_OUTOFMEMORY;
     }
-    if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length )))
+    if (!(attr->ns = dup_xml_string( ns )))
     {
         free_attribute( attr );
         return E_OUTOFMEMORY;
@@ -1439,17 +1501,17 @@ static HRESULT write_add_element_node( struct writer *writer, const WS_XML_STRIN
     if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
     elem = &node->hdr;
 
-    if (prefix && !(elem->prefix = alloc_xml_string( prefix->bytes, prefix->length )))
+    if (prefix && !(elem->prefix = dup_xml_string( prefix )))
     {
         free_node( node );
         return E_OUTOFMEMORY;
     }
-    if (!(elem->localName = alloc_xml_string( localname->bytes, localname->length )))
+    if (!(elem->localName = dup_xml_string( localname )))
     {
         free_node( node );
         return E_OUTOFMEMORY;
     }
-    if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length )))
+    if (!(elem->ns = dup_xml_string( ns )))
     {
         free_node( node );
         return E_OUTOFMEMORY;
@@ -1999,7 +2061,7 @@ static HRESULT write_text_bin( struct writer *writer, const WS_XML_TEXT *text, U
         return S_OK;
 
     default:
-        FIXME( "unhandled record type %u\n", type );
+        FIXME( "unhandled record type %02x\n", type );
         return WS_E_NOT_SUPPORTED;
     }
 }
-- 
2.1.4




More information about the wine-patches mailing list