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 const int rc =
404 WideCharToMultiByte(CP_UTF8, 0, wstr, (int)iwlen, str, (int)len, nullptr, nullptr);
405 if ((rc <= 0) || ((len > 0) && ((size_t)rc > len)))
406 return -1;
407 else if (!isNullTerminated)
408 {
409 if (str && ((size_t)rc < len))
410 str[rc] = '\0';
411 return rc;
412 }
413 else if ((size_t)rc == len)
414 {
415 if (str && (str[rc - 1] != '\0'))
416 return rc;
417 }
418 return rc - 1;
419}
420
421SSIZE_T ConvertMszWCharNToUtf8(const WCHAR* wstr, size_t wlen, char* str, size_t len)
422{
423 if (wlen == 0)
424 return 0;
425
426 WINPR_ASSERT(wstr);
427
428 if ((len > INT32_MAX) || (wlen > INT32_MAX))
429 {
430 SetLastError(ERROR_INVALID_PARAMETER);
431 return -1;
432 }
433
434 const int iwlen = (int)len;
435 const int rc = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)wlen, str, iwlen, nullptr, nullptr);
436 if ((rc <= 0) || ((len > 0) && (rc > iwlen)))
437 return -1;
438
439 return rc;
440}
441
442SSIZE_T ConvertUtf8ToWChar(const char* str, WCHAR* wstr, size_t wlen)
443{
444 if (!str)
445 {
446 if (wstr && wlen)
447 wstr[0] = 0;
448 return 0;
449 }
450
451 const size_t len = strlen(str);
452 return ConvertUtf8NToWChar(str, len + 1, wstr, wlen);
453}
454
455SSIZE_T ConvertUtf8NToWChar(const char* str, size_t len, WCHAR* wstr, size_t wlen)
456{
457 size_t ilen = strnlen(str, len);
458 BOOL isNullTerminated = FALSE;
459 if (len == 0)
460 return 0;
461
462 WINPR_ASSERT(str);
463
464 if ((len > INT32_MAX) || (wlen > INT32_MAX))
465 {
466 SetLastError(ERROR_INVALID_PARAMETER);
467 return -1;
468 }
469 if (ilen < len)
470 {
471 isNullTerminated = TRUE;
472 ilen++;
473 }
474
475 const int iwlen = (int)wlen;
476 const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (int)ilen, wstr, iwlen);
477 if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
478 return -1;
479 if (!isNullTerminated)
480 {
481 if (wstr && (rc < iwlen))
482 wstr[rc] = '\0';
483 return rc;
484 }
485 else if (rc == iwlen)
486 {
487 if (wstr && (wstr[rc - 1] != '\0'))
488 return rc;
489 }
490 return rc - 1;
491}
492
493SSIZE_T ConvertMszUtf8NToWChar(const char* str, size_t len, WCHAR* wstr, size_t wlen)
494{
495 if (len == 0)
496 return 0;
497
498 WINPR_ASSERT(str);
499
500 if ((len > INT32_MAX) || (wlen > INT32_MAX))
501 {
502 SetLastError(ERROR_INVALID_PARAMETER);
503 return -1;
504 }
505
506 const int iwlen = (int)wlen;
507 const int rc = MultiByteToWideChar(CP_UTF8, 0, str, (int)len, wstr, iwlen);
508 if ((rc <= 0) || ((wlen > 0) && (rc > iwlen)))
509 return -1;
510
511 return rc;
512}
513
514char* ConvertWCharToUtf8Alloc(const WCHAR* wstr, size_t* pUtfCharLength)
515{
516 char* tmp = nullptr;
517 const SSIZE_T rc = ConvertWCharToUtf8(wstr, nullptr, 0);
518 if (pUtfCharLength)
519 *pUtfCharLength = 0;
520 if (rc < 0)
521 return nullptr;
522 tmp = calloc((size_t)rc + 1ull, sizeof(char));
523 if (!tmp)
524 return nullptr;
525 const SSIZE_T rc2 = ConvertWCharToUtf8(wstr, tmp, (size_t)rc + 1ull);
526 if (rc2 < 0)
527 {
528 free(tmp);
529 return nullptr;
530 }
531 WINPR_ASSERT(rc == rc2);
532 if (pUtfCharLength)
533 *pUtfCharLength = (size_t)rc2;
534 return tmp;
535}
536
537char* ConvertWCharNToUtf8Alloc(const WCHAR* wstr, size_t wlen, size_t* pUtfCharLength)
538{
539 char* tmp = nullptr;
540 const SSIZE_T rc = ConvertWCharNToUtf8(wstr, wlen, nullptr, 0);
541
542 if (pUtfCharLength)
543 *pUtfCharLength = 0;
544 if (rc < 0)
545 return nullptr;
546 tmp = calloc((size_t)rc + 1ull, sizeof(char));
547 if (!tmp)
548 return nullptr;
549 const SSIZE_T rc2 = ConvertWCharNToUtf8(wstr, wlen, tmp, (size_t)rc + 1ull);
550 if (rc2 < 0)
551 {
552 free(tmp);
553 return nullptr;
554 }
555 WINPR_ASSERT(rc == rc2);
556 if (pUtfCharLength)
557 *pUtfCharLength = (size_t)rc2;
558 return tmp;
559}
560
561char* ConvertMszWCharNToUtf8Alloc(const WCHAR* wstr, size_t wlen, size_t* pUtfCharLength)
562{
563 char* tmp = nullptr;
564 const SSIZE_T rc = ConvertMszWCharNToUtf8(wstr, wlen, nullptr, 0);
565
566 if (pUtfCharLength)
567 *pUtfCharLength = 0;
568 if (rc < 0)
569 return nullptr;
570 tmp = calloc((size_t)rc + 1ull, sizeof(char));
571 if (!tmp)
572 return nullptr;
573 const SSIZE_T rc2 = ConvertMszWCharNToUtf8(wstr, wlen, tmp, (size_t)rc + 1ull);
574 if (rc2 < 0)
575 {
576 free(tmp);
577 return nullptr;
578 }
579 WINPR_ASSERT(rc == rc2);
580 if (pUtfCharLength)
581 *pUtfCharLength = (size_t)rc2;
582 return tmp;
583}
584
585WCHAR* ConvertUtf8ToWCharAlloc(const char* str, size_t* pSize)
586{
587 WCHAR* tmp = nullptr;
588 const SSIZE_T rc = ConvertUtf8ToWChar(str, nullptr, 0);
589 if (pSize)
590 *pSize = 0;
591 if (rc < 0)
592 return nullptr;
593 tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
594 if (!tmp)
595 return nullptr;
596 const SSIZE_T rc2 = ConvertUtf8ToWChar(str, tmp, (size_t)rc + 1ull);
597 if (rc2 < 0)
598 {
599 free(tmp);
600 return nullptr;
601 }
602 WINPR_ASSERT(rc == rc2);
603 if (pSize)
604 *pSize = (size_t)rc2;
605 return tmp;
606}
607
608WCHAR* ConvertUtf8NToWCharAlloc(const char* str, size_t len, size_t* pSize)
609{
610 WCHAR* tmp = nullptr;
611 const SSIZE_T rc = ConvertUtf8NToWChar(str, len, nullptr, 0);
612 if (pSize)
613 *pSize = 0;
614 if (rc < 0)
615 return nullptr;
616 tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
617 if (!tmp)
618 return nullptr;
619 const SSIZE_T rc2 = ConvertUtf8NToWChar(str, len, tmp, (size_t)rc + 1ull);
620 if (rc2 < 0)
621 {
622 free(tmp);
623 return nullptr;
624 }
625 WINPR_ASSERT(rc == rc2);
626 if (pSize)
627 *pSize = (size_t)rc2;
628 return tmp;
629}
630
631WCHAR* ConvertMszUtf8NToWCharAlloc(const char* str, size_t len, size_t* pSize)
632{
633 WCHAR* tmp = nullptr;
634 const SSIZE_T rc = ConvertMszUtf8NToWChar(str, len, nullptr, 0);
635 if (pSize)
636 *pSize = 0;
637 if (rc < 0)
638 return nullptr;
639 tmp = calloc((size_t)rc + 1ull, sizeof(WCHAR));
640 if (!tmp)
641 return nullptr;
642 const SSIZE_T rc2 = ConvertMszUtf8NToWChar(str, len, tmp, (size_t)rc + 1ull);
643 if (rc2 < 0)
644 {
645 free(tmp);
646 return nullptr;
647 }
648 WINPR_ASSERT(rc == rc2);
649 if (pSize)
650 *pSize = (size_t)rc2;
651 return tmp;
652}