Andrew Nguyen : msvcrt: Implement _localtime64_s.

Alexandre Julliard julliard at winehq.org
Mon Oct 11 13:15:16 CDT 2010


Module: wine
Branch: master
Commit: e245cb52c6f4e2dd60a8e4989a2ba79e39039067
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e245cb52c6f4e2dd60a8e4989a2ba79e39039067

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Mon Oct 11 05:24:20 2010 -0500

msvcrt: Implement _localtime64_s.

---

 dlls/msvcr100/msvcr100.spec |    2 +-
 dlls/msvcr80/msvcr80.spec   |    2 +-
 dlls/msvcr90/msvcr90.spec   |    2 +-
 dlls/msvcrt/msvcrt.h        |    2 +
 dlls/msvcrt/msvcrt.spec     |    2 +-
 dlls/msvcrt/tests/time.c    |   70 +++++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/time.c          |   45 +++++++++++++++++++++++++++
 include/msvcrt/time.h       |    1 +
 8 files changed, 122 insertions(+), 4 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 79517e5..ace6201 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -849,7 +849,7 @@
 @ cdecl _localtime32(ptr) msvcrt._localtime32
 @ stub _localtime32_s
 @ cdecl _localtime64(ptr) msvcrt._localtime64
-@ stub _localtime64_s
+@ cdecl _localtime64_s(ptr ptr) msvcrt._localtime64_s
 @ cdecl _lock(long) msvcrt._lock
 @ stub _lock_file
 @ cdecl _locking(long long long) msvcrt._locking
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 3795264..3c03f09 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -695,7 +695,7 @@
 @ cdecl _localtime32(ptr) msvcrt._localtime32
 @ stub _localtime32_s
 @ cdecl _localtime64(ptr) msvcrt._localtime64
-@ stub _localtime64_s
+@ cdecl _localtime64_s(ptr ptr) msvcrt._localtime64_s
 @ cdecl _lock(long) msvcrt._lock
 @ stub _lock_file
 @ cdecl _locking(long long long) msvcrt._locking
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index c0ed8b6..5917bcc 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -683,7 +683,7 @@
 @ cdecl _localtime32(ptr) msvcrt._localtime32
 @ stub _localtime32_s
 @ cdecl _localtime64(ptr) msvcrt._localtime64
-@ stub _localtime64_s
+@ cdecl _localtime64_s(ptr ptr) msvcrt._localtime64_s
 @ cdecl _lock(long) msvcrt._lock
 @ stub _lock_file
 @ cdecl _locking(long long long) msvcrt._locking
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 8e0bd43..3d9639e 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -717,6 +717,8 @@ typedef void (__cdecl *MSVCRT___sighandler_t)(int);
 
 #define MSVCRT__TRUNCATE ((MSVCRT_size_t)-1)
 
+#define _MAX__TIME64_T    (((MSVCRT___time64_t)0x00000007 << 32) | 0x93406FFF)
+
 void  __cdecl    MSVCRT_free(void*);
 void* __cdecl    MSVCRT_malloc(MSVCRT_size_t);
 void* __cdecl    MSVCRT_calloc(MSVCRT_size_t,MSVCRT_size_t);
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 341093b..8f3a318 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -622,7 +622,7 @@
 @ cdecl _localtime32(ptr) MSVCRT__localtime32
 # stub _localtime32_s
 @ cdecl _localtime64(ptr) MSVCRT__localtime64
-# stub _localtime64_s
+@ cdecl _localtime64_s(ptr ptr)
 @ cdecl _lock(long)
 @ cdecl _locking(long long long) MSVCRT__locking
 @ cdecl _logb( double )
diff --git a/dlls/msvcrt/tests/time.c b/dlls/msvcrt/tests/time.c
index b11ecf7..38e06c2 100644
--- a/dlls/msvcrt/tests/time.c
+++ b/dlls/msvcrt/tests/time.c
@@ -27,6 +27,8 @@
 #include <stdio.h> /*printf*/
 #include <errno.h>
 
+#define _MAX__TIME64_T     (((__time64_t)0x00000007 << 32) | 0x93406FFF)
+
 #define SECSPERDAY         86400
 #define SECSPERHOUR        3600
 #define SECSPERMIN         60
@@ -38,6 +40,7 @@ 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_strdate_s)(char*,size_t);
+static errno_t    (__cdecl *p_localtime64_s)(struct tm*, __time64_t*);
 
 static void init(void)
 {
@@ -48,6 +51,7 @@ static void init(void)
     p_mkgmtime32 = (void*)GetProcAddress(hmod, "_mkgmtime32");
     p_strtime_s = (void*)GetProcAddress(hmod, "_strtime_s");
     p_strdate_s = (void*)GetProcAddress(hmod, "_strdate_s");
+    p_localtime64_s = (void*)GetProcAddress(hmod, "_localtime64_s");
 }
 
 static int get_test_year(time_t *start)
@@ -421,6 +425,71 @@ static void test_wstrtime(void)
     ok(count == 3, "Wrong format: count = %d, should be 3\n", count);
 }
 
