FreeRDP
Loading...
Searching...
No Matches
unicode.c
1
22#include <winpr/config.h>
23#include <winpr/assert.h>
24
25#include <errno.h>
26#include <wctype.h>
27
28#include <winpr/crt.h>
29#include <winpr/error.h>
30#include <winpr/print.h>
31
32#ifndef _WIN32
33
34#include "unicode.h"
35
149#if !defined(WITH_WINPR_DEPRECATED)
150static
151#endif
152 int
153 MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
154 LPWSTR lpWideCharStr, int cchWideChar)
155{
156 return int_MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr,
157 cchWideChar);
158}
159
200#if !defined(WITH_WINPR_DEPRECATED)
201static
202#endif
203 int
204 WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
205 LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
206 LPBOOL lpUsedDefaultChar)
207{
208 return int_WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr,
209 cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
210}
211
212#endif
213
226#if defined(WITH_WINPR_DEPRECATED)
227int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte,
228 LPWSTR* lpWideCharStr, int cchWideChar)
229{
230 int status = 0;
231 BOOL allocate = FALSE;
232
233 if (!lpMultiByteStr)
234 return 0;
235
236 if (!lpWideCharStr)
237 return 0;
238
239 if (cbMultiByte == -1)
240 {
241 size_t len = strnlen(lpMultiByteStr, INT_MAX);
242 if (len >= INT_MAX)
243 return 0;
244 cbMultiByte = (int)(len + 1);
245 }
246
247 if (cchWideChar == 0)
248 {
249 cchWideChar =
250 MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, nullptr, 0);
251 allocate = TRUE;
252 }
253 else if (!(*lpWideCharStr))
254 allocate = TRUE;
255
256 if (cchWideChar < 1)
257 return 0;
258
259 if (allocate)
260 {
261 *lpWideCharStr = (LPWSTR)calloc((size_t)cchWideChar + 1ull, sizeof(WCHAR));
262
263 if (!(*lpWideCharStr))
264 {
265 // SetLastError(ERROR_INSUFFICIENT_BUFFER);
266 return 0;
267 }
268 }
269
270 status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr,
271 cchWideChar);
272
273 if (status != cchWideChar)
274 {
275 if (allocate)
276 {
277 free(*lpWideCharStr);
278 *lpWideCharStr = nullptr;
279 status = 0;
280 }
281 }
282
283 return status;
284}
285#endif
286
299#if defined(WITH_WINPR_DEPRECATED)
300int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar,
301 LPSTR* lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar,
302 LPBOOL lpUsedDefaultChar)
303{
304 int status = 0;
305 BOOL allocate = FALSE;
306
307 if (!lpWideCharStr)
308 return 0;
309
310 if (!lpMultiByteStr)
311 return 0;
312
313 if (cchWideChar == -1)
314 cchWideChar = (int)(_wcslen(lpWideCharStr) + 1);
315
316 if (cbMultiByte == 0)
317 {
318 cbMultiByte = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, nullptr, 0,
319 nullptr, nullptr);
320 allocate = TRUE;
321 }
322 else if (!(*lpMultiByteStr))
323 allocate = TRUE;
324
325 if (cbMultiByte < 1)
326 return 0;
327
328 if (allocate)
329 {
330 *lpMultiByteStr = (LPSTR)calloc(1, (size_t)cbMultiByte + 1ull);
331
332 if (!(*lpMultiByteStr))
333 {
334 // SetLastError(ERROR_INSUFFICIENT_BUFFER);
335 return 0;
336 }
337 }
338
339 status = WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, *lpMultiByteStr,
340 cbMultiByte, lpDefaultChar, lpUsedDefaultChar);
341
342 if ((status != cbMultiByte) && allocate)
343 {
344 status = 0;
345 }
346
347 if ((status <= 0) && allocate)
348 {
349 free(*lpMultiByteStr);
350 *lpMultiByteStr = nullptr;
351 }
352
353 return status;
354}
355#endif
356
361const WCHAR* ByteSwapUnicode(WCHAR* wstr, size_t length)
362{
363 WINPR_ASSERT(wstr || (length == 0));
364
365 for (size_t x = 0; x < length; x++)
366 wstr[x] = _byteswap_ushort(wstr[x]);
367 return wstr;
368}
369
370SSIZE_T ConvertWCharToUtf8(const WCHAR* wstr, char* str, size_t len)
371{
372 if (!wstr)
373 {
374 if (str && len)
375 str[0] = 0;
376 return 0;
377 }
378
379 const size_t wlen = _wcslen(wstr);
380 return ConvertWCharNToUtf8(wstr, wlen + 1, str, len);
381}
382
383SSIZE_T ConvertWCharNToUtf8(const WCHAR* wstr, size_t wlen, char* str, size_t len)
384{
385 BOOL isNullTerminated = FALSE;
386 if (wlen == 0)
387 return 0;
388
389 WINPR_ASSERT(wstr);
390 size_t iwlen = _wcsnlen(wstr, wlen);
391
392 if ((len > INT32_MAX) || (wlen > INT32_MAX))
393 {
394 SetLastError(ERROR_INVALID_PARAMETER);
395 return -1;
396 }
397
398 if (iwlen < wlen)
399 {
400 isNullTerminated = TRUE;
401 iwlen++;
402 }
403 WINPR_PRAGMA_DIAG_PUSH
404 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
405 const int rc =
406 WideCharToMultiByte(CP_UTF8, 0, wstr, (int)iwlen, str, (int)len, nullptr, nullptr);
407 WINPR_PRAGMA_DIAG_POP
408 if ((rc <= 0) || ((len > 0) && ((size_t)rc > len)))
409 return -1;
410 else if (!isNullTerminated)
411 {
412 if (str && ((size_t)rc < len))
413 str[rc] = '\0';
414 return rc;
415 }
416 else if ((size_t)rc == len)
417 {
418 if (str && (str[rc - 1] != '\0'))
419 return rc;
420 }
421 return rc - 1;
422}
423
424SSIZE_T ConvertMszWCharNToUtf8(const WCHAR* wstr, size_t wlen, char* str, size_t len)
425{
426 if (wlen == 0)
427 return 0;
428
429 WINPR_ASSERT(wstr);
430
431 if ((len > INT32_MAX) || (wlen > INT32_MAX))
432 {
433 SetLastError(ERROR_INVALID_PARAMETER);
434 return -1;
435 }
436
437 const int iwlen = (int)len;
438 WINPR_PRAGMA_DIAG_PUSH
439 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
440 const int rc = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)wlen, str, iwlen, nullptr, nullptr);
441 WINPR_PRAGMA_DIAG_POP
442 if ((rc <= 0) || ((len > 0) && (rc > iwlen)))
443 return -1;
444
445 return rc;
446}
447
448SSIZE_T ConvertUtf8ToWChar(const char* str, WCHAR* wstr, size_t wlen)
449{
450 if (!str)
451 {
452 if (wstr && wlen)
453 wstr[0] = 0;
454 return 0;
455 }
456
457 const size_t len = strlen(str);
458 return ConvertUtf8NToWChar(str, len + 1, wstr, wlen);
459}
460
461SSIZE_T ConvertUtf8NToWChar(const char* str, size_t len, WCHAR* wstr, size_t wlen)
462{
463 size_t ilen = strnlen(str, len);
464 BOOL isNullTerminated = FALSE;
465 if (len == 0)
466 return 0;
467
468 WINPR_ASSERT(str);
469
470 if ((len > INT32_MAX) || (wlen > INT32_MAX))
471 {
472 SetLastError(ERROR_INVALID_PARAMETER);
473 return -1;
474 }
475 if (ilen < len)
476 {
477 isNullTerminated = TRUE;
478 ilen++;
479 }
480
481 const int iwlen = (int)wlen;
482 WINPR_PRAGMA_DIAG_PUSH
483 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
484 const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (int)ilen, wstr, iwlen);
485 WINPR_PRAGMA_DIAG_POP
486 if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
487 return -1;
488 if (!isNullTerminated)
489 {
490 if (wstr && (rc < iwlen))
491 wstr[rc] = '\0';
492 return rc;
493 }
494 else if (rc == iwlen)
495 {
496 if (wstr && (wstr[rc - 1] != '\0'))
497 return rc;
498 }
499 return rc - 1;
500}
501
502SSIZE_T ConvertMszUtf8NToWChar(const char* str, size_t len, WCHAR* wstr, size_t wlen)
503{
504 if (len == 0)
505 return 0;
506
507 WINPR_ASSERT(str);
508
509 if ((len > INT32_MAX) || (wlen > INT32_MAX))
510 {
511 SetLastError(ERROR_INVALID_PARAMETER);
512 return -1;
513 }
514
515 const int iwlen = (int)wlen;
516 WINPR_PRAGMA_DIAG_PUSH
517 WINPR_PRAGMA_DIAG_IGNORED_DEPRECATED_DECL
518 const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (int)len, wstr, iwlen);
519 WINPR_PRAGMA_DIAG_POP
520 if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
521 return -1;
522
523 return rc;
524}
525
526char* ConvertWCharToUtf8Alloc(const WCHAR* wstr, size_t* pUtfCharLength)
527{
528 char* tmp = nullptr;
529 const SSIZE_T rc = ConvertWCharToUtf8(wstr, nullptr, 0);
530 if (pUtfCharLength)
531 *pUtfCharLength = 0;
532 if (rc < 0)
533 return nullptr;
534 tmp = calloc((size_t)rc + 1ull, sizeof(char));
535 if (!tmp)
536 return nullptr;
537 const SSIZE_T rc2 = ConvertWCharToUtf8(wstr, tmp, (size_t)rc + 1ull);
538 if (rc2 < 0)
539 {
540 free(tmp);
541 return nullptr;
542 }
543 WINPR_ASSERT(rc == rc2);
544 if (pUtfCharLength)
545 *pUtfCharLength = (size_t)rc2;
546 return tmp;
547}
548
549char* ConvertWCharNToUtf8Alloc(const WCHAR* wstr, size_t wlen, size_t* pUtfCharLength)
550{
551 char* tmp = nullptr;
552 const SSIZE_T rc = ConvertWCharNToUtf8(wstr, wlen, nullptr, 0);
553
554 if (pUtfCharLength)
555 *pUtfCharLength = 0;
556 if (rc < 0)
557 return nullptr;
558 tmp = calloc((size_t)rc + 1ull, sizeof(char));
559 if (!tmp)
560 return nullptr;
561 const SSIZE_T rc2 = ConvertWCharNToUtf8(wstr, wlen, tmp, (size_t)rc + 1ull);
562 if (rc2 < 0)
563 {
564 free(tmp);
565 return nullptr;
566 }
567 WINPR_ASSERT(rc == rc2);
568 if (pUtfCharLength)
569 *pUtfCharLength = (size_t)rc2;
570 return tmp;
571}
572
573char* ConvertMszWCharNToUtf8Alloc(const WCHAR* wstr, size_t wlen, size_t* pUtfCharLength)
574{
575 char* tmp = nullptr;
576 const SSIZE_T rc = ConvertMszWCharNToUtf8(wstr, wlen, nullptr, 0);
577
578 if (pUtfCharLength)
579 *pUtfCharLength = 0;
580 if (rc < 0)
581 return nullptr;
582 tmp = calloc((size_t)rc + 1ull, sizeof(char));
583 if (!tmp)
584 return nullptr;
585 const SSIZE_T rc2 = ConvertMszWCharNToUtf8(wstr, wlen, tmp, (size_t)rc + 1ull);
586 if (rc2 < 0)
587 {
588 free(tmp);
589 return nullptr;
590 }
591 WINPR_ASSERT(rc == rc2);
592 if (pUtfCharLength)
593 *pUtfCharLength = (size_t)rc2;
594 return tmp;
595}
596
597WCHAR* ConvertUtf8ToWCharAlloc(const char* str, size_t* pSize)
598{
599 WCHAR* tmp = nullptr;
600 const SSIZE_T rc = ConvertUtf8ToWChar(str, nullptr, 0);
601 if (pSize)
602 *pSize = 0;
603 if (rc < 0)
604 return nullptr;
605 tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
606 if (!tmp)
607 return nullptr;
608 const SSIZE_T rc2 = ConvertUtf8ToWChar(str, tmp, (size_t)rc + 1ull);
609 if (rc2 < 0)
610 {
611 free(tmp);
612 return nullptr;
613 }
614 WINPR_ASSERT(rc == rc2);
615 if (pSize)
616 *pSize = (size_t)rc2;
617 return tmp;
618}
619
620WCHAR* ConvertUtf8NToWCharAlloc(const char* str, size_t len, size_t* pSize)
621{
622 WCHAR* tmp = nullptr;
623 const SSIZE_T rc = ConvertUtf8NToWChar(str, len, nullptr, 0);
624 if (pSize)
625 *pSize = 0;
626 if (rc < 0)
627 return nullptr;
628 tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
629 if (!tmp)
630 return nullptr;
631 const SSIZE_T rc2 = ConvertUtf8NToWChar(str, len, tmp, (size_t)rc + 1ull);
632 if (rc2 < 0)
633 {
634 free(tmp);
635 return nullptr;
636 }
637 WINPR_ASSERT(rc == rc2);
638 if (pSize)
639 *pSize = (size_t)rc2;
640 return tmp;
641}
642
643WCHAR* ConvertMszUtf8NToWCharAlloc(const char* str, size_t len, size_t* pSize)
644{
645 WCHAR* tmp = nullptr;
646 const SSIZE_T rc = ConvertMszUtf8NToWChar(str, len, nullptr, 0);
647 if (pSize)
648 *pSize = 0;
649 if (rc < 0)
650 return nullptr;
651 tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
652 if (!tmp)
653 return nullptr;
654 const SSIZE_T rc2 = ConvertMszUtf8NToWChar(str, len, tmp, (size_t)rc + 1ull);
655 if (rc2 < 0)
656 {
657 free(tmp);
658 return nullptr;
659 }
660 WINPR_ASSERT(rc == rc2);
661 if (pSize)
662 *pSize = (size_t)rc2;
663 return tmp;
664}