errno_t __cdecl _mbscpy_s_l(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, _LOCALE_ARG_DECL) { unsigned char *p; size_t available; BOOL fIsLeadPrefix; /* validation section */ _VALIDATE_STRING(_Dst, _SizeInBytes); _VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); _LOCALE_UPDATE; if (_LOCALE_SHORTCUT_TEST) { return strcpy_s((char *)_Dst, _SizeInBytes, (const char *)_Src); } p = _Dst; available = _SizeInBytes; while ((*p++ = *_Src++) != 0 && --available > 0) { } /* * If we ran out of destination bytes then we did so before copying null. * Only exception to that is if last mbc was invalid (leadbyte+null), which * is treated as null. In that case clear the copied lead byte and return ok. */ if (available == 0) { if (*_Src == 0) { _ISMBBLEADPREFIX(fIsLeadPrefix,_Dst,p-1); if (fIsLeadPrefix) { p[-1] = 0; _RETURN_MBCS_ERROR; } } _RESET_STRING(_Dst, _SizeInBytes); _RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); } /* * Otherwise we have space left in the dst buffer and stopped copying because * we saw a null in the src. If null is part of invalid MBC (lead byte + null) * then clear the lead byte also. */ _ISMBBLEADPREFIX(fIsLeadPrefix, _Dst, p-2); if (fIsLeadPrefix && (p - 2) >= _Dst) { p[-2] = 0; available++; _FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); _RETURN_MBCS_ERROR; } _FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); _RETURN_NO_ERROR; }
_TCHAR* __cdecl _getts_helper( _TCHAR* string, size_t bufferSize, int earlyOutIfEOFIsFirstChar ) { int ch = 0; _TCHAR* pointer = string; _TCHAR* retval = string; _VALIDATE_RETURN((string != NULL), EINVAL, NULL); _VALIDATE_RETURN((bufferSize > 0), EINVAL, NULL); /* The C Standard states the input buffer should remain unchanged if EOF is encountered immediately. Hence we do not blank out the input buffer here */ _lock_str2(0, stdin); __try { #ifndef _UNICODE _VALIDATE_STREAM_ANSI_SETRET(stdin, EINVAL, retval, NULL); if (retval == NULL) { goto done; } #endif /* _UNICODE */ /* special case: check if the first char is EOF and treat it differently if the user requested so */ ch = _getchar_helper(); if (ch == _TEOF) { retval = NULL; if (earlyOutIfEOFIsFirstChar) { goto done; } } if (bufferSize == (size_t) - 1) { /* insecure case: no buffer size check, no debug filling */ while (ch != _T('\n') && ch != _TEOF) { *pointer++ = (_TCHAR)ch; ch = _getchar_helper(); } *pointer = 0; } else { /* secure case, check buffer size; if buffer overflow, keep on reading until /n or EOF */ size_t available = bufferSize; while (ch != _T('\n') && ch != _TEOF) { if (available > 0) { --available; *pointer++ = (_TCHAR)ch; } ch = _getchar_helper(); } if (available == 0) { _RESET_STRING(string, bufferSize); _RETURN_BUFFER_TOO_SMALL_ERROR(string, bufferSize, NULL); } *pointer = 0; _FILL_STRING(string, bufferSize, bufferSize - available + 1); } /* Common return */ done: ; } __finally { _unlock_str2(0, stdin); } return retval; }
extern "C" errno_t __cdecl _mbsupr_s_l( unsigned char *string, size_t sizeInBytes, _locale_t plocinfo ) { size_t stringlen; /* validation section */ _VALIDATE_RETURN_ERRCODE((string != nullptr && sizeInBytes > 0) || (string == nullptr && sizeInBytes == 0), EINVAL); if (string == nullptr) { /* nothing to do */ return 0; } stringlen = strnlen((char *)string, sizeInBytes); if (stringlen >= sizeInBytes) { _RESET_STRING(string, sizeInBytes); _RETURN_DEST_NOT_NULL_TERMINATED(string, sizeInBytes); } _FILL_STRING(string, sizeInBytes, stringlen + 1); unsigned char *cp, *dst; _LocaleUpdate _loc_update(plocinfo); for (cp = string, dst = string; *cp; ++cp) { if ( _ismbblead_l(*cp, _loc_update.GetLocaleT()) ) { int retval; unsigned char ret[4]; if ( (retval = __acrt_LCMapStringA( _loc_update.GetLocaleT(), _loc_update.GetLocaleT()->mbcinfo->mblocalename, LCMAP_UPPERCASE, (const char *)cp, 2, (char *)ret, 2, _loc_update.GetLocaleT()->mbcinfo->mbcodepage, TRUE )) == 0 ) { errno = EILSEQ; _RESET_STRING(string, sizeInBytes); return errno; } *(dst++) = ret[0]; ++cp; if (retval > 1) { *(dst++) = ret[1]; } } else /* single byte, macro version */ *(dst++) = (unsigned char) _mbbtoupper_l(*cp, _loc_update.GetLocaleT()); } /* null terminate the string */ *dst = '\0'; return 0; }
static errno_t __cdecl _wcslwr_s_l_stat ( wchar_t * wsrc, size_t sizeInWords, _locale_t plocinfo ) { wchar_t *p; /* traverses string for C locale conversion */ wchar_t *wdst; /* wide version of string in alternate case */ int dstsize; /* size in wide chars of wdst string buffer (include null) */ errno_t e = 0; size_t stringlen; /* validation section */ _VALIDATE_RETURN_ERRCODE(wsrc != NULL, EINVAL); stringlen = wcsnlen(wsrc, sizeInWords); if (stringlen >= sizeInWords) { _RESET_STRING(wsrc, sizeInWords); _RETURN_DEST_NOT_NULL_TERMINATED(wsrc, sizeInWords); } _FILL_STRING(wsrc, sizeInWords, stringlen + 1); if ( plocinfo->locinfo->locale_name[LC_CTYPE] == NULL) { for ( p = wsrc ; *p ; p++ ) { if ( (*p >= (wchar_t)L'A') && (*p <= (wchar_t)L'Z') ) { *p -= L'A' - L'a'; } } return 0; } /* C locale */ /* Inquire size of wdst string */ if ( (dstsize = __crtLCMapStringW( plocinfo->locinfo->locale_name[LC_CTYPE], LCMAP_LOWERCASE, wsrc, -1, NULL, 0 )) == 0 ) { errno = EILSEQ; return errno; } if (sizeInWords < (size_t)dstsize) { _RESET_STRING(wsrc, sizeInWords); _RETURN_BUFFER_TOO_SMALL(wsrc, sizeInWords); } /* Allocate space for wdst */ wdst = (wchar_t *)_calloca(dstsize, sizeof(wchar_t)); if (wdst == NULL) { errno = ENOMEM; return errno; } /* Map wrc string to wide-character wdst string in alternate case */ if (__crtLCMapStringW( plocinfo->locinfo->locale_name[LC_CTYPE], LCMAP_LOWERCASE, wsrc, -1, wdst, dstsize ) != 0) { /* Copy wdst string to user string */ e = wcscpy_s(wsrc, sizeInWords, wdst); } else { e = errno = EILSEQ; } _freea(wdst); return e; }