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;
|
||||
}
|
||||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue