[3/3] webservices: Add support for writing WS_BYTES values.

Hans Leidekker hans at codeweavers.com
Tue Oct 4 06:28:36 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/tests/writer.c | 100 ++++++++++++++++++++++------------------
 dlls/webservices/writer.c       |  75 ++++++++++++++++++++++++++++--
 2 files changed, 127 insertions(+), 48 deletions(-)

diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index c817615..3bed673 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -574,6 +574,17 @@ static void test_WsWriteType(void)
     WsFreeWriter( writer );
 }
 
+static void prepare_basic_type_test( WS_XML_WRITER *writer )
+{
+    WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
+    HRESULT hr;
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+}
+
 static void test_basic_type(void)
 {
     static WCHAR testW[] = {'t','e','s','t',0};
@@ -583,6 +594,7 @@ static void test_basic_type(void)
     GUID guid;
     WCHAR *str;
     WS_STRING string;
+    WS_BYTES bytes;
     ULONG i;
     static const struct
     {
@@ -615,12 +627,7 @@ static void test_basic_type(void)
     /* element content type mapping */
     for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
     {
-        hr = set_output( writer );
-        ok( hr == S_OK, "got %08x\n", hr );
-
-        hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
-        ok( hr == S_OK, "got %08x\n", hr );
-
+        prepare_basic_type_test( writer );
         hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
                           WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
         ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -635,12 +642,7 @@ static void test_basic_type(void)
     {
         const INT64 *ptr = &tests[i].val;
 
-        hr = set_output( writer );
-        ok( hr == S_OK, "got %08x\n", hr );
-
-        hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
-        ok( hr == S_OK, "got %08x\n", hr );
-
+        prepare_basic_type_test( writer );
         hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
                           WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
         ok( hr == S_OK, "%u: got %08x\n", i, hr );
@@ -653,12 +655,7 @@ static void test_basic_type(void)
     /* attribute type mapping */
     for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
     {
-        hr = set_output( writer );
-        ok( hr == S_OK, "got %08x\n", hr );
-
-        hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
-        ok( hr == S_OK, "got %08x\n", hr );
-
+        prepare_basic_type_test( writer );
         hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
         ok( hr == S_OK, "got %08x\n", hr );
 
@@ -674,67 +671,80 @@ static void test_basic_type(void)
         check_output( writer, tests[i].result2, __LINE__ );
     }
 
-    hr = set_output( writer );
-    ok( hr == S_OK, "got %08x\n", hr );
-
-    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
-    ok( hr == S_OK, "got %08x\n", hr );
-
+    prepare_basic_type_test( writer );
     memset( &guid, 0, sizeof(guid) );
     hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
                       &guid, sizeof(guid), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
-
     hr = WsWriteEndElement( writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
     check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
 
-    hr = set_output( writer );
-    ok( hr == S_OK, "got %08x\n", hr );
-
-    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
-    ok( hr == S_OK, "got %08x\n", hr );
-
+    prepare_basic_type_test( writer );
     string.chars  = testW;
     string.length = 4;
     hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
                       &string, sizeof(string), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
-
     hr = WsWriteEndElement( writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
     check_output( writer, "<t>test</t>", __LINE__ );
 
-    hr = set_output( writer );
-    ok( hr == S_OK, "got %08x\n", hr );
-
-    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
-    ok( hr == S_OK, "got %08x\n", hr );
-
+    prepare_basic_type_test( writer );
     str = testW;
     hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
                       &str, sizeof(str), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<t>test</t>", __LINE__ );
 
+    prepare_basic_type_test( writer );
+    xmlstr.bytes  = (BYTE *)"test";
+    xmlstr.length = 4;
+    hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
+                      &xmlstr, sizeof(xmlstr), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
     hr = WsWriteEndElement( writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
     check_output( writer, "<t>test</t>", __LINE__ );
 
-    hr = set_output( writer );
+    prepare_basic_type_test( writer );
+    bytes.bytes  = (BYTE *)"test";
+    bytes.length = 4;
+    hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
+                      &bytes, sizeof(bytes), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<t>dGVzdA==</t>", __LINE__ );
 
-    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    prepare_basic_type_test( writer );
+    bytes.length = 0;
+    hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
+                      &bytes, sizeof(bytes), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteEndElement( writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<t/>", __LINE__ );
 
-    xmlstr.bytes  = (BYTE *)"test";
-    xmlstr.length = 4;
-    hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
-                      &xmlstr, sizeof(xmlstr), NULL );
+    prepare_basic_type_test( writer );
+    bytes.bytes  = NULL;
+    hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
+                      &bytes, sizeof(bytes), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<t/>", __LINE__ );
 
+    prepare_basic_type_test( writer );
+    hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_NILLABLE_VALUE,
+                      &bytes, sizeof(bytes), NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
     hr = WsWriteEndElement( writer, NULL );
     ok( hr == S_OK, "got %08x\n", hr );
-    check_output( writer, "<t>test</t>", __LINE__ );
+    check_output( writer, "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>",
+                  __LINE__ );
 
     WsFreeWriter( writer );
 }
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 7a818eb..619ec2b 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -1265,6 +1265,38 @@ static ULONG format_urn( const GUID *ptr, unsigned char *buf )
                     ptr->Data4[4], ptr->Data4[5], ptr->Data4[6], ptr->Data4[7] );
 }
 
+static ULONG encode_base64( const unsigned char *bin, ULONG len, unsigned char *buf )
+{
+    static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    ULONG i = 0, x;
+
+    while (len > 0)
+    {
+        buf[i++] = base64[(bin[0] & 0xfc) >> 2];
+        x = (bin[0] & 3) << 4;
+        if (len == 1)
+        {
+            buf[i++] = base64[x];
+            buf[i++] = '=';
+            buf[i++] = '=';
+            break;
+        }
+        buf[i++] = base64[x | ((bin[1] & 0xf0) >> 4)];
+        x = (bin[1] & 0x0f) << 2;
+        if (len == 2)
+        {
+            buf[i++] = base64[x];
+            buf[i++] = '=';
+            break;
+        }
+        buf[i++] = base64[x | ((bin[2] & 0xc0) >> 6)];
+        buf[i++] = base64[bin[2] & 0x3f];
+        bin += 3;
+        len -= 3;
+    }
+    return i;
+}
+
 static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret )
 {
     switch (text->textType)
@@ -1287,6 +1319,14 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret
         WideCharToMultiByte( CP_UTF8, 0, str, len, (char *)(*ret)->value.bytes, (*ret)->value.length, NULL, NULL );
         return S_OK;
     }
+    case WS_XML_TEXT_TYPE_BASE64:
+    {
+        const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text;
+        ULONG len = ((4 * base64->length / 3) + 3) & ~3;
+        if (!(*ret = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
+        (*ret)->value.length = encode_base64( base64->bytes, base64->length, (*ret)->value.bytes );
+        return S_OK;
+    }
     case WS_XML_TEXT_TYPE_BOOL:
     {
         const WS_XML_BOOL_TEXT *bool_text = (const WS_XML_BOOL_TEXT *)text;
@@ -1837,6 +1877,32 @@ static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
     return write_type_text( writer, mapping, &utf16.text );
 }
 
+static HRESULT write_type_bytes( struct writer *writer, WS_TYPE_MAPPING mapping,
+                                 const WS_BYTES_DESCRIPTION *desc, WS_WRITE_OPTION option,
+                                 const void *value, ULONG size )
+{
+    WS_XML_BASE64_TEXT base64;
+    const WS_BYTES *ptr;
+    HRESULT hr;
+
+    if (desc)
+    {
+        FIXME( "description not supported\n" );
+        return E_NOTIMPL;
+    }
+
+    if (!option) return E_INVALIDARG;
+    if ((hr = get_value_ptr( option, value, size, sizeof(WS_BYTES), (const void **)&ptr )) != S_OK) return hr;
+    if ((option == WS_WRITE_NILLABLE_VALUE && is_nil_value( value, size )) ||
+        (option == WS_WRITE_NILLABLE_POINTER && !ptr)) return write_add_nil_attribute( writer );
+    if (!ptr->length) return S_OK;
+
+    base64.text.textType = WS_XML_TEXT_TYPE_BASE64;
+    base64.bytes         = ptr->bytes;
+    base64.length        = ptr->length;
+    return write_type_text( writer, mapping, &base64.text );
+}
+
 static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING mapping,
                                       const WS_XML_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option,
                                       const void *value, ULONG size )
@@ -1996,9 +2062,6 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
 {
     switch (type)
     {
-    case WS_STRUCT_TYPE:
-        return write_type_struct( writer, mapping, desc, option, value, size );
-
     case WS_BOOL_TYPE:
         return write_type_bool( writer, mapping, desc, option, value, size );
 
@@ -2038,9 +2101,15 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
     case WS_WSZ_TYPE:
         return write_type_wsz( writer, mapping, desc, option, value, size );
 
+    case WS_BYTES_TYPE:
+        return write_type_bytes( writer, mapping, desc, option, value, size );
+
     case WS_XML_STRING_TYPE:
         return write_type_xml_string( writer, mapping, desc, option, value, size );
 
+    case WS_STRUCT_TYPE:
+        return write_type_struct( writer, mapping, desc, option, value, size );
+
     default:
         FIXME( "type %u not supported\n", type );
         return E_NOTIMPL;
-- 
2.1.4




More information about the wine-patches mailing list