Commit 2a0c37d8 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

oleaut32: Correctly handle NULLs embedded in BSTRs, with tests.

parent 22d7f141
...@@ -4898,8 +4898,8 @@ static void test_VarBstrFromDec(void) ...@@ -4898,8 +4898,8 @@ static void test_VarBstrFromDec(void)
#define _VARBSTRCMP(left,right,lcid,flags,result) \ #define _VARBSTRCMP(left,right,lcid,flags,result) \
hres = pVarBstrCmp(left,right,lcid,flags); \ hres = pVarBstrCmp(left,right,lcid,flags); \
ok(hres == result, "VarBstrCmp: expected " #result ", got hres=0x%lx\n", hres) ok(hres == result, "VarBstrCmp: expected " #result ", got hres=0x%lx\n", hres)
#define VARBSTRCMP(left,right,result) \ #define VARBSTRCMP(left,right,flags,result) \
_VARBSTRCMP(left,right,lcid,0,result) _VARBSTRCMP(left,right,lcid,flags,result)
static void test_VarBstrCmp(void) static void test_VarBstrCmp(void)
{ {
...@@ -4907,7 +4907,11 @@ static void test_VarBstrCmp(void) ...@@ -4907,7 +4907,11 @@ static void test_VarBstrCmp(void)
HRESULT hres; HRESULT hres;
static const WCHAR sz[] = {'W','u','r','s','c','h','t','\0'}; static const WCHAR sz[] = {'W','u','r','s','c','h','t','\0'};
static const WCHAR szempty[] = {'\0'}; static const WCHAR szempty[] = {'\0'};
BSTR bstr, bstrempty; static const WCHAR sz1[] = { 'a',0 };
static const WCHAR sz2[] = { 'A',0 };
static const WCHAR s1[] = { 'a',0 };
static const WCHAR s2[] = { 'a',0,'b' };
BSTR bstr, bstrempty, bstr2;
CHECKPTR(VarBstrCmp); CHECKPTR(VarBstrCmp);
...@@ -4916,13 +4920,34 @@ static void test_VarBstrCmp(void) ...@@ -4916,13 +4920,34 @@ static void test_VarBstrCmp(void)
bstrempty = SysAllocString(szempty); bstrempty = SysAllocString(szempty);
/* NULL handling. Yepp, MSDN is totaly wrong here */ /* NULL handling. Yepp, MSDN is totaly wrong here */
VARBSTRCMP(NULL,NULL,VARCMP_EQ); VARBSTRCMP(NULL,NULL,0,VARCMP_EQ);
VARBSTRCMP(bstr,NULL,VARCMP_GT); VARBSTRCMP(bstr,NULL,0,VARCMP_GT);
VARBSTRCMP(NULL,bstr,VARCMP_LT); VARBSTRCMP(NULL,bstr,0,VARCMP_LT);
/* NULL and empty string comparisions */ /* NULL and empty string comparisions */
VARBSTRCMP(bstrempty,NULL,VARCMP_EQ); VARBSTRCMP(bstrempty,NULL,0,VARCMP_EQ);
VARBSTRCMP(NULL,bstrempty,VARCMP_EQ); VARBSTRCMP(NULL,bstrempty,0,VARCMP_EQ);
SysFreeString(bstr);
bstr = SysAllocString(sz1);
bstr2 = SysAllocString(sz2);
VARBSTRCMP(bstr,bstr2,0,VARCMP_LT);
VARBSTRCMP(bstr,bstr2,NORM_IGNORECASE,VARCMP_EQ);
SysFreeString(bstr2);
/* These two strings are considered equal even though one is
* NULL-terminated and the other not.
*/
bstr2 = SysAllocStringLen(s1, sizeof(s1) / sizeof(WCHAR));
VARBSTRCMP(bstr,bstr2,0,VARCMP_EQ);
SysFreeString(bstr2);
/* These two strings are not equal */
bstr2 = SysAllocStringLen(s2, sizeof(s2) / sizeof(WCHAR));
VARBSTRCMP(bstr,bstr2,0,VARCMP_LT);
SysFreeString(bstr2);
SysFreeString(bstr);
} }
/* Get the internal representation of a BSTR */ /* Get the internal representation of a BSTR */
...@@ -5175,6 +5200,73 @@ static void test_BstrCopy(void) ...@@ -5175,6 +5200,73 @@ static void test_BstrCopy(void)
} }
} }
static void test_VarBstrCat(void)
{
static const WCHAR sz1[] = { 'a',0 };
static const WCHAR sz2[] = { 'b',0 };
static const WCHAR sz1sz2[] = { 'a','b',0 };
static const WCHAR s1[] = { 'a',0 };
static const WCHAR s2[] = { 'b',0 };
static const WCHAR s1s2[] = { 'a',0,'b',0 };
HRESULT ret;
BSTR str1, str2, res;
/* Crash
ret = VarBstrCat(NULL, NULL, NULL);
*/
/* Concatenation of two NULL strings works */
ret = VarBstrCat(NULL, NULL, &res);
ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
ok(res != NULL, "Expected a string\n");
ok(SysStringLen(res) == 0, "Expected a 0-length string\n");
SysFreeString(res);
str1 = SysAllocString(sz1);
/* Concatenation with one NULL arg */
ret = VarBstrCat(NULL, str1, &res);
ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
ok(res != NULL, "Expected a string\n");
ok(SysStringLen(res) == SysStringLen(str1), "Unexpected length\n");
ok(!memcmp(res, sz1, SysStringLen(str1)), "Unexpected value\n");
SysFreeString(res);
ret = VarBstrCat(str1, NULL, &res);
ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
ok(res != NULL, "Expected a string\n");
ok(SysStringLen(res) == SysStringLen(str1), "Unexpected length\n");
ok(!memcmp(res, sz1, SysStringLen(str1)), "Unexpected value\n");
SysFreeString(res);
/* Concatenation of two zero-terminated strings */
str2 = SysAllocString(sz2);
ret = VarBstrCat(str1, str2, &res);
ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
ok(res != NULL, "Expected a string\n");
ok(SysStringLen(res) == sizeof(sz1sz2) / sizeof(WCHAR) - 1,
"Unexpected length\n");
ok(!memcmp(res, sz1sz2, sizeof(sz1sz2)), "Unexpected value\n");
SysFreeString(res);
SysFreeString(str2);
SysFreeString(str1);
/* Concatenation of two strings with embedded NULLs */
str1 = SysAllocStringLen(s1, sizeof(s1) / sizeof(WCHAR));
str2 = SysAllocStringLen(s2, sizeof(s2) / sizeof(WCHAR));
ret = VarBstrCat(str1, str2, &res);
ok(ret == S_OK, "VarBstrCat failed: %08lx\n", ret);
ok(res != NULL, "Expected a string\n");
ok(SysStringLen(res) == sizeof(s1s2) / sizeof(WCHAR),
"Unexpected length\n");
ok(!memcmp(res, s1s2, sizeof(s1s2)), "Unexpected value\n");
SysFreeString(res);
SysFreeString(str2);
SysFreeString(str1);
}
/* IUnknown */ /* IUnknown */
static void test_IUnknownClear(void) static void test_IUnknownClear(void)
...@@ -5940,6 +6032,7 @@ START_TEST(vartype) ...@@ -5940,6 +6032,7 @@ START_TEST(vartype)
test_SysReAllocString(); test_SysReAllocString();
test_SysReAllocStringLen(); test_SysReAllocStringLen();
test_BstrCopy(); test_BstrCopy();
test_VarBstrCat();
test_IUnknownClear(); test_IUnknownClear();
test_IUnknownCopy(); test_IUnknownCopy();
......
...@@ -6584,27 +6584,31 @@ HRESULT WINAPI VarBstrFromDisp(IDispatch* pdispIn, LCID lcid, ULONG dwFlags, BST ...@@ -6584,27 +6584,31 @@ HRESULT WINAPI VarBstrFromDisp(IDispatch* pdispIn, LCID lcid, ULONG dwFlags, BST
*/ */
HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut) HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
{ {
unsigned int len; unsigned int lenLeft, lenRight;
TRACE("%s,%s,%p\n",
debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), pbstrOut);
if (!pbstrOut) if (!pbstrOut)
return E_INVALIDARG; return E_INVALIDARG;
len = pbstrLeft ? strlenW(pbstrLeft) : 0; lenLeft = pbstrLeft ? SysStringLen(pbstrLeft) : 0;
if (pbstrRight) lenRight = pbstrRight ? SysStringLen(pbstrRight) : 0;
len += strlenW(pbstrRight);
*pbstrOut = SysAllocStringLen(NULL, len); *pbstrOut = SysAllocStringLen(NULL, lenLeft + lenRight);
if (!*pbstrOut) if (!*pbstrOut)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
(*pbstrOut)[0] = '\0'; (*pbstrOut)[0] = '\0';
if (pbstrLeft) if (pbstrLeft)
strcpyW(*pbstrOut, pbstrLeft); memcpy(*pbstrOut, pbstrLeft, lenLeft * sizeof(WCHAR));
if (pbstrRight) if (pbstrRight)
strcatW(*pbstrOut, pbstrRight); memcpy(*pbstrOut + lenLeft, pbstrRight, lenRight * sizeof(WCHAR));
TRACE("%s\n", debugstr_wn(*pbstrOut, SysStringLen(*pbstrOut)));
return S_OK; return S_OK;
} }
...@@ -6629,6 +6633,12 @@ HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut) ...@@ -6629,6 +6633,12 @@ HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
*/ */
HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags) HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags)
{ {
HRESULT hres;
TRACE("%s,%s,%ld,%08lx\n",
debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), lcid, dwFlags);
if (!pbstrLeft || !*pbstrLeft) if (!pbstrLeft || !*pbstrLeft)
{ {
if (!pbstrRight || !*pbstrRight) if (!pbstrRight || !*pbstrRight)
...@@ -6638,7 +6648,10 @@ HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFl ...@@ -6638,7 +6648,10 @@ HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFl
else if (!pbstrRight || !*pbstrRight) else if (!pbstrRight || !*pbstrRight)
return VARCMP_GT; return VARCMP_GT;
return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1; hres = CompareStringW(lcid, dwFlags, pbstrLeft, SysStringLen(pbstrLeft),
pbstrRight, SysStringLen(pbstrRight)) - 1;
TRACE("%ld\n", hres);
return hres;
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment