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