shlwapi: Fixed error handling in StrRetToBufW.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-02-23 15:42:41 +01:00 committed by Alexandre Julliard
parent dd99871cec
commit dfb846c214
2 changed files with 68 additions and 38 deletions

View File

@ -1521,47 +1521,58 @@ HRESULT WINAPI StrRetToBufA (LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, U
*/ */
HRESULT WINAPI StrRetToBufW (LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len) HRESULT WINAPI StrRetToBufW (LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len)
{ {
TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl); TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
if (!src) if (!dest || !len)
return E_FAIL;
if (!src)
{
WARN("Invalid lpStrRet would crash under Win32!\n");
if (dest)
*dest = '\0';
return E_FAIL;
}
*dest = '\0';
switch (src->uType) {
case STRRET_WSTR: {
size_t dst_len;
if (!src->u.pOleStr)
return E_FAIL;
dst_len = strlenW(src->u.pOleStr);
memcpy(dest, src->u.pOleStr, min(dst_len, len-1) * sizeof(WCHAR));
dest[min(dst_len, len-1)] = 0;
CoTaskMemFree(src->u.pOleStr);
if (len <= dst_len)
{
dest[0] = 0;
return E_NOT_SUFFICIENT_BUFFER;
}
break;
}
case STRRET_CSTR:
if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
dest[len-1] = 0;
break;
case STRRET_OFFSET:
if (pidl)
{ {
WARN("Invalid lpStrRet would crash under Win32!\n"); if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
if (dest) dest, len ))
*dest = '\0'; dest[len-1] = 0;
return E_FAIL; }
} break;
if (!dest || !len) default:
return E_FAIL; FIXME("unknown type!\n");
return E_NOTIMPL;
}
*dest = '\0'; return S_OK;
switch (src->uType)
{
case STRRET_WSTR:
lstrcpynW(dest, src->u.pOleStr, len);
CoTaskMemFree(src->u.pOleStr);
break;
case STRRET_CSTR:
if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
dest[len-1] = 0;
break;
case STRRET_OFFSET:
if (pidl)
{
if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
dest, len ))
dest[len-1] = 0;
}
break;
default:
FIXME("unknown type!\n");
return E_NOTIMPL;
}
return S_OK;
} }
/************************************************************************* /*************************************************************************

View File

@ -988,6 +988,7 @@ static void test_StrXXX_overflows(void)
WCHAR wstr1[2*MAX_PATH+1], wbuf[2*MAX_PATH]; WCHAR wstr1[2*MAX_PATH+1], wbuf[2*MAX_PATH];
const WCHAR fmt[] = {'%','s',0}; const WCHAR fmt[] = {'%','s',0};
STRRET strret; STRRET strret;
HRESULT hres;
int ret; int ret;
int i; int i;
@ -1059,9 +1060,27 @@ if (0)
memset(wbuf, 0xbf, sizeof(wbuf)); memset(wbuf, 0xbf, sizeof(wbuf));
strret.uType = STRRET_WSTR; strret.uType = STRRET_WSTR;
U(strret).pOleStr = StrDupW(wstr1); U(strret).pOleStr = StrDupW(wstr1);
expect_eq2(pStrRetToBufW(&strret, NULL, wbuf, 10), S_OK, E_NOT_SUFFICIENT_BUFFER /* Vista */, HRESULT, "%x"); hres = pStrRetToBufW(&strret, NULL, wbuf, 10);
ok(hres == E_NOT_SUFFICIENT_BUFFER || broken(hres == S_OK) /* winxp */,
"StrRetToBufW returned %08x\n", hres);
if (hres == E_NOT_SUFFICIENT_BUFFER)
expect_eq(wbuf[0], 0, WCHAR, "%x");
expect_eq(wbuf[9], 0, WCHAR, "%x"); expect_eq(wbuf[9], 0, WCHAR, "%x");
expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x"); expect_eq(wbuf[10], (WCHAR)0xbfbf, WCHAR, "%x");
memset(wbuf, 0xbf, sizeof(wbuf));
strret.uType = STRRET_CSTR;
StrCpyNA(U(strret).cStr, str1, MAX_PATH);
hres = pStrRetToBufW(&strret, NULL, wbuf, 10);
ok(hres == S_OK, "StrRetToBufW returned %08x\n", hres);
ok(!memcmp(wbuf, wstr1, 9*sizeof(WCHAR)) && !wbuf[9], "StrRetToBuf returned %s\n", wine_dbgstr_w(wbuf));
memset(wbuf, 0xbf, sizeof(wbuf));
strret.uType = STRRET_WSTR;
U(strret).pOleStr = NULL;
hres = pStrRetToBufW(&strret, NULL, wbuf, 10);
ok(hres == E_FAIL, "StrRetToBufW returned %08x\n", hres);
ok(!wbuf[0], "StrRetToBuf returned %s\n", wine_dbgstr_w(wbuf));
} }
else else
win_skip("StrRetToBufW() is not available\n"); win_skip("StrRetToBufW() is not available\n");