msvcrt: Added _gmtime32_s and _gmtime64_s implementation.
This commit is contained in:
parent
471bad1ee8
commit
6467c8325f
|
@ -719,9 +719,9 @@
|
||||||
@ stub _getws_s
|
@ stub _getws_s
|
||||||
@ cdecl -i386 _global_unwind2(ptr) msvcrt._global_unwind2
|
@ cdecl -i386 _global_unwind2(ptr) msvcrt._global_unwind2
|
||||||
@ cdecl _gmtime32(ptr) msvcrt._gmtime32
|
@ cdecl _gmtime32(ptr) msvcrt._gmtime32
|
||||||
@ stub _gmtime32_s
|
@ cdecl _gmtime32_s(ptr ptr) msvcrt._gmtime32_s
|
||||||
@ cdecl _gmtime64(ptr) msvcrt._gmtime64
|
@ cdecl _gmtime64(ptr) msvcrt._gmtime64
|
||||||
@ stub _gmtime64_s
|
@ cdecl _gmtime64_s(ptr ptr) msvcrt._gmtime64_s
|
||||||
@ cdecl _heapadd(ptr long) msvcrt._heapadd
|
@ cdecl _heapadd(ptr long) msvcrt._heapadd
|
||||||
@ cdecl _heapchk() msvcrt._heapchk
|
@ cdecl _heapchk() msvcrt._heapchk
|
||||||
@ cdecl _heapmin() msvcrt._heapmin
|
@ cdecl _heapmin() msvcrt._heapmin
|
||||||
|
|
|
@ -566,9 +566,9 @@
|
||||||
@ stub _getws_s
|
@ stub _getws_s
|
||||||
@ cdecl -i386 _global_unwind2(ptr) msvcrt._global_unwind2
|
@ cdecl -i386 _global_unwind2(ptr) msvcrt._global_unwind2
|
||||||
@ cdecl _gmtime32(ptr) msvcrt._gmtime32
|
@ cdecl _gmtime32(ptr) msvcrt._gmtime32
|
||||||
@ stub _gmtime32_s
|
@ cdecl _gmtime32_s(ptr ptr) msvcrt._gmtime32_s
|
||||||
@ cdecl _gmtime64(ptr) msvcrt._gmtime64
|
@ cdecl _gmtime64(ptr) msvcrt._gmtime64
|
||||||
@ stub _gmtime64_s
|
@ cdecl _gmtime64_s(ptr ptr) msvcrt._gmtime64_s
|
||||||
@ cdecl _heapadd(ptr long) msvcrt._heapadd
|
@ cdecl _heapadd(ptr long) msvcrt._heapadd
|
||||||
@ cdecl _heapchk() msvcrt._heapchk
|
@ cdecl _heapchk() msvcrt._heapchk
|
||||||
@ cdecl _heapmin() msvcrt._heapmin
|
@ cdecl _heapmin() msvcrt._heapmin
|
||||||
|
|
|
@ -554,9 +554,9 @@
|
||||||
@ stub _getws_s
|
@ stub _getws_s
|
||||||
@ cdecl -i386 _global_unwind2(ptr) msvcrt._global_unwind2
|
@ cdecl -i386 _global_unwind2(ptr) msvcrt._global_unwind2
|
||||||
@ cdecl _gmtime32(ptr) msvcrt._gmtime32
|
@ cdecl _gmtime32(ptr) msvcrt._gmtime32
|
||||||
@ stub _gmtime32_s
|
@ cdecl _gmtime32_s(ptr ptr) msvcrt._gmtime32_s
|
||||||
@ cdecl _gmtime64(ptr) msvcrt._gmtime64
|
@ cdecl _gmtime64(ptr) msvcrt._gmtime64
|
||||||
@ stub _gmtime64_s
|
@ cdecl _gmtime64_s(ptr ptr) msvcrt._gmtime64_s
|
||||||
@ cdecl _heapadd(ptr long) msvcrt._heapadd
|
@ cdecl _heapadd(ptr long) msvcrt._heapadd
|
||||||
@ cdecl _heapchk() msvcrt._heapchk
|
@ cdecl _heapchk() msvcrt._heapchk
|
||||||
@ cdecl _heapmin() msvcrt._heapmin
|
@ cdecl _heapmin() msvcrt._heapmin
|
||||||
|
|
|
@ -499,9 +499,9 @@
|
||||||
@ cdecl _getws(ptr) MSVCRT__getws
|
@ cdecl _getws(ptr) MSVCRT__getws
|
||||||
@ cdecl -i386 _global_unwind2(ptr)
|
@ cdecl -i386 _global_unwind2(ptr)
|
||||||
@ cdecl _gmtime32(ptr) MSVCRT__gmtime32
|
@ cdecl _gmtime32(ptr) MSVCRT__gmtime32
|
||||||
# stub _gmtime32_s
|
@ cdecl _gmtime32_s(ptr ptr) MSVCRT__gmtime32_s
|
||||||
@ cdecl _gmtime64(ptr) MSVCRT__gmtime64
|
@ cdecl _gmtime64(ptr) MSVCRT__gmtime64
|
||||||
# stub _gmtime64_s
|
@ cdecl _gmtime64_s(ptr ptr) MSVCRT__gmtime64_s
|
||||||
@ cdecl _heapadd (ptr long)
|
@ cdecl _heapadd (ptr long)
|
||||||
@ cdecl _heapchk()
|
@ cdecl _heapchk()
|
||||||
@ cdecl _heapmin()
|
@ cdecl _heapmin()
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
static __time32_t (__cdecl *p_mkgmtime32)(struct tm*);
|
static __time32_t (__cdecl *p_mkgmtime32)(struct tm*);
|
||||||
static struct tm* (__cdecl *p_gmtime32)(__time32_t*);
|
static struct tm* (__cdecl *p_gmtime32)(__time32_t*);
|
||||||
|
static errno_t (__cdecl *p_gmtime32_s)(struct tm*, __time32_t*);
|
||||||
static errno_t (__cdecl *p_strtime_s)(char*,size_t);
|
static errno_t (__cdecl *p_strtime_s)(char*,size_t);
|
||||||
static errno_t (__cdecl *p_strdate_s)(char*,size_t);
|
static errno_t (__cdecl *p_strdate_s)(char*,size_t);
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ static void init(void)
|
||||||
HMODULE hmod = GetModuleHandleA("msvcrt.dll");
|
HMODULE hmod = GetModuleHandleA("msvcrt.dll");
|
||||||
|
|
||||||
p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
|
p_gmtime32 = (void*)GetProcAddress(hmod, "_gmtime32");
|
||||||
|
p_gmtime32_s = (void*)GetProcAddress(hmod, "_gmtime32_s");
|
||||||
p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
|
p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
|
||||||
p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
|
p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
|
||||||
p_strdate_s = (void*)GetProcAddress(hmod, "_strdate_s");
|
p_strdate_s = (void*)GetProcAddress(hmod, "_strdate_s");
|
||||||
|
@ -71,13 +73,21 @@ static void test_ctime(void)
|
||||||
static void test_gmtime(void)
|
static void test_gmtime(void)
|
||||||
{
|
{
|
||||||
__time32_t valid, gmt;
|
__time32_t valid, gmt;
|
||||||
struct tm* gmt_tm;
|
struct tm* gmt_tm, gmt_tm_s;
|
||||||
|
errno_t err;
|
||||||
|
|
||||||
if(!p_gmtime32) {
|
if(!p_gmtime32) {
|
||||||
win_skip("Skipping _gmtime32 tests\n");
|
win_skip("Skipping _gmtime32 tests\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gmt_tm = p_gmtime32(NULL);
|
||||||
|
ok(gmt_tm == NULL, "gmt_tm != NULL\n");
|
||||||
|
|
||||||
|
gmt = -1;
|
||||||
|
gmt_tm = p_gmtime32(&gmt);
|
||||||
|
ok(gmt_tm == NULL, "gmt_tm != NULL\n");
|
||||||
|
|
||||||
gmt = valid = 0;
|
gmt = valid = 0;
|
||||||
gmt_tm = p_gmtime32(&gmt);
|
gmt_tm = p_gmtime32(&gmt);
|
||||||
if(!gmt_tm) {
|
if(!gmt_tm) {
|
||||||
|
@ -133,6 +143,24 @@ static void test_gmtime(void)
|
||||||
gmt_tm->tm_isdst = 1;
|
gmt_tm->tm_isdst = 1;
|
||||||
gmt = p_mkgmtime32(gmt_tm);
|
gmt = p_mkgmtime32(gmt_tm);
|
||||||
ok(gmt == valid, "gmt = %u\n", gmt);
|
ok(gmt == valid, "gmt = %u\n", gmt);
|
||||||
|
|
||||||
|
if(!p_gmtime32_s) {
|
||||||
|
win_skip("Skipping _gmtime32_s tests\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
gmt = 0;
|
||||||
|
err = p_gmtime32_s(NULL, &gmt);
|
||||||
|
ok(err == EINVAL, "err = %d\n", err);
|
||||||
|
ok(errno == EINVAL, "errno = %d\n", errno);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
gmt = -1;
|
||||||
|
err = p_gmtime32_s(&gmt_tm_s, &gmt);
|
||||||
|
ok(err == EINVAL, "err = %d\n", err);
|
||||||
|
ok(errno == EINVAL, "errno = %d\n", errno);
|
||||||
|
ok(gmt_tm_s.tm_year == -1, "tm_year = %d\n", gmt_tm_s.tm_year);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_mktime(void)
|
static void test_mktime(void)
|
||||||
|
|
|
@ -232,37 +232,78 @@ struct MSVCRT_tm* CDECL MSVCRT_localtime(const MSVCRT___time32_t* secs)
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* _gmtime64 (MSVCRT.@)
|
* _gmtime64 (MSVCRT.@)
|
||||||
*/
|
*/
|
||||||
struct MSVCRT_tm* CDECL MSVCRT__gmtime64(const MSVCRT___time64_t* secs)
|
int CDECL MSVCRT__gmtime64_s(struct MSVCRT_tm *res, const MSVCRT___time64_t *secs)
|
||||||
{
|
{
|
||||||
thread_data_t * const data = msvcrt_get_thread_data();
|
int i;
|
||||||
int i;
|
FILETIME ft;
|
||||||
FILETIME ft;
|
SYSTEMTIME st;
|
||||||
SYSTEMTIME st;
|
ULONGLONG time;
|
||||||
|
|
||||||
ULONGLONG time = *secs * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
|
if(!res || !secs || *secs<0) {
|
||||||
|
if(res) {
|
||||||
|
res->tm_sec = -1;
|
||||||
|
res->tm_min = -1;
|
||||||
|
res->tm_hour = -1;
|
||||||
|
res->tm_mday = -1;
|
||||||
|
res->tm_year = -1;
|
||||||
|
res->tm_mon = -1;
|
||||||
|
res->tm_wday = -1;
|
||||||
|
res->tm_yday = -1;
|
||||||
|
res->tm_isdst = -1;
|
||||||
|
}
|
||||||
|
|
||||||
ft.dwHighDateTime = (UINT)(time >> 32);
|
*MSVCRT__errno() = MSVCRT_EINVAL;
|
||||||
ft.dwLowDateTime = (UINT)time;
|
return MSVCRT_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
FileTimeToSystemTime(&ft, &st);
|
time = *secs * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
|
||||||
|
|
||||||
if (st.wYear < 1970) return NULL;
|
ft.dwHighDateTime = (UINT)(time >> 32);
|
||||||
|
ft.dwLowDateTime = (UINT)time;
|
||||||
|
|
||||||
data->time_buffer.tm_sec = st.wSecond;
|
FileTimeToSystemTime(&ft, &st);
|
||||||
data->time_buffer.tm_min = st.wMinute;
|
|
||||||
data->time_buffer.tm_hour = st.wHour;
|
|
||||||
data->time_buffer.tm_mday = st.wDay;
|
|
||||||
data->time_buffer.tm_year = st.wYear - 1900;
|
|
||||||
data->time_buffer.tm_mon = st.wMonth - 1;
|
|
||||||
data->time_buffer.tm_wday = st.wDayOfWeek;
|
|
||||||
for (i = data->time_buffer.tm_yday = 0; i < st.wMonth - 1; i++) {
|
|
||||||
data->time_buffer.tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
|
|
||||||
}
|
|
||||||
|
|
||||||
data->time_buffer.tm_yday += st.wDay - 1;
|
res->tm_sec = st.wSecond;
|
||||||
data->time_buffer.tm_isdst = 0;
|
res->tm_min = st.wMinute;
|
||||||
|
res->tm_hour = st.wHour;
|
||||||
|
res->tm_mday = st.wDay;
|
||||||
|
res->tm_year = st.wYear - 1900;
|
||||||
|
res->tm_mon = st.wMonth - 1;
|
||||||
|
res->tm_wday = st.wDayOfWeek;
|
||||||
|
for (i = res->tm_yday = 0; i < st.wMonth - 1; i++) {
|
||||||
|
res->tm_yday += MonthLengths[IsLeapYear(st.wYear)][i];
|
||||||
|
}
|
||||||
|
|
||||||
return &data->time_buffer;
|
res->tm_yday += st.wDay - 1;
|
||||||
|
res->tm_isdst = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* _gmtime64 (MSVCRT.@)
|
||||||
|
*/
|
||||||
|
struct MSVCRT_tm* CDECL MSVCRT__gmtime64(const MSVCRT___time64_t *secs)
|
||||||
|
{
|
||||||
|
thread_data_t * const data = msvcrt_get_thread_data();
|
||||||
|
|
||||||
|
if(MSVCRT__gmtime64_s(&data->time_buffer, secs))
|
||||||
|
return NULL;
|
||||||
|
return &data->time_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* _gmtime32_s (MSVCRT.@)
|
||||||
|
*/
|
||||||
|
int CDECL MSVCRT__gmtime32_s(struct MSVCRT_tm *res, const MSVCRT___time32_t *secs)
|
||||||
|
{
|
||||||
|
MSVCRT___time64_t secs64;
|
||||||
|
|
||||||
|
if(secs) {
|
||||||
|
secs64 = *secs;
|
||||||
|
return MSVCRT__gmtime64_s(res, &secs64);
|
||||||
|
}
|
||||||
|
return MSVCRT__gmtime64_s(res, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
@ -270,7 +311,12 @@ struct MSVCRT_tm* CDECL MSVCRT__gmtime64(const MSVCRT___time64_t* secs)
|
||||||
*/
|
*/
|
||||||
struct MSVCRT_tm* CDECL MSVCRT__gmtime32(const MSVCRT___time32_t* secs)
|
struct MSVCRT_tm* CDECL MSVCRT__gmtime32(const MSVCRT___time32_t* secs)
|
||||||
{
|
{
|
||||||
MSVCRT___time64_t secs64 = *secs;
|
MSVCRT___time64_t secs64;
|
||||||
|
|
||||||
|
if(!secs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
secs64 = *secs;
|
||||||
return MSVCRT__gmtime64( &secs64 );
|
return MSVCRT__gmtime64( &secs64 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue