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)
41 #define TAG WINPR_TAG("unicode")
156 #if !defined(WITH_WINPR_DEPRECATED)
160 MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte,
161 LPWSTR lpWideCharStr,
int cchWideChar)
163 return int_MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr,
206 #if !defined(WITH_WINPR_DEPRECATED)
210 WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
int cchWideChar,
211 LPSTR lpMultiByteStr,
int cbMultiByte, LPCSTR lpDefaultChar,
212 LPBOOL lpUsedDefaultChar)
214 return int_WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr,
215 cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
232 #if defined(WITH_WINPR_DEPRECATED)
233 int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr,
int cbMultiByte,
234 LPWSTR* lpWideCharStr,
int cchWideChar)
237 BOOL allocate = FALSE;
245 if (cbMultiByte == -1)
247 size_t len = strnlen(lpMultiByteStr, INT_MAX);
250 cbMultiByte = (int)(len + 1);
253 if (cchWideChar == 0)
255 cchWideChar = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, NULL, 0);
258 else if (!(*lpWideCharStr))
266 *lpWideCharStr = (LPWSTR)calloc(cchWideChar + 1,
sizeof(WCHAR));
268 if (!(*lpWideCharStr))
275 status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr,
278 if (status != cchWideChar)
282 free(*lpWideCharStr);
283 *lpWideCharStr = NULL;
304 #if defined(WITH_WINPR_DEPRECATED)
305 int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr,
int cchWideChar,
306 LPSTR* lpMultiByteStr,
int cbMultiByte, LPCSTR lpDefaultChar,
307 LPBOOL lpUsedDefaultChar)
310 BOOL allocate = FALSE;
318 if (cchWideChar == -1)
319 cchWideChar = (int)(_wcslen(lpWideCharStr) + 1);
321 if (cbMultiByte == 0)
324 WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL);
327 else if (!(*lpMultiByteStr))
335 *lpMultiByteStr = (LPSTR)calloc(1, cbMultiByte + 1);
337 if (!(*lpMultiByteStr))
344 status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, *lpMultiByteStr,
345 cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
347 if ((status != cbMultiByte) && allocate)
352 if ((status <= 0) && allocate)
354 free(*lpMultiByteStr);
355 *lpMultiByteStr = NULL;
366 const WCHAR* ByteSwapUnicode(WCHAR* wstr,
size_t length)
368 WINPR_ASSERT(wstr || (length == 0));
370 for (
size_t x = 0; x < length; x++)
371 wstr[x] = _byteswap_ushort(wstr[x]);
375 SSIZE_T ConvertWCharToUtf8(
const WCHAR* wstr,
char* str,
size_t len)
384 const size_t wlen = _wcslen(wstr);
385 return ConvertWCharNToUtf8(wstr, wlen + 1, str, len);
388 SSIZE_T ConvertWCharNToUtf8(
const WCHAR* wstr,
size_t wlen,
char* str,
size_t len)
390 BOOL isNullTerminated = FALSE;
395 size_t iwlen = _wcsnlen(wstr, wlen);
397 if ((len > INT32_MAX) || (wlen > INT32_MAX))
399 SetLastError(ERROR_INVALID_PARAMETER);
405 isNullTerminated = TRUE;
408 const int rc = WideCharToMultiByte(CP_UTF8, 0, wstr, (
int)iwlen, str, (
int)len, NULL, NULL);
409 if ((rc <= 0) || ((len > 0) && ((
size_t)rc > len)))
411 else if (!isNullTerminated)
413 if (str && ((
size_t)rc < len))
417 else if ((
size_t)rc == len)
419 if (str && (str[rc - 1] !=
'\0'))
425 SSIZE_T ConvertMszWCharNToUtf8(
const WCHAR* wstr,
size_t wlen,
char* str,
size_t len)
432 if ((len > INT32_MAX) || (wlen > INT32_MAX))
434 SetLastError(ERROR_INVALID_PARAMETER);
438 const int iwlen = (int)len;
439 const int rc = WideCharToMultiByte(CP_UTF8, 0, wstr, (
int)wlen, str, iwlen, NULL, NULL);
440 if ((rc <= 0) || ((len > 0) && (rc > iwlen)))
446 SSIZE_T ConvertUtf8ToWChar(
const char* str, WCHAR* wstr,
size_t wlen)
455 const size_t len = strlen(str);
456 return ConvertUtf8NToWChar(str, len + 1, wstr, wlen);
459 SSIZE_T ConvertUtf8NToWChar(
const char* str,
size_t len, WCHAR* wstr,
size_t wlen)
461 size_t ilen = strnlen(str, len);
462 BOOL isNullTerminated = FALSE;
468 if ((len > INT32_MAX) || (wlen > INT32_MAX))
470 SetLastError(ERROR_INVALID_PARAMETER);
475 isNullTerminated = TRUE;
479 const int iwlen = (int)wlen;
480 const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (
int)ilen, wstr, iwlen);
481 if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
483 if (!isNullTerminated)
485 if (wstr && (rc < iwlen))
489 else if (rc == iwlen)
491 if (wstr && (wstr[rc - 1] !=
'\0'))
497 SSIZE_T ConvertMszUtf8NToWChar(
const char* str,
size_t len, WCHAR* wstr,
size_t wlen)
504 if ((len > INT32_MAX) || (wlen > INT32_MAX))
506 SetLastError(ERROR_INVALID_PARAMETER);
510 const int iwlen = (int)wlen;
511 const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (
int)len, wstr, iwlen);
512 if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
518 char* ConvertWCharToUtf8Alloc(
const WCHAR* wstr,
size_t* pUtfCharLength)
521 const SSIZE_T rc = ConvertWCharToUtf8(wstr, NULL, 0);
526 tmp = calloc((
size_t)rc + 1ull,
sizeof(
char));
529 const SSIZE_T rc2 = ConvertWCharToUtf8(wstr, tmp, (
size_t)rc + 1ull);
535 WINPR_ASSERT(rc == rc2);
537 *pUtfCharLength = (size_t)rc2;
541 char* ConvertWCharNToUtf8Alloc(
const WCHAR* wstr,
size_t wlen,
size_t* pUtfCharLength)
544 const SSIZE_T rc = ConvertWCharNToUtf8(wstr, wlen, NULL, 0);
550 tmp = calloc((
size_t)rc + 1ull,
sizeof(
char));
553 const SSIZE_T rc2 = ConvertWCharNToUtf8(wstr, wlen, tmp, (
size_t)rc + 1ull);
559 WINPR_ASSERT(rc == rc2);
561 *pUtfCharLength = (size_t)rc2;
565 char* ConvertMszWCharNToUtf8Alloc(
const WCHAR* wstr,
size_t wlen,
size_t* pUtfCharLength)
568 const SSIZE_T rc = ConvertMszWCharNToUtf8(wstr, wlen, NULL, 0);
574 tmp = calloc((
size_t)rc + 1ull,
sizeof(
char));
577 const SSIZE_T rc2 = ConvertMszWCharNToUtf8(wstr, wlen, tmp, (
size_t)rc + 1ull);
583 WINPR_ASSERT(rc == rc2);
585 *pUtfCharLength = (size_t)rc2;
589 WCHAR* ConvertUtf8ToWCharAlloc(
const char* str,
size_t* pSize)
592 const SSIZE_T rc = ConvertUtf8ToWChar(str, NULL, 0);
597 tmp = calloc((
size_t)rc + 1ull,
sizeof(WCHAR));
600 const SSIZE_T rc2 = ConvertUtf8ToWChar(str, tmp, (
size_t)rc + 1ull);
606 WINPR_ASSERT(rc == rc2);
608 *pSize = (size_t)rc2;
612 WCHAR* ConvertUtf8NToWCharAlloc(
const char* str,
size_t len,
size_t* pSize)
615 const SSIZE_T rc = ConvertUtf8NToWChar(str, len, NULL, 0);
620 tmp = calloc((
size_t)rc + 1ull,
sizeof(WCHAR));
623 const SSIZE_T rc2 = ConvertUtf8NToWChar(str, len, tmp, (
size_t)rc + 1ull);
629 WINPR_ASSERT(rc == rc2);
631 *pSize = (size_t)rc2;
635 WCHAR* ConvertMszUtf8NToWCharAlloc(
const char* str,
size_t len,
size_t* pSize)
638 const SSIZE_T rc = ConvertMszUtf8NToWChar(str, len, NULL, 0);
643 tmp = calloc((
size_t)rc + 1ull,
sizeof(WCHAR));
646 const SSIZE_T rc2 = ConvertMszUtf8NToWChar(str, len, tmp, (
size_t)rc + 1ull);
652 WINPR_ASSERT(rc == rc2);
654 *pSize = (size_t)rc2;