+static void test_localtime64_s(void)
+{
+    struct tm tm;
+    __time64_t time;
+    errno_t err;
+
+    if (!p_localtime64_s)
+    {
+        win_skip("Skipping _localtime64_s tests\n");
+        return;
+    }
+
+    errno = EBADF;
+    err = p_localtime64_s(NULL, NULL);
+    ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+
+    errno = EBADF;
+    time = 0xdeadbeef;
+    err = p_localtime64_s(NULL, &time);
+    ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+
+    memset(&tm, 0, sizeof(tm));
+    errno = EBADF;
+    err = p_localtime64_s(&tm, NULL);
+    ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+    ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
+       tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
+       tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
+       "Expected tm structure members to be initialized to -1, got "
+       "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
+       tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
+       tm.tm_isdst);
+
+    memset(&tm, 0, sizeof(tm));
+    time = -1;
+    errno = EBADF;
+    err = p_localtime64_s(&tm, &time);
+    ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+    ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
+       tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
+       tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
+       "Expected tm structure members to be initialized to -1, got "
+       "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
+       tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
+       tm.tm_isdst);
+
+    memset(&tm, 0, sizeof(tm));
+    time = _MAX__TIME64_T + 1;
+    errno = EBADF;
+    err = p_localtime64_s(&tm, &time);
+    ok(err == EINVAL, "Expected _localtime64_s to return EINVAL, got %d\n", err);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+    ok(tm.tm_sec == -1 && tm.tm_min == -1 && tm.tm_hour == -1 &&
+       tm.tm_mday == -1 && tm.tm_mon == -1 && tm.tm_year == -1 &&
+       tm.tm_wday == -1 && tm.tm_yday == -1 && tm.tm_isdst == -1,
+       "Expected tm structure members to be initialized to -1, got "
+       "(%d, %d, %d, %d, %d, %d, %d, %d, %d)\n", tm.tm_sec, tm.tm_min,
+       tm.tm_hour, tm.tm_mday, tm.tm_mon, tm.tm_year, tm.tm_wday, tm.tm_yday,
+       tm.tm_isdst);
+}
+
 START_TEST(time)
 {
     init();
@@ -433,4 +502,5 @@ START_TEST(time)
     test_strtime();
     test_wstrdate();
     test_wstrtime();
+    test_localtime64_s();
 }
diff --git a/dlls/msvcrt/time.c b/dlls/msvcrt/time.c
index df31593..d0201e2 100644
--- a/dlls/msvcrt/time.c
+++ b/dlls/msvcrt/time.c
@@ -78,6 +78,19 @@ static inline void unix_tm_to_msvcrt( struct MSVCRT_tm *dest, const struct tm *s
     dest->tm_isdst = src->tm_isdst;
 }
 
+static inline void write_invalid_msvcrt_tm( struct MSVCRT_tm *tm )
+{
+    tm->tm_sec = -1;
+    tm->tm_min = -1;
+    tm->tm_hour = -1;
+    tm->tm_mday = -1;
+    tm->tm_mon = -1;
+    tm->tm_year = -1;
+    tm->tm_wday = -1;
+    tm->tm_yday = -1;
+    tm->tm_isdst = -1;
+}
+
 #define SECSPERDAY        86400
 /* 1601 to 1970 is 369 years plus 89 leap days */
 #define SECS_1601_TO_1970  ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
@@ -206,6 +219,38 @@ struct MSVCRT_tm* CDECL MSVCRT__localtime64(const MSVCRT___time64_t* secs)
 }
 
 /*********************************************************************
+ *      _localtime64_s (MSVCRT.@)
+ */
+int CDECL _localtime64_s(struct MSVCRT_tm *time, const MSVCRT___time64_t *secs)
+{
+    struct tm *tm;
+    time_t seconds;
+
+    if (!time || !secs || *secs < 0 || *secs > _MAX__TIME64_T)
+    {
+        if (time)
+            write_invalid_msvcrt_tm(time);
+
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+
+    seconds = *secs;
+
+    _mlock(_TIME_LOCK);
+    if (!(tm = localtime(&seconds)))
+    {
+        _munlock(_TIME_LOCK);
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+
+    unix_tm_to_msvcrt(time, tm);
+    _munlock(_TIME_LOCK);
+    return 0;
+}
+
+/*********************************************************************
  *      _localtime32 (MSVCRT.@)
  */
 struct MSVCRT_tm* CDECL MSVCRT__localtime32(const MSVCRT___time32_t* secs)
diff --git a/include/msvcrt/time.h b/include/msvcrt/time.h
index ebbfbc2..194b47c 100644
--- a/include/msvcrt/time.h
+++ b/include/msvcrt/time.h
@@ -104,6 +104,7 @@ struct tm*  __cdecl _gmtime32(const __time32_t*);
 struct tm*  __cdecl _gmtime64(const __time64_t*);
 struct tm*  __cdecl _localtime32(const __time32_t*);
 struct tm*  __cdecl _localtime64(const __time64_t*);
+errno_t     __cdecl _localtime64_s(struct tm*, const __time64_t*);
 __time32_t  __cdecl _mktime32(struct tm*);
 __time64_t  __cdecl _mktime64(struct tm*);
 size_t      __cdecl strftime(char*,size_t,const char*,const struct tm*);




More information about the wine-cvs mailing list