Commit 6467c832 authored by Piotr Caban's avatar Piotr Caban Committed by Alexandre Julliard

msvcrt: Added _gmtime32_s and _gmtime64_s implementation.

parent 471bad1e
...@@ -719,9 +719,9 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
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;
}
*MSVCRT__errno() = MSVCRT_EINVAL;
return MSVCRT_EINVAL;
}
ULONGLONG time = *secs * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970; time = *secs * (ULONGLONG)TICKSPERSEC + TICKS_1601_TO_1970;
ft.dwHighDateTime = (UINT)(time >> 32); ft.dwHighDateTime = (UINT)(time >> 32);
ft.dwLowDateTime = (UINT)time; ft.dwLowDateTime = (UINT)time;
FileTimeToSystemTime(&ft, &st); FileTimeToSystemTime(&ft, &st);
res->tm_sec = st.wSecond;
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];
}
res->tm_yday += st.wDay - 1;
res->tm_isdst = 0;
return 0;
}
if (st.wYear < 1970) return NULL; /*********************************************************************
* _gmtime64 (MSVCRT.@)
*/
struct MSVCRT_tm* CDECL MSVCRT__gmtime64(const MSVCRT___time64_t *secs)
{
thread_data_t * const data = msvcrt_get_thread_data();
data->time_buffer.tm_sec = st.wSecond; if(MSVCRT__gmtime64_s(&data->time_buffer, secs))
data->time_buffer.tm_min = st.wMinute; return NULL;
data->time_buffer.tm_hour = st.wHour; return &data->time_buffer;
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; /*********************************************************************
data->time_buffer.tm_isdst = 0; * _gmtime32_s (MSVCRT.@)
*/
int CDECL MSVCRT__gmtime32_s(struct MSVCRT_tm *res, const MSVCRT___time32_t *secs)
{
MSVCRT___time64_t secs64;
return &data->time_buffer; 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) ...@@ -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 );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment