Nikolay Sivov : msxml3: Implement put_nodeTypedValue() for bin. base64 type and commonly used input vartypes.

Alexandre Julliard julliard at winehq.org
Fri Jun 29 14:24:27 CDT 2012


Module: wine
Branch: master
Commit: a11ce7945ade91ad2681febd794f072a3691597d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=a11ce7945ade91ad2681febd794f072a3691597d

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Jun 29 11:10:55 2012 +0400

msxml3: Implement put_nodeTypedValue() for bin.base64 type and commonly used input vartypes.

---

 dlls/msxml3/element.c      |  114 ++++++++++++++++++++++++++++++++++++++++++--
 dlls/msxml3/tests/domdoc.c |   94 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 202 insertions(+), 6 deletions(-)

diff --git a/dlls/msxml3/element.c b/dlls/msxml3/element.c
index 26bfd0c..db6b283 100644
--- a/dlls/msxml3/element.c
+++ b/dlls/msxml3/element.c
@@ -732,6 +732,75 @@ static HRESULT WINAPI domelem_get_nodeTypedValue(
     return hr;
 }
 
+static HRESULT encode_base64(const BYTE *buf, int len, BSTR *ret)
+{
+    static const char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+    const BYTE *d = buf;
+    int bytes, pad_bytes, div, i;
+    DWORD needed;
+    WCHAR *ptr;
+
+    bytes = (len*8 + 5)/6;
+    pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
+
+    TRACE("%d, bytes is %d, pad bytes is %d\n", len, bytes, pad_bytes);
+    needed = bytes + pad_bytes + 1;
+
+    *ret = SysAllocStringLen(NULL, needed);
+    if (!*ret) return E_OUTOFMEMORY;
+
+    /* Three bytes of input give 4 chars of output */
+    div = len / 3;
+
+    ptr = *ret;
+    i = 0;
+    while (div > 0)
+    {
+        /* first char is the first 6 bits of the first byte*/
+        *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
+        /* second char is the last 2 bits of the first byte and the first 4
+         * bits of the second byte */
+        *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
+        /* third char is the last 4 bits of the second byte and the first 2
+         * bits of the third byte */
+        *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
+        /* fourth char is the remaining 6 bits of the third byte */
+        *ptr++ = b64[   d[2]       & 0x3f];
+        i += 4;
+        d += 3;
+        div--;
+    }
+
+    switch (pad_bytes)
+    {
+        case 1:
+            /* first char is the first 6 bits of the first byte*/
+            *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
+            /* second char is the last 2 bits of the first byte and the first 4
+             * bits of the second byte */
+            *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
+            /* third char is the last 4 bits of the second byte padded with
+             * two zeroes */
+            *ptr++ = b64[ ((d[1] << 2) & 0x3c) ];
+            /* fourth char is a = to indicate one byte of padding */
+            *ptr++ = '=';
+            break;
+        case 2:
+            /* first char is the first 6 bits of the first byte*/
+            *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
+            /* second char is the last 2 bits of the first byte padded with
+             * four zeroes*/
+            *ptr++ = b64[ ((d[0] << 4) & 0x30)];
+            /* third char is = to indicate padding */
+            *ptr++ = '=';
+            /* fourth char is = to indicate padding */
+            *ptr++ = '=';
+            break;
+    }
+
+    return S_OK;
+}
+
 static HRESULT WINAPI domelem_put_nodeTypedValue(
     IXMLDOMElement *iface,
     VARIANT value)
