22 #include <winpr/config.h>
23 #include <winpr/assert.h>
28 #include <winpr/crt.h>
29 #include <winpr/error.h>
30 #include <winpr/print.h>
33 #define MIN(a, b) (a) < (b) ? (a) : (b)
36 #include <unicode/ucnv.h>
37 #include <unicode/ustring.h>
42 #define TAG WINPR_TAG("unicode")
44 #define UCNV_CONVERT 1
46 int int_MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte,
47 LPWSTR lpWideCharStr,
int cchWideChar)
49 const BOOL isNullTerminated = cbMultiByte < 0;
51 WINPR_UNUSED(dwFlags);
55 if ((cbMultiByte == 0) || (cbMultiByte < -1))
57 SetLastError(ERROR_INVALID_PARAMETER);
63 len = strlen(lpMultiByteStr) + 1;
69 SetLastError(ERROR_INVALID_PARAMETER);
72 cbMultiByte = (int)len;
79 UErrorCode error = U_ZERO_ERROR;
80 int32_t targetLength = -1;
89 WLog_ERR(TAG,
"Unsupported encoding %u", CodePage);
90 SetLastError(ERROR_INVALID_PARAMETER);
94 const int32_t targetCapacity = cchWideChar;
95 #if defined(UCNV_CONVERT)
96 char* targetStart = (
char*)lpWideCharStr;
98 ucnv_convert(
"UTF-16LE",
"UTF-8", targetStart, targetCapacity * (int32_t)
sizeof(WCHAR),
99 lpMultiByteStr, cbMultiByte, &error);
100 if (targetLength > 0)
101 targetLength /=
sizeof(WCHAR);
103 WCHAR* targetStart = lpWideCharStr;
104 u_strFromUTF8(targetStart, targetCapacity, &targetLength, lpMultiByteStr, cbMultiByte,
110 case U_BUFFER_OVERFLOW_ERROR:
111 if (targetCapacity > 0)
114 WLog_ERR(TAG,
"insufficient buffer supplied, got %d, required %d",
115 targetCapacity, targetLength);
116 SetLastError(ERROR_INSUFFICIENT_BUFFER);
119 cchWideChar = targetLength;
121 case U_STRING_NOT_TERMINATED_WARNING:
122 cchWideChar = targetLength;
125 cchWideChar = targetLength;
128 WLog_WARN(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"]", u_errorName(error),
130 if (U_FAILURE(error))
132 WLog_ERR(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"] is fatal",
133 u_errorName(error), error);
135 SetLastError(ERROR_NO_UNICODE_TRANSLATION);
138 cchWideChar = targetLength;
146 int int_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
int cchWideChar,
147 LPSTR lpMultiByteStr,
int cbMultiByte, LPCSTR lpDefaultChar,
148 LPBOOL lpUsedDefaultChar)
152 if ((cchWideChar == 0) || (cchWideChar < -1))
154 SetLastError(ERROR_INVALID_PARAMETER);
161 if (cchWideChar == -1)
162 len = _wcslen(lpWideCharStr) + 1;
166 if (len >= INT32_MAX)
168 SetLastError(ERROR_INVALID_PARAMETER);
171 cchWideChar = (int)len;
178 UErrorCode error = U_ZERO_ERROR;
179 int32_t targetLength = -1;
188 WLog_ERR(TAG,
"Unsupported encoding %u", CodePage);
189 SetLastError(ERROR_INVALID_PARAMETER);
193 char* targetStart = lpMultiByteStr;
194 const int32_t targetCapacity = cbMultiByte;
195 #if defined(UCNV_CONVERT)
196 const char* str = (
const char*)lpWideCharStr;
197 targetLength = ucnv_convert(
"UTF-8",
"UTF-16LE", targetStart, targetCapacity, str,
198 cchWideChar * (int32_t)
sizeof(WCHAR), &error);
200 u_strToUTF8(targetStart, targetCapacity, &targetLength, lpWideCharStr, cchWideChar, &error);
204 case U_BUFFER_OVERFLOW_ERROR:
205 if (targetCapacity > 0)
207 WLog_ERR(TAG,
"insufficient buffer supplied, got %d, required %d",
208 targetCapacity, targetLength);
210 SetLastError(ERROR_INSUFFICIENT_BUFFER);
213 cbMultiByte = targetLength;
215 case U_STRING_NOT_TERMINATED_WARNING:
216 cbMultiByte = targetLength;
219 cbMultiByte = targetLength;
222 WLog_WARN(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"]", u_errorName(error),
224 if (U_FAILURE(error))
226 WLog_ERR(TAG,
"unexpected ICU error code %s [0x%08" PRIx32
"] is fatal",
227 u_errorName(error), error);
229 SetLastError(ERROR_NO_UNICODE_TRANSLATION);
232 cbMultiByte = targetLength;