diff --git a/configure b/configure index 062287ee966..d560f439e6a 100755 --- a/configure +++ b/configure @@ -17246,6 +17246,7 @@ wine_fn_config_dll msvcp100 enable_msvcp100 wine_fn_config_test dlls/msvcp100/tests msvcp100_test wine_fn_config_dll msvcp110 enable_msvcp110 wine_fn_config_dll msvcp120 enable_msvcp120 +wine_fn_config_test dlls/msvcp120/tests msvcp120_test wine_fn_config_dll msvcp120_app enable_msvcp120_app wine_fn_config_dll msvcp60 enable_msvcp60 wine_fn_config_test dlls/msvcp60/tests msvcp60_test diff --git a/configure.ac b/configure.ac index 50efb9feb16..8263c66a125 100644 --- a/configure.ac +++ b/configure.ac @@ -3070,6 +3070,7 @@ WINE_CONFIG_DLL(msvcp100) WINE_CONFIG_TEST(dlls/msvcp100/tests) WINE_CONFIG_DLL(msvcp110) WINE_CONFIG_DLL(msvcp120) +WINE_CONFIG_TEST(dlls/msvcp120/tests) WINE_CONFIG_DLL(msvcp120_app) WINE_CONFIG_DLL(msvcp60) WINE_CONFIG_TEST(dlls/msvcp60/tests) diff --git a/dlls/msvcp120/msvcp120.spec b/dlls/msvcp120/msvcp120.spec index 422f0b6cfd9..653b742b3cb 100644 --- a/dlls/msvcp120/msvcp120.spec +++ b/dlls/msvcp120/msvcp120.spec @@ -3838,9 +3838,9 @@ @ stub _Xp_setw @ stub _Xp_sqrtx @ stub _Xp_subx -@ stub _Xtime_diff_to_millis -@ stub _Xtime_diff_to_millis2 -@ cdecl _Xtime_get_ticks() +@ cdecl _Xtime_diff_to_millis(ptr) +@ cdecl _Xtime_diff_to_millis2(ptr ptr) +@ cdecl -ret64 _Xtime_get_ticks() # extern _Zero @ stub __Wcrtomb_lk -@ stub xtime_get +@ cdecl xtime_get(ptr long) diff --git a/dlls/msvcp120/tests/Makefile.in b/dlls/msvcp120/tests/Makefile.in new file mode 100644 index 00000000000..fc0869951ac --- /dev/null +++ b/dlls/msvcp120/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = msvcp120.dll +APPMODE = -mno-cygwin + +C_SRCS = \ + msvcp120.c diff --git a/dlls/msvcp120/tests/msvcp120.c b/dlls/msvcp120/tests/msvcp120.c new file mode 100644 index 00000000000..1b1dbf0d04a --- /dev/null +++ b/dlls/msvcp120/tests/msvcp120.c @@ -0,0 +1,139 @@ +/* + * Copyright 2014 Yifu Wang for ESRI + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/test.h" +#include "winbase.h" + +typedef int MSVCRT_long; + +/* xtime */ +typedef struct { + __time64_t sec; + MSVCRT_long nsec; +} xtime; + +static MSVCRT_long (__cdecl *p__Xtime_diff_to_millis2)(const xtime*, const xtime*); +static int (__cdecl *p_xtime_get)(xtime*, int); + +static HMODULE msvcp; + +static BOOL init(void) +{ + msvcp = LoadLibraryA("msvcp120.dll"); + if(!msvcp) + { + win_skip("msvcp120.dll not installed\n"); + return FALSE; + } + + p__Xtime_diff_to_millis2 = (void*)GetProcAddress(msvcp, "_Xtime_diff_to_millis2"); + p_xtime_get = (void*)GetProcAddress(msvcp, "xtime_get"); + + return TRUE; +} + +static void test__Xtime_diff_to_millis2(void) +{ + struct { + __time64_t sec_before; + MSVCRT_long nsec_before; + __time64_t sec_after; + MSVCRT_long nsec_after; + MSVCRT_long expect; + } tests[] = { + {1, 0, 2, 0, 1000}, + {0, 1000000000, 0, 2000000000, 1000}, + {1, 100000000, 2, 100000000, 1000}, + {1, 100000000, 1, 200000000, 100}, + {0, 0, 0, 1000000000, 1000}, + {0, 0, 0, 1200000000, 1200}, + {0, 0, 0, 1230000000, 1230}, + {0, 0, 0, 1234000000, 1234}, + {0, 0, 0, 1234100000, 1235}, + {0, 0, 0, 1234900000, 1235}, + {0, 0, 0, 1234010000, 1235}, + {0, 0, 0, 1234090000, 1235}, + {0, 0, 0, 1234000001, 1235}, + {0, 0, 0, 1234000009, 1235}, + {0, 0, -1, 0, 0}, + {0, 0, 0, -10000000, 0}, + {0, 0, -1, -100000000, 0}, + {-1, 0, 0, 0, 1000}, + {0, -100000000, 0, 0, 100}, + {-1, -100000000, 0, 0, 1100}, + {0, 0, -1, 2000000000, 1000}, + {0, 0, -2, 2000000000, 0}, + {0, 0, -2, 2100000000, 100} + }; + int i; + MSVCRT_long ret; + xtime t1, t2; + + for(i = 0; i < sizeof(tests) / sizeof(tests[0]); ++ i) + { + t1.sec = tests[i].sec_before; + t1.nsec = tests[i].nsec_before; + t2.sec = tests[i].sec_after; + t2.nsec = tests[i].nsec_after; + ret = p__Xtime_diff_to_millis2(&t2, &t1); + ok(ret == tests[i].expect, + "_Xtime_diff_to_millis2(): test: %d expect: %d, got: %d\n", + i, tests[i].expect, ret); + } +} + +static void test_xtime_get(void) +{ + static const MSVCRT_long tests[] = {1, 50, 100, 200, 500}; + MSVCRT_long diff; + xtime before, after; + int i; + + for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i ++) + { + p_xtime_get(&before, 1); + Sleep(tests[i]); + p_xtime_get(&after, 1); + + diff = p__Xtime_diff_to_millis2(&after, &before); + + ok(diff >= tests[i], + "xtime_get() not functioning correctly, test: %d, expect: ge %d, got: %d\n", + i, tests[i], diff); + } + + /* Test parameter and return value */ + before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef; + i = p_xtime_get(&before, 0); + ok(i == 0, "expect xtime_get() to return 0, got: %d\n", i); + ok(before.sec == 0xdeadbeef && before.nsec == 0xdeadbeef, + "xtime_get() shouldn't have modified the xtime struct with the given option\n"); + + before.sec = 0xdeadbeef, before.nsec = 0xdeadbeef; + i = p_xtime_get(&before, 1); + ok(i == 1, "expect xtime_get() to return 1, got: %d\n", i); + ok(before.sec != 0xdeadbeef && before.nsec != 0xdeadbeef, + "xtime_get() should have modified the xtime struct with the given option\n"); +} + +START_TEST(msvcp120) +{ + if(!init()) return; + test__Xtime_diff_to_millis2(); + test_xtime_get(); +} diff --git a/dlls/msvcp120_app/msvcp120_app.spec b/dlls/msvcp120_app/msvcp120_app.spec index 6bc0374b345..390d470eba6 100644 --- a/dlls/msvcp120_app/msvcp120_app.spec +++ b/dlls/msvcp120_app/msvcp120_app.spec @@ -3838,9 +3838,9 @@ @ stub _Xp_setw @ stub _Xp_sqrtx @ stub _Xp_subx -@ stub _Xtime_diff_to_millis -@ stub _Xtime_diff_to_millis2 -@ cdecl _Xtime_get_ticks() msvcp120._Xtime_get_ticks +@ cdecl _Xtime_diff_to_millis(ptr) msvcp120._Xtime_diff_to_millis +@ cdecl _Xtime_diff_to_millis2(ptr ptr) msvcp120._Xtime_diff_to_millis2 +@ cdecl -ret64 _Xtime_get_ticks() msvcp120._Xtime_get_ticks # extern _Zero @ stub __Wcrtomb_lk -@ stub xtime_get +@ cdecl xtime_get(ptr long) msvcp120.xtime_get diff --git a/dlls/msvcp90/misc.c b/dlls/msvcp90/misc.c index 61e43c30d43..a030b01a76d 100644 --- a/dlls/msvcp90/misc.c +++ b/dlls/msvcp90/misc.c @@ -33,6 +33,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcp); #define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY) #define TICKSPERSEC 10000000 #define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) +#define NANOSEC_PER_MILLISEC 1000000 +#define MILLISEC_PER_SEC 1000 struct __Container_proxy; @@ -350,6 +352,15 @@ void __thiscall _Container_base12__Swap_all( that->proxy->cont = that; } +#if _MSVCP_VER >= 110 +typedef int MSVCRT_long; + +/* xtime */ +typedef struct { + __time64_t sec; + MSVCRT_long nsec; +} xtime; + /* _Xtime_get_ticks */ LONGLONG __cdecl _Xtime_get_ticks(void) { @@ -361,6 +372,49 @@ LONGLONG __cdecl _Xtime_get_ticks(void) return ((LONGLONG)ft.dwHighDateTime<<32) + ft.dwLowDateTime - TICKS_1601_TO_1970; } +/* _xtime_get */ +int __cdecl xtime_get(xtime* t, int unknown) +{ + LONGLONG ticks; + + TRACE("(%p)\n", t); + + if(unknown != 1) + return 0; + + ticks = _Xtime_get_ticks(); + t->sec = ticks / TICKSPERSEC; + t->nsec = ticks % TICKSPERSEC * 100; + return 1; +} + +/* _Xtime_diff_to_millis2 */ +MSVCRT_long __cdecl _Xtime_diff_to_millis2(xtime *t1, xtime *t2) +{ + __time64_t diff_sec; + MSVCRT_long diff_nsec, ret; + + TRACE("(%p, %p)\n", t1, t2); + + diff_sec = t1->sec - t2->sec; + diff_nsec = t1->nsec - t2->nsec; + ret = diff_sec * MILLISEC_PER_SEC + + (diff_nsec + NANOSEC_PER_MILLISEC - 1) / NANOSEC_PER_MILLISEC; + return ret > 0 ? ret : 0; +} + +/* _Xtime_diff_to_millis */ +MSVCRT_long __cdecl _Xtime_diff_to_millis(xtime *t) +{ + xtime now; + + TRACE("%p\n", t); + + xtime_get(&now, 1); + return _Xtime_diff_to_millis2(t, &now); +} +#endif + #if _MSVCP_VER >= 90 unsigned int __cdecl _Random_device(void) {