msxml3: Implement put_nodeTypedValue() for bin.base64 type and commonly used input vartypes
Nikolay Sivov
nsivov at codeweavers.com
Fri Jun 29 03:16:21 CDT 2012
Encoder part stolen from crypt32
-------------- next part --------------
>From dae1b46f48e65e5ba4c85b1a53cc8b9acaae6364 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri, 29 Jun 2012 11:10:55 +0400
Subject: [PATCH 2/2] Implement put_nodeTypedValue() for bin.base64 type and commonly used input vartypes
---
dlls/msxml3/element.c | 114 ++++++++++++++++++++++++++++++++++++++++++--
dlls/msxml3/tests/domdoc.c | 97 +++++++++++++++++++++++++++++++++++++-
2 files changed, 205 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..895c1b8 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -9076,8 +9076,14 @@ 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;
+ int len;
doc = create_document(&IID_IXMLDOMDocument);
if (!doc) return;
@@ -9110,6 +9116,95 @@ 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);
+ len = (ubound - lbound)*SafeArrayGetElemsize(V_ARRAY(&value));
+ 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);
+ len = (ubound - lbound)*SafeArrayGetElemsize(V_ARRAY(&value));
+ 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();
--
1.5.6.5
More information about the wine-patches
mailing list