22#include <winpr/config.h>
23#include <winpr/assert.h>
29#include <winpr/error.h>
30#include <winpr/print.h>
32#include <unicode/ucnv.h>
33#include <unicode/ustring.h>
38#define TAG WINPR_TAG("unicode")
42int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte,
43 LPWSTR lpWideCharStr,
int cchWideChar)
45 const BOOL isNullTerminated = cbMultiByte < 0;
47 WINPR_UNUSED(dwFlags);
51 if ((cbMultiByte == 0) || (cbMultiByte < -1))
53 SetLastError(ERROR_INVALID_PARAMETER);
59 len = strlen(lpMultiByteStr) + 1;
61 len = WINPR_ASSERTING_INT_CAST(
size_t, cbMultiByte);
65 SetLastError(ERROR_INVALID_PARAMETER);
68 cbMultiByte = WINPR_ASSERTING_INT_CAST(
int, len);
75 UErrorCode error = U_ZERO_ERROR;
76 int32_t targetLength = -1;
85 WLog_ERR(TAG,
"Unsupported encoding %u", CodePage);
86 SetLastError(ERROR_INVALID_PARAMETER);
90 const int32_t targetCapacity = cchWideChar;
91#if defined(UCNV_CONVERT)
92 char* targetStart = (
char*)lpWideCharStr;
94 ucnv_convert(
"UTF-16LE",
"UTF-8", targetStart, targetCapacity * (int32_t)
sizeof(WCHAR),
95 lpMultiByteStr, cbMultiByte, &error);
97 targetLength /=
sizeof(WCHAR);
99 WCHAR* targetStart = lpWideCharStr;
100 u_strFromUTF8(targetStart, targetCapacity, &targetLength, lpMultiByteStr, cbMultiByte,
106 case U_BUFFER_OVERFLOW_ERROR:
107 if (targetCapacity > 0)
110 WLog_ERR(TAG,
"insufficient buffer supplied, got %d, required %d",
111 targetCapacity, targetLength);
112 SetLastError(ERROR_INSUFFICIENT_BUFFER);
115 cchWideChar = targetLength;
117 case U_STRING_NOT_TERMINATED_WARNING:
118 cchWideChar = targetLength;
121 cchWideChar = targetLength;
124 WLog_WARN(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"]", u_errorName(error),
126 if (U_FAILURE(error))
128 WLog_ERR(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"] is fatal",
129 u_errorName(error), error);
131 SetLastError(ERROR_NO_UNICODE_TRANSLATION);
134 cchWideChar = targetLength;
142int int_WideCharToMultiByte(UINT CodePage, WINPR_ATTR_UNUSED DWORD dwFlags, LPCWSTR lpWideCharStr,
143 int cchWideChar, LPSTR lpMultiByteStr,
int cbMultiByte,
144 WINPR_ATTR_UNUSED LPCSTR lpDefaultChar,
145 WINPR_ATTR_UNUSED LPBOOL lpUsedDefaultChar)
149 if ((cchWideChar == 0) || (cchWideChar < -1))
151 SetLastError(ERROR_INVALID_PARAMETER);
158 if (cchWideChar == -1)
159 len = _wcslen(lpWideCharStr) + 1;
161 len = WINPR_ASSERTING_INT_CAST(
size_t, cchWideChar);
163 if (len >= INT32_MAX)
165 SetLastError(ERROR_INVALID_PARAMETER);
168 cchWideChar = WINPR_ASSERTING_INT_CAST(
int, len);
175 UErrorCode error = U_ZERO_ERROR;
176 int32_t targetLength = -1;
185 WLog_ERR(TAG,
"Unsupported encoding %u", CodePage);
186 SetLastError(ERROR_INVALID_PARAMETER);
190 char* targetStart = lpMultiByteStr;
191 const int32_t targetCapacity = cbMultiByte;
192#if defined(UCNV_CONVERT)
193 const char* str = (
const char*)lpWideCharStr;
194 targetLength = ucnv_convert(
"UTF-8",
"UTF-16LE", targetStart, targetCapacity, str,
195 cchWideChar * (int32_t)
sizeof(WCHAR), &error);
197 u_strToUTF8(targetStart, targetCapacity, &targetLength, lpWideCharStr, cchWideChar, &error);
201 case U_BUFFER_OVERFLOW_ERROR:
202 if (targetCapacity > 0)
204 WLog_ERR(TAG,
"insufficient buffer supplied, got %d, required %d",
205 targetCapacity, targetLength);
207 SetLastError(ERROR_INSUFFICIENT_BUFFER);
210 cbMultiByte = targetLength;
212 case U_STRING_NOT_TERMINATED_WARNING:
213 cbMultiByte = targetLength;
216 cbMultiByte = targetLength;
219 WLog_WARN(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"]", u_errorName(error),
221 if (U_FAILURE(error))
223 WLog_ERR(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"] is fatal",
224 u_errorName(error), error);
226 SetLastError(ERROR_NO_UNICODE_TRANSLATION);
229 cbMultiByte = targetLength;