@@ -743,9 +812,10 @@ static HRESULT WINAPI domelem_put_nodeTypedValue(
     TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
 
     dt = element_get_dt(get_element(This));
-    /* for untyped node coerce to BSTR and set */
-    if (dt == DT_INVALID)
+    switch (dt)
     {
+    /* for untyped node coerce to BSTR and set */
+    case DT_INVALID:
         if (V_VT(&value) != VT_BSTR)
         {
             VARIANT content;
@@ -759,9 +829,43 @@ static HRESULT WINAPI domelem_put_nodeTypedValue(
         }
         else
             hr = node_set_content(&This->node, V_BSTR(&value));
-    }
-    else
-    {
+        break;
+    case DT_BIN_BASE64:
+        if (V_VT(&value) == VT_BSTR)
+            hr = node_set_content(&This->node, V_BSTR(&value));
+        else if (V_VT(&value) == (VT_UI1|VT_ARRAY))
+        {
+            UINT dim = SafeArrayGetDim(V_ARRAY(&value));
+            LONG lbound, ubound;
+            BSTR encoded;
+            BYTE *ptr;
+            int len;
+
+            if (dim > 1)
+                FIXME("unexpected array dimension count %u\n", dim);
+
+            SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
+            SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
+
+            len = (ubound - lbound + 1)*SafeArrayGetElemsize(V_ARRAY(&value));
+
+            hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
+            if (FAILED(hr)) return hr;
+
+            hr = encode_base64(ptr, len, &encoded);
+            SafeArrayUnaccessData(V_ARRAY(&value));
+            if (FAILED(hr)) return hr;
+
+            hr = node_set_content(&This->node, encoded);
+            SysFreeString(encoded);
+        }
+        else
+        {
+            FIXME("unhandled variant type %d for dt:%s\n", V_VT(&value), debugstr_dt(dt));
+            return E_NOTIMPL;
+        }
+        break;
+    default:
         FIXME("not implemented for dt:%s\n", debugstr_dt(dt));
         return E_NOTIMPL;
     }
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 4bbbe56..7a02e19 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -9076,8 +9076,13 @@ static void test_put_nodeTypedValue(void)
 {
     IXMLDOMDocument *doc;
     IXMLDOMElement *elem;
-    VARIANT type;
+    VARIANT type, value;
+    LONG ubound, lbound;
+    IXMLDOMNode *node;
+    SAFEARRAY *array;
     HRESULT hr;
+    BYTE *ptr;
+    BSTR str;
 
     doc = create_document(&IID_IXMLDOMDocument);
     if (!doc) return;
@@ -9110,6 +9115,93 @@ static void test_put_nodeTypedValue(void)
        "got %s, expected \"1\"\n", wine_dbgstr_w(V_BSTR(&type)));
     VariantClear(&type);
 
+    hr = IXMLDOMElement_get_firstChild(elem, &node);
+    EXPECT_HR(hr, S_OK);
+    hr = IXMLDOMElement_removeChild(elem, node, NULL);
+    EXPECT_HR(hr, S_OK);
+    IXMLDOMNode_Release(node);
+
+    hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)elem, NULL);
+    EXPECT_HR(hr, S_OK);
+
+    /* bin.base64 */
+    hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.base64"));
+    EXPECT_HR(hr, S_OK);
+
+    V_VT(&value) = VT_BSTR;
+    V_BSTR(&value) = _bstr_("ABCD");
+    hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
+    EXPECT_HR(hr, S_OK);
+
+    V_VT(&value) = VT_EMPTY;
+    hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
+    EXPECT_HR(hr, S_OK);
+    ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
+    ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
+    ubound = 0;
+    hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
+    EXPECT_HR(hr, S_OK);
+    ok(ubound == 2, "got %d\n", ubound);
+    lbound = 0;
+    hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
+    EXPECT_HR(hr, S_OK);
+    ok(lbound == 0, "got %d\n", lbound);
+    hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
+    EXPECT_HR(hr, S_OK);
+    ok(ptr[0] == 0, "got %x\n", ptr[0]);
+    ok(ptr[1] == 0x10, "got %x\n", ptr[1]);
+    ok(ptr[2] == 0x83, "got %x\n", ptr[2]);
+    SafeArrayUnaccessData(V_ARRAY(&value));
+    VariantClear(&value);
+
+    /* when set as VT_BSTR it's stored as is */
+    hr = IXMLDOMElement_get_firstChild(elem, &node);
+    EXPECT_HR(hr, S_OK);
+    hr = IXMLDOMNode_get_text(node, &str);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(str, _bstr_("ABCD")), "%s\n", wine_dbgstr_w(str));
+    IXMLDOMNode_Release(node);
+
+    array = SafeArrayCreateVector(VT_UI1, 0, 7);
+    hr = SafeArrayAccessData(array, (void*)&ptr);
+    EXPECT_HR(hr, S_OK);
+    memcpy(ptr, "dGVzdA=", strlen("dGVzdA="));
+    SafeArrayUnaccessData(V_ARRAY(&value));
+
+    V_VT(&value) = VT_UI1|VT_ARRAY;
+    V_ARRAY(&value) = array;
+    hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
+    EXPECT_HR(hr, S_OK);
+
+    V_VT(&value) = VT_EMPTY;
+    hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
+    EXPECT_HR(hr, S_OK);
+    ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
+    ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
+    ubound = 0;
+    hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
+    EXPECT_HR(hr, S_OK);
+    ok(ubound == 6, "got %d\n", ubound);
+    lbound = 0;
+    hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
+    EXPECT_HR(hr, S_OK);
+    ok(lbound == 0, "got %d\n", lbound);
+    hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
+    EXPECT_HR(hr, S_OK);
+    ok(!memcmp(ptr, "dGVzdA=", strlen("dGVzdA=")), "got wrong data, %s\n", ptr);
+    SafeArrayUnaccessData(V_ARRAY(&value));
+    VariantClear(&value);
+
+    /* if set with VT_UI1|VT_ARRAY it's encoded */
+    hr = IXMLDOMElement_get_firstChild(elem, &node);
+    EXPECT_HR(hr, S_OK);
+    hr = IXMLDOMNode_get_text(node, &str);
+    EXPECT_HR(hr, S_OK);
+    ok(!lstrcmpW(str, _bstr_("ZEdWemRBPQ==")), "%s\n", wine_dbgstr_w(str));
+    IXMLDOMNode_Release(node);
+
+    SafeArrayDestroyData(array);
+
     IXMLDOMElement_Release(elem);
     IXMLDOMDocument_Release(doc);
     free_bstrs();




More information about the wine-cvs mailing list