diff --git a/reactos/dll/win32/shlwapi/shlwapi.spec b/reactos/dll/win32/shlwapi/shlwapi.spec index b7ea3aa6fff..b6426e784db 100644 --- a/reactos/dll/win32/shlwapi/shlwapi.spec +++ b/reactos/dll/win32/shlwapi/shlwapi.spec @@ -215,7 +215,7 @@ 215 stdcall -noname SHAnsiToUnicode(str ptr long) 216 stdcall -noname SHAnsiToUnicodeCP(long str ptr long) 217 stdcall -noname SHUnicodeToAnsi(wstr ptr ptr) -218 stdcall -noname SHUnicodeToAnsiCP(long wstr ptr ptr) +218 stdcall -noname SHUnicodeToAnsiCP(long wstr ptr long) 219 stdcall -noname QISearch(long long long long) 220 stdcall -noname SHSetDefaultDialogFont(ptr long) 221 stdcall -noname SHRemoveDefaultDialogFont(ptr) @@ -477,7 +477,7 @@ 477 stub -noname SHCreatePropertyBagOnMemory 478 stdcall -noname IUnknown_TranslateAcceleratorIO(ptr ptr) 479 stub -noname IUnknown_UIActivateIO -480 stub -noname UrlCrackW +480 stdcall -noname UrlCrackW(wstr long long ptr) wininet.InternetCrackUrlW 481 stdcall -noname IUnknown_HasFocusIO(ptr) 482 stub -noname SHMessageBoxHelpA 483 stub -noname SHMessageBoxHelpW diff --git a/reactos/dll/win32/shlwapi/string.c b/reactos/dll/win32/shlwapi/string.c index da0dee3cfd2..755360d790a 100644 --- a/reactos/dll/win32/shlwapi/string.c +++ b/reactos/dll/win32/shlwapi/string.c @@ -2477,20 +2477,24 @@ DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen) * CodePage [I] Code page to use for the conversion * lpSrcStr [I] Source Unicode string to convert * lpDstStr [O] Destination for converted Ascii string - * lpiLen [I/O] Input length of lpDstStr/destination for length of lpDstStr + * dstlen [I] Length of buffer at lpDstStr * * RETURNS - * Success: The number of characters that result from the conversion. - * Failure: 0. + * Success: The length in bytes of the result at lpDstStr (including the terminator) + * Failure: When using CP_UTF8, CP_UTF7 or 0xc350 as codePage, 0 is returned and + * the result is not nul-terminated. + * When using a different codepage, the length in bytes of the truncated + * result at lpDstStr (including the terminator) is returned and + * lpDstStr is always nul-terminated. + * */ -INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, - LPINT lpiLen) +DWORD WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, int dstlen) { static const WCHAR emptyW[] = { '\0' }; int len , reqLen; LPSTR mem; - if (!lpDstStr || !lpiLen) + if (!lpDstStr || !dstlen) return 0; if (!lpSrcStr) @@ -2509,41 +2513,41 @@ INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, case CP_UTF8: { DWORD dwMode = 0; - INT nWideCharCount = len - 1; + INT lenW = len - 1; + INT needed = dstlen - 1; + HRESULT hr; - if (ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, - &nWideCharCount, lpDstStr, - lpiLen) == S_OK) + /* try the user supplied buffer first */ + hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, lpDstStr, &needed); + if (hr == S_OK) + { + lpDstStr[needed] = '\0'; + return needed + 1; + } + + /* user buffer too small. exclude termination and copy as much as possible */ + lenW = len; + hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &lenW, NULL, &needed); + needed++; + mem = HeapAlloc(GetProcessHeap(), 0, needed); + if (!mem) return 0; - if (nWideCharCount < len - 1) + hr = ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, &needed); + if (hr == S_OK) { - mem = HeapAlloc(GetProcessHeap(), 0, *lpiLen); - if (!mem) - return 0; - - *lpiLen = 0; - - if (ConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, - mem, lpiLen) != S_OK) - { - SHTruncateString(mem, *lpiLen); - lstrcpynA(lpDstStr, mem, *lpiLen + 1); - HeapFree(GetProcessHeap(), 0, mem); - return *lpiLen + 1; - } - HeapFree(GetProcessHeap(), 0, mem); - return *lpiLen; + reqLen = SHTruncateString(mem, dstlen); + if (reqLen > 0) memcpy(lpDstStr, mem, reqLen-1); } - lpDstStr[*lpiLen] = '\0'; - return *lpiLen; + HeapFree(GetProcessHeap(), 0, mem); + return 0; } default: break; } - reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr, - *lpiLen, NULL, NULL); + /* try the user supplied buffer first */ + reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr, dstlen, NULL, NULL); if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { @@ -2556,12 +2560,12 @@ INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem, reqLen, NULL, NULL); - reqLen = SHTruncateString(mem, *lpiLen); + reqLen = SHTruncateString(mem, dstlen -1); reqLen++; - lstrcpynA(lpDstStr, mem, *lpiLen); - + lstrcpynA(lpDstStr, mem, reqLen); HeapFree(GetProcessHeap(), 0, mem); + lpDstStr[reqLen-1] = '\0'; } } } @@ -2586,9 +2590,7 @@ INT WINAPI SHUnicodeToAnsiCP(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr, */ INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen) { - INT myint = iLen; - - return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, &myint); + return SHUnicodeToAnsiCP(CP_ACP, lpSrcStr, lpDstStr, iLen); } /*************************************************************************