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

This commit is contained in:
Nikolay Sivov 2012-06-29 11:10:55 +04:00 committed by Alexandre Julliard
parent 1796632166
commit a11ce7945a
2 changed files with 202 additions and 6 deletions

View file

@ -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;
}

View file

@ -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();