Esempio n. 1
0
extern "C" errno_t __cdecl wcsrtombs_s(
        size_t *pRetValue,
        char *dst,
        size_t sizeInBytes,
        const wchar_t **src,
        size_t n,
        mbstate_t *pmbst
        )
{
    size_t retsize;

    if (pRetValue != NULL)
    {
        *pRetValue = -1;
    }

    /* validation section */
    _VALIDATE_RETURN_ERRCODE((dst == NULL && sizeInBytes == 0) || (dst != NULL && sizeInBytes > 0), EINVAL);
    if (dst != NULL)
    {
        _RESET_STRING(dst, sizeInBytes);
    }
    _VALIDATE_RETURN_ERRCODE(src != NULL, EINVAL);

    /* Call a non-deprecated helper to do the work. */
    retsize = _wcsrtombs_helper(dst, src, (n > sizeInBytes ? sizeInBytes : n), pmbst);

    if (retsize == (size_t)-1)
    {
        if (dst != NULL)
        {
            _RESET_STRING(dst, sizeInBytes);
        }
        return errno;
    }

    /* count the null terminator */
    retsize++;

    if (dst != NULL)
    {
        /* return error if the string does not fit */
        if (retsize > sizeInBytes)
        {
            _RESET_STRING(dst, sizeInBytes);
            _VALIDATE_RETURN_ERRCODE(retsize <= sizeInBytes, ERANGE);
        }

        /* ensure the string is null terminated */
        dst[retsize - 1] = '\0';
    }

    if (pRetValue != NULL)
    {
        *pRetValue = retsize;
    }

    return 0;
}
Esempio n. 2
0
extern "C" errno_t __cdecl _wcstombs_s_l(
    size_t* pConvertedChars,
    char* dst,
    size_t sizeInBytes,
    const wchar_t* src,
    size_t n,
    _locale_t plocinfo
) {
    size_t retsize;
    errno_t retvalue = 0;
    /* validation section */
    _VALIDATE_RETURN_ERRCODE((dst != NULL && sizeInBytes > 0) || (dst == NULL && sizeInBytes == 0), EINVAL);

    if (dst != NULL) {
        _RESET_STRING(dst, sizeInBytes);
    }

    if (pConvertedChars != NULL) {
        *pConvertedChars = 0;
    }

    retsize = _wcstombs_l_helper(dst, src, (n > sizeInBytes ? sizeInBytes : n), plocinfo);

    if (retsize == (size_t) - 1) {
        if (dst != NULL) {
            _RESET_STRING(dst, sizeInBytes);
        }

        return errno;
    }

    /* count the null terminator */
    retsize++;

    if (dst != NULL) {
        /* return error if the string does not fit, unless n == _TRUNCATE */
        if (retsize > sizeInBytes) {
            if (n != _TRUNCATE) {
                _RESET_STRING(dst, sizeInBytes);
                _VALIDATE_RETURN_ERRCODE(sizeInBytes > retsize, ERANGE);
            }

            retsize = sizeInBytes;
            retvalue = STRUNCATE;
        }

        /* ensure the string is null terminated */
        dst[retsize - 1] = '\0';
    }

    if (pConvertedChars != NULL) {
        *pConvertedChars = retsize;
    }

    return retvalue;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
errno_t __cdecl _tctime64_s (
        _TSCHAR * buffer,
        size_t sizeInChars,
        const __time64_t *timp
        )
{
        struct tm tmtemp;
        errno_t e;

        _VALIDATE_RETURN_ERRCODE(
            ( ( buffer != NULL ) && ( sizeInChars > 0 ) ),
            EINVAL
        )

        _RESET_STRING(buffer, sizeInChars);

        _VALIDATE_RETURN_ERRCODE( ( timp != NULL ), EINVAL )
        _VALIDATE_RETURN_ERRCODE_NOEXC( ( *timp >= 0 ), EINVAL )

        e = _localtime64_s(&tmtemp, timp);
        if ( e == 0 )
        {
            e = _tasctime_s(buffer, sizeInChars, &tmtemp);
        }
        return e;
}
Esempio n. 5
0
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;
}
Esempio n. 6
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
extern "C" errno_t __cdecl _gcvt_s (
        char *buf,
        size_t sizeInChars,
        double value,
        int ndec
        )
{
        STRFLT string;
        int    magnitude;
        _CRT_DOUBLE *pdvalue = (_CRT_DOUBLE *)&value;

        char *str;
        char *stop;
        errno_t e;
    _locale_t plocinfo = NULL;
    _LocaleUpdate _loc_update(plocinfo);
        struct _strflt strfltstruct;    /* temporary buffers */
        char   resultstring[22 /* MAX_MAN_DIGITS+1 */];

        /* validation section */
        _VALIDATE_RETURN_ERRCODE(buf != NULL, EINVAL);
        _VALIDATE_RETURN_ERRCODE(sizeInChars > 0, EINVAL);
        _RESET_STRING(buf, sizeInChars);
        _VALIDATE_RETURN_ERRCODE((size_t)ndec < sizeInChars, ERANGE);
        /* _cftoe and _cftof (used below) are more strict in validating sizeInChars */

        /* get the magnitude of the number */

        string = _fltout2( *pdvalue, &strfltstruct, resultstring, _countof(resultstring) );

        magnitude = string->decpt - 1;

        /* output the result according to the Fortran G format as outlined in
           Fortran language specification */

        if ( magnitude < -1  ||  magnitude > ndec-1 )
                /* then  Ew.d  d = ndec */
                e = _cftoe( &value, buf, sizeInChars, ndec-1, 0);
        else
                /* Fw.d  where d = ndec-string->decpt */
                e = _cftof( &value, buf, sizeInChars, ndec-string->decpt );

        if (e == 0)
        {
                /* remove the trailing zeroes before the exponent; we don't need to check for sizeInChars */
                str = buf;
                while (*str && *str != *__LCONV(_loc_update.GetLocaleT()->locinfo)->decimal_point)
                        str++;

                if (*str++)
                {
                        while (*str && *str != 'e')
                                str++;

                        stop = str--;

                        while (*str == '0')
                                str--;

                        while (*++str = *stop++)
                                ;
                }
        }
        else
        {
                errno = e;
        }

        return e;
}
Esempio n. 9
0
errno_t __cdecl _tasctime_s (
    _TSCHAR *buffer,
    size_t sizeInChars,
    const struct tm *tb
    )
{
    _TSCHAR *p = buffer;
    int day, mon;
    int i;

    _VALIDATE_RETURN_ERRCODE(
        ( buffer != NULL ) && ( sizeInChars > 0 ),
        EINVAL
    )

    _RESET_STRING(buffer, sizeInChars);

    _VALIDATE_RETURN_ERRCODE(
        ( sizeInChars >= _ASCBUFSIZE ),
        EINVAL
    )
    _VALIDATE_RETURN_ERRCODE(
        ( tb != NULL ),
        EINVAL
    )
    _VALIDATE_RETURN_ERRCODE(
        ( tb->tm_year >= 0 ),
        EINVAL
    )
    // month 0 based
    _VALIDATE_RETURN_ERRCODE(
        ( ( tb->tm_mon  >= 0 ) && ( tb->tm_mon  <= 11 ) ),
        EINVAL
    )
    // hour/min/sec 0 based
    _VALIDATE_RETURN_ERRCODE(
        ( ( tb->tm_hour >= 0 ) && ( tb->tm_hour <= 23 ) ),
        EINVAL
    )
    _VALIDATE_RETURN_ERRCODE(
        ( ( tb->tm_min  >= 0 ) && ( tb->tm_min  <= 59 ) ),
        EINVAL
    )
    _VALIDATE_RETURN_ERRCODE(
        ( ( tb->tm_sec  >= 0 ) && ( tb->tm_sec  <= 59 ) ),
        EINVAL
    )
    // day 1 based
    _VALIDATE_RETURN_ERRCODE(
        (
            ( tb->tm_mday >= 1 ) &&
            (
                // Day is in valid range for the month
                ( ( _days[ tb->tm_mon + 1 ] - _days[ tb->tm_mon ] ) >=
                        tb->tm_mday ) ||
                // Special case for Feb in a leap year
                (
                    ( IS_LEAP_YEAR( tb->tm_year + 1900 ) ) &&
                    ( tb->tm_mon == 1 ) &&
                    ( tb->tm_mday <= 29 )
                )
            )
        ),
        EINVAL
    )
    // week day 0 based
    _VALIDATE_RETURN_ERRCODE(
        ( ( tb->tm_wday >= 0 ) && ( tb->tm_wday <= 6 ) ),
        EINVAL
    )


    /* copy day and month names into the buffer */

    day = tb->tm_wday * 3;      /* index to correct day string */
    mon = tb->tm_mon * 3;       /* index to correct month string */
    for (i=0; i < 3; i++,p++) {
        *p = *(__dnames + day + i);
        *(p+4) = *(__mnames + mon + i);
    }

    *p = _T(' ');           /* blank between day and month */

    p += 4;

    *p++ = _T(' ');
    p = store_dt(p, tb->tm_mday);   /* day of the month (1-31) */
    *p++ = _T(' ');
    p = store_dt(p, tb->tm_hour);   /* hours (0-23) */
    *p++ = _T(':');
    p = store_dt(p, tb->tm_min);    /* minutes (0-59) */
    *p++ = _T(':');
    p = store_dt(p, tb->tm_sec);    /* seconds (0-59) */
    *p++ = _T(' ');
    p = store_dt(p, 19 + (tb->tm_year/100)); /* year (after 1900) */
    p = store_dt(p, tb->tm_year%100);
    *p++ = _T('\n');
    *p = _T('\0');


    return 0;
}
Esempio n. 10
0
errno_t __cdecl _cgetws_s (
        wchar_t *string,
        size_t sizeInWords,
        size_t * pSizeRead
        )
{
        ULONG oldstate;
        ULONG num_read;
        errno_t err = 0;

        _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((string != NULL), EINVAL);
        _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((sizeInWords > 0), EINVAL);
        _RESET_STRING(string, sizeInWords);

        _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE((pSizeRead != NULL), EINVAL);

        _mlock(_CONIO_LOCK);            /* lock the console */
        __TRY

            /*
             * We need to decrement sizeInWords because ReadConsole reads as
             * many characters as the parameter passed, doesn't null terminate
             */

            --sizeInWords;
            *pSizeRead = 0;

            /*
             * If the __console_whcar_buffer_used is set, then first fill the
             * buffered character and then proceed.
             */
            if (__console_wchar_buffer_used != 0 && sizeInWords > 0)
            {
                *string++ = __console_wchar_buffer;
                __console_wchar_buffer = 0;
                --sizeInWords;
                (*pSizeRead)++;
                if (__console_wchar_buffer == L'\0')
                    sizeInWords = 0;
            }

                        /* if the user only asked for one character, we have now filled their request
                        */
            if (sizeInWords != 0)
                        {
                                /*
                                * _coninpfh, the handle to the console input, is created the first
                                * time that either _getch() or _cgets() or _kbhit() is called.
                                */

                                if ( _coninpfh == -2 )
                                        __initconin();

                                if ( _coninpfh != -1 ) {

                                        GetConsoleMode( (HANDLE)_coninpfh, &oldstate );
                                        SetConsoleMode( (HANDLE)_coninpfh, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
                                        // First try usual way just as _cgets
                                        if ( bUseW)
                                        {
                                                if ( !ReadConsoleW( (HANDLE)_coninpfh,
                                                                                        (LPVOID)string,
                                                                                        (DWORD)sizeInWords,
                                                                                        &num_read,
                                                                                        NULL )
                                                        )
                                                {
                                                        if ( bUseW == 2 )
                                                        {
                                                                if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
                                                                        bUseW = FALSE;
                                                                else
                                                                        bUseW = TRUE;
                                                        }
                                                }
                                                else
                                                {
                                                        bUseW = TRUE;

                                                        /* set length of string and null terminate it */

                                                        if (string[num_read - 2] == L'\r') {
                                                                (*pSizeRead) += num_read - 2;
                                                                string[num_read - 2] = L'\0';
                                                        } else if ( (num_read == sizeInWords) &&
                                                                                (string[num_read - 1] == L'\r') ) {
                                                        /* special case 1 - \r\n straddles the boundary */
                                                                (*pSizeRead) += num_read -1;
                                                                string[num_read - 1] = L'\0';
                                                        } else if ( (num_read == 1) && (string[0] == L'\n') ) {
                                                                /* special case 2 - read a single '\n'*/
                                                                string[0] = L'\0';
                                                                (*pSizeRead) += 0;
                                                        } else {
                                                                (*pSizeRead) += num_read;
                                                                string[num_read] = L'\0';
                                                        }
                                                }
                                        }
                                        // If ReadConsoleW is not present, use ReadConsoleA and then convert
                                        // to Wide Char.
                                        if ( !bUseW)
                                        {
                                                static char AStr[BUF_MAX_LEN +1];
                                                static int in_buff = 0, was_buff_full = 0;
                                                unsigned int Copy, Sz, consoleCP;
                                                unsigned int last_read = 0, i;
                                                consoleCP = GetConsoleCP();
                                                do {
                                                        if (!in_buff)
                                                        {
                                                                if ( ReadConsoleA( (HANDLE)_coninpfh,
                                                                                                        (LPVOID)AStr,
                                                                                                        BUF_MAX_LEN,
                                                                                                        &num_read,
                                                                                   NULL) &&
                                                                     num_read <= BUF_MAX_LEN
                                                                        ) {
                                                                        if (num_read >= 2 && AStr[num_read -2] == '\r')
                                                                        {
                                                                                AStr[num_read -2] = '\0';
                                                                        }
                                                                        else if (num_read == BUF_MAX_LEN &&
                                                                                        AStr[num_read -1] == '\r')
                                                                                AStr[num_read -1] = '\0';
                                                                        else if (num_read == 1 && AStr[0] == '\n')
                                                                                AStr[0] = '\0';
                                                                        else
                                                                                AStr[num_read] = '\0';
                                                                } else {
                                                                        _dosmaperr(GetLastError());
                                                                        err = errno;
                                                                }
                                                        }
                                                        for ( i = 0; AStr[i] != '\0' &&
                                                                                i < (BUF_MAX_LEN) &&
                                                                                last_read < sizeInWords; i += Sz)
                                                        {
                                                                // Check if this character is lead byte. If yes, the size
                                                                // of this character is 2. Else 1.
                                                                if ( IsDBCSLeadByteEx( GetConsoleCP(), AStr[i]))
                                                                        Sz = 2;
                                                                else
                                                                        Sz = 1;
                                                                if ( (Copy = MultiByteToWideChar( consoleCP,
                                                                                                                                MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
                                                                                                                                &AStr[i],
                                                                                                                                Sz,
                                                                                                                                &string[last_read],
                                                                                                                                (int)sizeInWords - last_read)))
                                                                {
                                                                        last_read += Copy;
                                                                }
                                                        }
                                                        // Check if this conversion was from buffer. If yes, was
                                                        // buffer fully filled when it was first read using
                                                        // ReadConsoleA. If the buffer not fully filled, we don't need
                                                        // to read more from buffer. This is necessary to make it
                                                        // behave same as if we are reading using ReadConsoleW.
                                                        if ( in_buff && i == strlen(AStr))
                                                        {
                                                                in_buff = 0;
                                                                if ( was_buff_full)
                                                                {
                                                                        was_buff_full = 0;
                                                                        continue;
                                                                }
                                                                else
                                                                {
                                                                        break;
                                                                }
                                                        }
                                                        else if ( i < (BUF_MAX_LEN))
                                                                break;
                                                } while (last_read < sizeInWords);
                                                // We save the buffer to be used again.
                                                if ( i < strlen(AStr))
                                                {
                                                        in_buff = 1;
                                                        if ( strlen(AStr) == (BUF_MAX_LEN))
                                                                was_buff_full = 1;
                                                        memmove(AStr, &AStr[i], BUF_MAX_LEN +1 - i);
                                                }
                                                string[last_read] = '\0';
                                                (*pSizeRead) += last_read;
                                        }

                                        SetConsoleMode( (HANDLE)_coninpfh, oldstate );
                                } else {
                                        _dosmaperr(GetLastError());
                                        err = errno;
                                }
                        }

        __FINALLY
            _munlock(_CONIO_LOCK);          /* unlock the console */
        __END_TRY_FINALLY

        if (err != 0)
        {
            errno = err;
        }
        return err;
}