1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS CRT 4 * PURPOSE: Implementation of mbstowcs_s 5 * FILE: lib/sdk/crt/string/wcstombs_s.c 6 * PROGRAMMER: Timo Kreuzer 7 */ 8 9 #include <precomp.h> 10 11 _Success_(return!=EINVAL) 12 _Check_return_wat_ 13 _CRTIMP 14 errno_t 15 __cdecl 16 wcstombs_s( 17 _Out_opt_ size_t * pcchConverted, 18 _Out_writes_bytes_to_opt_(cjDstSize, *pcchConverted) 19 char * pmbstrDst, 20 _In_ size_t cjDstSize, 21 _In_z_ const wchar_t * pwszSrc, 22 _In_ size_t cjMaxCount) 23 { 24 size_t cchMax, cchConverted; 25 errno_t retval = 0; 26 27 /* Make sure, either we have a target buffer > 0 bytes, or no buffer */ 28 if (!MSVCRT_CHECK_PMT( ((cjDstSize != 0) && (pmbstrDst != 0)) || 29 ((cjDstSize == 0) && (pmbstrDst == 0)) )) 30 { 31 _set_errno(EINVAL); 32 return EINVAL; 33 } 34 35 /* Check if we have a return value pointer */ 36 if (pcchConverted) 37 { 38 /* Default to 0 bytes written */ 39 *pcchConverted = 0; 40 } 41 42 if (!MSVCRT_CHECK_PMT((cjMaxCount == 0) || (pwszSrc != 0))) 43 { 44 _set_errno(EINVAL); 45 return EINVAL; 46 } 47 48 /* Check if there is anything to do */ 49 if ((pmbstrDst == 0) && (pwszSrc == 0)) 50 { 51 _set_errno(EINVAL); 52 return EINVAL; 53 } 54 55 /* Check if we have a wchar string */ 56 if (pwszSrc) 57 { 58 /* Check if we also have a multibyte buffer */ 59 if (pmbstrDst) 60 { 61 /* Calculate the maximum that we can write */ 62 cchMax = (cjMaxCount < cjDstSize) ? cjMaxCount + 1 : cjDstSize; 63 64 /* Now do the conversion */ 65 cchConverted = wcstombs(pmbstrDst, pwszSrc, cchMax); 66 67 /* Check if the buffer was not zero terminated */ 68 if (cchConverted == cchMax) 69 { 70 /* Check if we reached the max size of the dest buffer */ 71 if (cchConverted == cjDstSize) 72 { 73 /* Does the caller allow this? */ 74 if (cjMaxCount != _TRUNCATE) 75 { 76 /* Not allowed, truncate to 0 length */ 77 pmbstrDst[0] = L'\0'; 78 79 /* Return error */ 80 _set_errno(ERANGE); 81 return ERANGE; 82 } 83 84 /* Inform the caller about truncation */ 85 retval = STRUNCATE; 86 } 87 88 /* zero teminate the buffer */ 89 pmbstrDst[cchConverted - 1] = L'\0'; 90 } 91 else 92 { 93 /* The buffer is zero terminated, count the terminating char */ 94 cchConverted++; 95 } 96 } 97 else 98 { 99 /* Get the length of the string, plus 0 terminator */ 100 cchConverted = wcsnlen(pwszSrc, cjMaxCount) + 1; 101 } 102 } 103 else 104 { 105 cchConverted = cjMaxCount + 1; 106 } 107 108 /* Check if we have a return value pointer */ 109 if (pcchConverted) 110 { 111 /* Default to 0 bytes written */ 112 *pcchConverted = cchConverted; 113 } 114 115 return retval; 116 } 117