1 /*** 2 *wcslwr.c - routine to map upper-case characters in a wchar_t string 3 * to lower-case 4 * 5 * Copyright (c) Microsoft Corporation. All rights reserved. 6 * 7 *Purpose: 8 * Converts all the upper case characters in a wchar_t string 9 * to lower case, in place. 10 * 11 *******************************************************************************/ 12 #include <corecrt_internal.h> 13 #include <ctype.h> 14 #include <corecrt_internal_securecrt.h> 15 #include <locale.h> 16 #include <string.h> 17 18 #pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED) // 26018 19 20 /*** 21 *wchar_t *_wcslwr(string) - map upper-case characters in a string to lower-case 22 * 23 *Purpose: 24 * wcslwr converts upper-case characters in a null-terminated wchar_t 25 * string to their lower-case equivalents. The result may be longer or 26 * shorter than the original string. Assumes enough space in string 27 * to hold the result. 28 * 29 *Entry: 30 * wchar_t *wsrc - wchar_t string to change to lower case 31 * 32 *Exit: 33 * input string address 34 * 35 *Exceptions: 36 * on an error, the original string is unaltered, and errno is set 37 * 38 *******************************************************************************/ 39 40 extern "C" wchar_t * __cdecl _wcslwr_l ( 41 wchar_t * wsrc, 42 _locale_t plocinfo 43 ) 44 { 45 _wcslwr_s_l(wsrc, (size_t)(-1), plocinfo); 46 return wsrc; 47 } 48 49 extern "C" wchar_t * __cdecl _wcslwr ( 50 wchar_t * wsrc 51 ) 52 { 53 if (!__acrt_locale_changed()) 54 { 55 wchar_t * p; 56 57 /* validation section */ 58 _VALIDATE_RETURN(wsrc != nullptr, EINVAL, nullptr); 59 60 for (p=wsrc; *p; ++p) 61 { 62 if (L'A' <= *p && *p <= L'Z') 63 *p += (wchar_t)L'a' - (wchar_t)L'A'; 64 } 65 } else { 66 _wcslwr_s_l(wsrc, (size_t)(-1), nullptr); 67 return wsrc; 68 } 69 70 return(wsrc); 71 } 72 73 /*** 74 *errno_t _wcslwr_s(string, size_t) - map upper-case characters in a string to lower-case 75 * 76 *Purpose: 77 * wcslwr_s converts upper-case characters in a null-terminated wchar_t 78 * string to their lower-case equivalents. The result may be longer or 79 * shorter than the original string. 80 * 81 *Entry: 82 * wchar_t *wsrc - wchar_t string to change to lower case 83 * size_t sizeInWords - size of the destination buffer 84 * 85 *Exit: 86 * the error code 87 * 88 *Exceptions: 89 * on an error, the original string is unaltered, and errno is set 90 * 91 *******************************************************************************/ 92 93 static errno_t __cdecl _wcslwr_s_l_stat ( 94 _Inout_updates_z_(sizeInWords) wchar_t * wsrc, 95 size_t sizeInWords, 96 _locale_t plocinfo 97 ) 98 { 99 100 wchar_t *p; /* traverses string for C locale conversion */ 101 int dstsize; /* size in wide chars of wdst string buffer (include null) */ 102 size_t stringlen; 103 104 /* validation section */ 105 _VALIDATE_RETURN_ERRCODE(wsrc != nullptr, EINVAL); 106 stringlen = wcsnlen(wsrc, sizeInWords); 107 if (stringlen >= sizeInWords) 108 { 109 _RESET_STRING(wsrc, sizeInWords); 110 _RETURN_DEST_NOT_NULL_TERMINATED(wsrc, sizeInWords); 111 } 112 _FILL_STRING(wsrc, sizeInWords, stringlen + 1); 113 114 if ( plocinfo->locinfo->locale_name[LC_CTYPE] == nullptr) 115 { 116 for ( p = wsrc ; *p ; p++ ) 117 { 118 if ( (*p >= (wchar_t)L'A') && (*p <= (wchar_t)L'Z') ) 119 { 120 *p -= static_cast<wchar_t>(L'A' - L'a'); 121 } 122 } 123 124 return 0; 125 } /* C locale */ 126 127 /* Inquire size of wdst string */ 128 if ( (dstsize = __acrt_LCMapStringW( 129 plocinfo->locinfo->locale_name[LC_CTYPE], 130 LCMAP_LOWERCASE, 131 wsrc, 132 -1, 133 nullptr, 134 0 135 )) == 0 ) 136 { 137 errno = EILSEQ; 138 return errno; 139 } 140 141 if (sizeInWords < (size_t)dstsize) 142 { 143 _RESET_STRING(wsrc, sizeInWords); 144 _RETURN_BUFFER_TOO_SMALL(wsrc, sizeInWords); 145 } 146 147 /* Allocate space for wdst */ 148 __crt_scoped_stack_ptr<wchar_t> const wdst(_malloca_crt_t(wchar_t, dstsize)); 149 if (!wdst) 150 { 151 errno = ENOMEM; 152 return errno; 153 } 154 155 /* Map wrc string to wide-character wdst string in alternate case */ 156 if (__acrt_LCMapStringW( 157 plocinfo->locinfo->locale_name[LC_CTYPE], 158 LCMAP_LOWERCASE, 159 wsrc, 160 -1, 161 wdst.get(), 162 dstsize 163 ) != 0) 164 { 165 /* Copy wdst string to user string */ 166 return wcscpy_s(wsrc, sizeInWords, wdst.get()); 167 } 168 else 169 { 170 return errno = EILSEQ; 171 } 172 } 173 174 extern "C" errno_t __cdecl _wcslwr_s_l ( 175 wchar_t * wsrc, 176 size_t sizeInWords, 177 _locale_t plocinfo 178 ) 179 { 180 _LocaleUpdate _loc_update(plocinfo); 181 182 return _wcslwr_s_l_stat(wsrc, sizeInWords, _loc_update.GetLocaleT()); 183 } 184 185 186 extern "C" errno_t __cdecl _wcslwr_s ( 187 wchar_t * wsrc, 188 size_t sizeInWords 189 ) 190 { 191 return _wcslwr_s_l(wsrc, sizeInWords, nullptr); 192 } 193