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 )
        _VALIDATE_RETURN_ERRCODE_NOEXC( ( *timp <= _MAX__TIME64_T ), EINVAL )

        e = _localtime64_s(&tmtemp, timp);
        if ( e == 0 )
        {
            e = _tasctime_s(buffer, sizeInChars, &tmtemp);
        }
        return e;
}
Example #2
0
static errno_t __cdecl common_freopen(
    FILE**             const result,
    Character const*   const file_name,
    Character const*   const mode,
    __crt_stdio_stream const stream,
    int                const share_flag
    ) throw()
{
    typedef __acrt_stdio_char_traits<Character> stdio_traits;

    _VALIDATE_RETURN_ERRCODE(result != nullptr, EINVAL);
    *result = nullptr;

    // C11 7.21.5.4/3:  "If filename is a null pointer, the freopen function
    // attempts to change the mode of the stream to that specified by mode, as
    // if the name of the file currently associated with the stream had been
    // used. It is implementation-defined which changes of mode are permitted
    // (if any), and under what circumstances."
    //
    // In our implementation, we do not currently support changing the mode
    // in this way.  In the future, we might consider use of ReOpenFile to
    // implement support for changing the mode.
    _VALIDATE_RETURN_ERRCODE_NOEXC(file_name != nullptr, EBADF);

    _VALIDATE_RETURN_ERRCODE(mode      != nullptr, EINVAL);
    _VALIDATE_RETURN_ERRCODE(stream.valid()      , EINVAL);

    // Just as in the common_fsopen function, we do not hard-validate empty
    // 'file_name' strings in this function:
    _VALIDATE_RETURN_ERRCODE_NOEXC(*file_name != 0, EINVAL);

    errno_t return_value = 0;

    _lock_file(stream.public_stream());
    __try
    {
        // If the stream is in use, try to close it, ignoring possible errors:
        if (stream.is_in_use())
            _fclose_nolock(stream.public_stream());

        stream->_ptr  = nullptr;
        stream->_base = nullptr;
        stream->_cnt  = 0;
        stream.unset_flags(-1);

        // We may have called fclose above, which will deallocate the stream.
        // We still hold the lock on the stream, though, so we can just reset
        // the allocated flag to retain ownership.
        stream.set_flags(_IOALLOCATED);

        *result = stdio_traits::open_file(file_name, mode, share_flag, stream.public_stream());
        if (*result == nullptr)
        {
            stream.unset_flags(_IOALLOCATED);
            return_value = errno;
        }
    }
    __finally
    {
        _unlock_file(stream.public_stream());
    }

    return return_value;
}
static errno_t __cdecl common_localtime_s(
    tm*             const ptm,
    TimeType const* const ptime
    ) throw()
{
    typedef __crt_time_time_t_traits<TimeType> time_traits;

    _VALIDATE_RETURN_ERRCODE(ptm != nullptr, EINVAL);
    memset(ptm, 0xff, sizeof(tm));

    _VALIDATE_RETURN_ERRCODE(ptime != nullptr, EINVAL);

    // Check for illegal time_t value:
    _VALIDATE_RETURN_ERRCODE_NOEXC(*ptime >= 0,                       EINVAL);
    _VALIDATE_RETURN_ERRCODE_NOEXC(*ptime <= time_traits::max_time_t, EINVAL);

    __tzset();

    int  daylight = 0;
    long dstbias  = 0;
    long timezone = 0;
    _ERRCHECK(_get_daylight(&daylight));
    _ERRCHECK(_get_dstbias (&dstbias ));
    _ERRCHECK(_get_timezone(&timezone));

    if (*ptime > 3 * _DAY_SEC && *ptime < time_traits::max_time_t - 3 * _DAY_SEC)
    {
        // The date does not fall within the first three or last three representable
        // days; therefore, there is no possibility of overflowing or underflowing
        // the time_t representation as we compensate for time zone and daylight
        // savings time.
        TimeType ltime = *ptime - timezone;

        errno_t status0 = time_traits::gmtime_s(ptm, &ltime);
        if (status0 != 0)
            return status0;

        // Check and adjust for daylight savings time:
        if (daylight && _isindst(ptm))
        {
            ltime -= dstbias;
            
            errno_t const status1 = time_traits::gmtime_s(ptm, &ltime);
            if (status1 != 0)
                return status1;

            ptm->tm_isdst = 1;
        }
    }
    else
    {
        // The date falls within the first three or last three representable days;
        // therefore, it is possible that the time_t representation would overflow
        // or underflow while compensating for time zone and daylight savings time.
        // Therefore, we make the time zone and daylight savings time adjustments
        // directly in the tm structure.
        errno_t const status0 = time_traits::gmtime_s(ptm, ptime);
        if (status0 != 0)
            return status0;

        TimeType ltime = static_cast<TimeType>(ptm->tm_sec);

        // First, adjust for the time zone:
        if (daylight && _isindst(ptm))
        {
            ltime -= (timezone + dstbias);
            ptm->tm_isdst = 1;
        }
        else
        {
            ltime -= timezone;
        }

        ptm->tm_sec = static_cast<int>(ltime % 60);
        if (ptm->tm_sec < 0)
        {
            ptm->tm_sec += 60;
            ltime -= 60;
        }

        ltime = static_cast<TimeType>(ptm->tm_min) + ltime / 60;
        ptm->tm_min = static_cast<int>(ltime % 60);
        if (ptm->tm_min < 0)
        {
            ptm->tm_min += 60;
            ltime -= 60;
        }

        ltime = static_cast<TimeType>(ptm->tm_hour) + ltime / 60;
        ptm->tm_hour = static_cast<int>(ltime % 24);
        if (ptm->tm_hour < 0)
        {
            ptm->tm_hour += 24;
            ltime -=24;
        }

        ltime /= 24;

        if (ltime > 0)
        {
            // There is no possibility of overflowing the tm_day and tm_yday
            // members because the date can be no later than January 19.
            ptm->tm_wday = (ptm->tm_wday + static_cast<int>(ltime)) % 7;
            ptm->tm_mday += static_cast<int>(ltime);
            ptm->tm_yday += static_cast<int>(ltime);
        }
        else if (ltime < 0)
        {
            // It is possible to underflow the tm_mday and tm_yday fields.  If
            // this happens, then the adjusted date must lie in December 1969:
            ptm->tm_wday = (ptm->tm_wday + 7 + static_cast<int>(ltime)) % 7;
            ptm->tm_mday += static_cast<int>(ltime);
            if (ptm->tm_mday <= 0)
            {
                ptm->tm_mday += 31;

                // Per assumption #4 above, the time zone can cause the date to
                // underflow the epoch by more than a day.
                ptm->tm_yday = ptm->tm_yday + static_cast<int>(ltime) + 365;
                ptm->tm_mon = 11;
                ptm->tm_year--;
            }
            else
            {
                ptm->tm_yday += static_cast<int>(ltime);
            }
        }
    }

    return 0;
}
static errno_t __cdecl common_configure_argv(_crt_argv_mode const mode) throw()
{
    typedef __crt_char_traits<Character> traits;

    _VALIDATE_RETURN_ERRCODE(
        mode == _crt_argv_expanded_arguments ||
        mode == _crt_argv_unexpanded_arguments, EINVAL);

    do_locale_initialization(Character());

    
    static Character program_name[MAX_PATH + 1];
    traits::get_module_file_name(nullptr, program_name, MAX_PATH);
    traits::set_program_name(&program_name[0]);

    // If there's no command line at all, then use the program name as the
    // command line to parse, so that argv[0] is initialized with the program
    // name.  (This won't happen when the program is run by cmd.exe, but it
    // could happen if the program is spawned via some other means.)
    Character* const raw_command_line = get_command_line(Character());
    Character* const command_line = raw_command_line == nullptr || raw_command_line[0] == '\0'
        ? program_name
        : raw_command_line;

    size_t argument_count  = 0;
    size_t character_count = 0;
    parse_command_line(
        command_line,
        static_cast<Character**>(nullptr),
        static_cast<Character*>(nullptr),
        &argument_count,
        &character_count);

    __crt_unique_heap_ptr<unsigned char> buffer(__acrt_allocate_buffer_for_argv(
        argument_count,
        character_count,
        sizeof(Character)));

    _VALIDATE_RETURN_ERRCODE_NOEXC(buffer, ENOMEM);

    Character** const first_argument = reinterpret_cast<Character**>(buffer.get());
    Character*  const first_string   = reinterpret_cast<Character*>(buffer.get() + argument_count * sizeof(Character*));

    parse_command_line(command_line, first_argument, first_string, &argument_count, &character_count);

    // If we are not expanding wildcards, then we are done...
    if (mode == _crt_argv_unexpanded_arguments)
    {
        __argc = static_cast<int>(argument_count - 1);
        get_argv(Character()) = reinterpret_cast<Character**>(buffer.detach());
        return 0;
    }

    // ... otherwise, we try to do the wildcard expansion:
    __crt_unique_heap_ptr<Character*> expanded_argv;
    errno_t const argv_expansion_status = expand_argv_wildcards(first_argument, expanded_argv.get_address_of());
    if (argv_expansion_status != 0)
        return argv_expansion_status;

    __argc = [&]()
    {
        size_t n = 0;
        for (auto it = expanded_argv.get(); *it; ++it, ++n) { }
        return static_cast<int>(n);
    }();

    get_argv(Character()) = expanded_argv.detach();
    return 0;
}