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;
}
Exemple #2
0
_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;
}