msxml3: Implement put_nodeTypedValue() for bin.base64 type and commonly used input vartypes.
This commit is contained in:
parent
1796632166
commit
a11ce7945a
|
@ -732,6 +732,75 @@ static HRESULT WINAPI domelem_get_nodeTypedValue(
|
||||||
return hr;
|
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(
|
static HRESULT WINAPI domelem_put_nodeTypedValue(
|
||||||
IXMLDOMElement *iface,
|
IXMLDOMElement *iface,
|
||||||
VARIANT value)
|
VARIANT value)
|
||||||
|
@ -743,9 +812,10 @@ static HRESULT WINAPI domelem_put_nodeTypedValue(
|
||||||
TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
|
TRACE("(%p)->(%s)\n", This, debugstr_variant(&value));
|
||||||
|
|
||||||
dt = element_get_dt(get_element(This));
|
dt = element_get_dt(get_element(This));
|
||||||
/* for untyped node coerce to BSTR and set */
|
switch (dt)
|
||||||
if (dt == DT_INVALID)
|
|
||||||
{
|
{
|
||||||
|
/* for untyped node coerce to BSTR and set */
|
||||||
|
case DT_INVALID:
|
||||||
if (V_VT(&value) != VT_BSTR)
|
if (V_VT(&value) != VT_BSTR)
|
||||||
{
|
{
|
||||||
VARIANT content;
|
VARIANT content;
|
||||||
|
@ -759,9 +829,43 @@ static HRESULT WINAPI domelem_put_nodeTypedValue(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
hr = node_set_content(&This->node, V_BSTR(&value));
|
hr = node_set_content(&This->node, V_BSTR(&value));
|
||||||
}
|
break;
|
||||||
else
|
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));
|
FIXME("not implemented for dt:%s\n", debugstr_dt(dt));
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9076,8 +9076,13 @@ static void test_put_nodeTypedValue(void)
|
||||||
{
|
{
|
||||||
IXMLDOMDocument *doc;
|
IXMLDOMDocument *doc;
|
||||||
IXMLDOMElement *elem;
|
IXMLDOMElement *elem;
|
||||||
VARIANT type;
|
VARIANT type, value;
|
||||||
|
LONG ubound, lbound;
|
||||||
|
IXMLDOMNode *node;
|
||||||
|
SAFEARRAY *array;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
BYTE *ptr;
|
||||||
|
BSTR str;
|
||||||
|
|
||||||
doc = create_document(&IID_IXMLDOMDocument);
|
doc = create_document(&IID_IXMLDOMDocument);
|
||||||
if (!doc) return;
|
if (!doc) return;
|
||||||
|
@ -9110,6 +9115,93 @@ static void test_put_nodeTypedValue(void)
|
||||||
"got %s, expected \"1\"\n", wine_dbgstr_w(V_BSTR(&type)));
|
"got %s, expected \"1\"\n", wine_dbgstr_w(V_BSTR(&type)));
|
||||||
VariantClear(&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);
|
IXMLDOMElement_Release(elem);
|
||||||
IXMLDOMDocument_Release(doc);
|
IXMLDOMDocument_Release(doc);
|
||||||
free_bstrs();
|
free_bstrs();
|
||||||
|
|
Loading…
Reference in New Issue