-- v3: msvcp140_atomic_wait: Stub __std_tzdb_get_leap_seconds() / __std_tzdb_delete_leap_seconds(). msvcp140_atomic_wait: Semi-stub __std_tzdb_get_current_zone() / __std_tzdb_delete_current_zone(). msvcp140_atomic_wait: Semi-stub __std_tzdb_get_time_zones() / __std_tzdb_delete_time_zones().
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msvcp140_atomic_wait/main.c | 62 +++++++++++++++++++ .../msvcp140_atomic_wait.spec | 4 +- .../tests/msvcp140_atomic_wait.c | 53 ++++++++++++++++ 3 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcp140_atomic_wait/main.c b/dlls/msvcp140_atomic_wait/main.c index 9c61b158b97..089df65dc40 100644 --- a/dlls/msvcp140_atomic_wait/main.c +++ b/dlls/msvcp140_atomic_wait/main.c @@ -187,3 +187,65 @@ void __stdcall __std_free_crt(void *ptr) { free(ptr); } + +enum tzdb_error +{ + TZDB_ERROR_SUCCESS, + TZDB_ERROR_WIN, + TZDB_ERROR_ICU, +}; + +struct tzdb_time_zones +{ + enum tzdb_error error; + char *ver; + unsigned int count; + char **names; + char **links; +}; + +struct tzdb_time_zones * __stdcall __std_tzdb_get_time_zones(void) +{ + DYNAMIC_TIME_ZONE_INFORMATION tzd; + static char ver[] = "2022g"; + struct tzdb_time_zones *z; + unsigned int i, j; + + FIXME("returning Windows time zone names.\n"); + + z = calloc(1, sizeof(*z)); + while (!EnumDynamicTimeZoneInformation(z->count, &tzd)) + ++z->count; + + z->ver = ver; + z->names = calloc(z->count, sizeof(*z->names)); + z->links = calloc(z->count, sizeof(*z->links)); + + for (i = 0; i < z->count; ++i) + { + if (EnumDynamicTimeZoneInformation(i, &tzd)) + break; + z->names[i] = malloc(wcslen(tzd.StandardName) + 1); + j = 0; + while ((z->names[i][j] = tzd.StandardName[j])) + ++j; + } + z->count = i; + return z; +} + +void __stdcall __std_tzdb_delete_time_zones(struct tzdb_time_zones *z) +{ + unsigned int i; + + TRACE("(%p)\n", z); + + for (i = 0; i < z->count; ++i) + { + free(z->names[i]); + free(z->links[i]); + } + free(z->names); + free(z->links); + free(z); +} diff --git a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec index d335828d35c..9cad0f9d0fb 100644 --- a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec +++ b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec @@ -24,9 +24,9 @@ @ stub __std_tzdb_delete_current_zone @ stub __std_tzdb_delete_leap_seconds @ stub __std_tzdb_delete_sys_info -@ stub __std_tzdb_delete_time_zones +@ stdcall __std_tzdb_delete_time_zones(ptr) @ stub __std_tzdb_get_current_zone @ stub __std_tzdb_get_leap_seconds @ stub __std_tzdb_get_sys_info -@ stub __std_tzdb_get_time_zones +@ stdcall __std_tzdb_get_time_zones() @ stdcall __std_wait_for_threadpool_work_callbacks(ptr long) diff --git a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c index 1e99145ac4b..4a8ec88ad54 100644 --- a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c +++ b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c @@ -28,6 +28,22 @@ typedef struct SRWLOCK srwlock; } shared_mutex;
+enum tzdb_error +{ + TZDB_ERROR_SUCCESS, + TZDB_ERROR_WIN, + TZDB_ERROR_ICU, +}; + +struct tzdb_time_zones +{ + enum tzdb_error error; + char *ver; + unsigned int count; + char **names; + char **links; +}; + static unsigned int (__stdcall *p___std_parallel_algorithms_hw_threads)(void);
static void (__stdcall *p___std_bulk_submit_threadpool_work)(PTP_WORK, size_t); @@ -41,6 +57,8 @@ static void (__stdcall *p___std_execution_wait_on_uchar)(void *, unsigned char); static void (__stdcall *p___std_execution_wake_by_address_all)(void *); static shared_mutex* (__stdcall *p___std_acquire_shared_mutex_for_instance)(void*); static void (__stdcall *p___std_release_shared_mutex_for_instance)(void*); +static struct tzdb_time_zones * (__stdcall *p___std_tzdb_get_time_zones)(void); +static void (__stdcall *p___std_tzdb_delete_time_zones)(struct tzdb_time_zones *);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) @@ -64,6 +82,8 @@ static HMODULE init(void) SET(p___std_execution_wake_by_address_all, "__std_execution_wake_by_address_all"); SET(p___std_acquire_shared_mutex_for_instance, "__std_acquire_shared_mutex_for_instance"); SET(p___std_release_shared_mutex_for_instance, "__std_release_shared_mutex_for_instance"); + SET(p___std_tzdb_get_time_zones, "__std_tzdb_get_time_zones"); + SET(p___std_tzdb_delete_time_zones, "__std_tzdb_delete_time_zones"); return msvcp; }
@@ -325,6 +345,38 @@ static void test___std_acquire_shared_mutex_for_instance(void) p___std_release_shared_mutex_for_instance(NULL); }
+static void test___std_tzdb(void) +{ + struct tzdb_time_zones *z; + unsigned int i; + + if (!p___std_tzdb_get_time_zones) + { + win_skip("__std_tzdb_get_time_zones is not available, skipping tests.\n"); + return; + } + + z = p___std_tzdb_get_time_zones(); + ok(!!z, "got NULL.\n"); + ok(!z->error || broken(z->error == TZDB_ERROR_WIN && !z->ver && !z->count), "got %u.\n", z->error); + if (z->error) + { + win_skip("__std_tzdb_get_time_zones empty result, skipping remaining tests.\n"); + p___std_tzdb_delete_time_zones(z); + return; + } + ok(!!z->ver, "got NULL.\n"); + ok(z->count, "got 0.\n"); + + trace("ver %s.\n", debugstr_a(z->ver)); + for (i = 0; i < z->count; ++i) + { + ok(!!z->names[i], "got NULL.\n"); + } + + p___std_tzdb_delete_time_zones(z); +} + START_TEST(msvcp140_atomic_wait) { HMODULE msvcp; @@ -338,5 +390,6 @@ START_TEST(msvcp140_atomic_wait) test___std_atomic_wait_direct(); test___std_execution(); test___std_acquire_shared_mutex_for_instance(); + test___std_tzdb(); FreeLibrary(msvcp); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msvcp140_atomic_wait/main.c | 37 +++++++++++++++++++ .../msvcp140_atomic_wait.spec | 4 +- .../tests/msvcp140_atomic_wait.c | 20 +++++++++- 3 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/dlls/msvcp140_atomic_wait/main.c b/dlls/msvcp140_atomic_wait/main.c index 089df65dc40..8d9136fbc7b 100644 --- a/dlls/msvcp140_atomic_wait/main.c +++ b/dlls/msvcp140_atomic_wait/main.c @@ -204,6 +204,12 @@ struct tzdb_time_zones char **links; };
+struct tzdb_current_zone +{ + enum tzdb_error error; + char *name; +}; + struct tzdb_time_zones * __stdcall __std_tzdb_get_time_zones(void) { DYNAMIC_TIME_ZONE_INFORMATION tzd; @@ -249,3 +255,34 @@ void __stdcall __std_tzdb_delete_time_zones(struct tzdb_time_zones *z) free(z->links); free(z); } + +struct tzdb_current_zone * __stdcall __std_tzdb_get_current_zone(void) +{ + DYNAMIC_TIME_ZONE_INFORMATION tzd; + struct tzdb_current_zone *c; + unsigned int i; + + FIXME("returning Windows time zone name.\n"); + + c = calloc(1, sizeof(*c)); + + if (GetDynamicTimeZoneInformation(&tzd) == TIME_ZONE_ID_INVALID) + { + c->error = TZDB_ERROR_WIN; + return c; + } + + c->name = malloc(wcslen(tzd.StandardName) + 1); + i = 0; + while ((c->name[i] = tzd.StandardName[i])) + ++i; + return c; +} + +void __stdcall __std_tzdb_delete_current_zone(struct tzdb_current_zone *c) +{ + TRACE("(%p)\n", c); + + free(c->name); + free(c); +} diff --git a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec index 9cad0f9d0fb..164e562baa8 100644 --- a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec +++ b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec @@ -21,11 +21,11 @@ @ stdcall __std_parallel_algorithms_hw_threads() @ stdcall __std_release_shared_mutex_for_instance(ptr) @ stdcall __std_submit_threadpool_work(ptr) -@ stub __std_tzdb_delete_current_zone +@ stdcall __std_tzdb_delete_current_zone(ptr) @ stub __std_tzdb_delete_leap_seconds @ stub __std_tzdb_delete_sys_info @ stdcall __std_tzdb_delete_time_zones(ptr) -@ stub __std_tzdb_get_current_zone +@ stdcall __std_tzdb_get_current_zone() @ stub __std_tzdb_get_leap_seconds @ stub __std_tzdb_get_sys_info @ stdcall __std_tzdb_get_time_zones() diff --git a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c index 4a8ec88ad54..2c7cd8664a7 100644 --- a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c +++ b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c @@ -44,6 +44,12 @@ struct tzdb_time_zones char **links; };
+struct tzdb_current_zone +{ + enum tzdb_error error; + char *name; +}; + static unsigned int (__stdcall *p___std_parallel_algorithms_hw_threads)(void);
static void (__stdcall *p___std_bulk_submit_threadpool_work)(PTP_WORK, size_t); @@ -59,6 +65,8 @@ static shared_mutex* (__stdcall *p___std_acquire_shared_mutex_for_instance)(void static void (__stdcall *p___std_release_shared_mutex_for_instance)(void*); static struct tzdb_time_zones * (__stdcall *p___std_tzdb_get_time_zones)(void); static void (__stdcall *p___std_tzdb_delete_time_zones)(struct tzdb_time_zones *); +static struct tzdb_current_zone * (__stdcall *p___std_tzdb_get_current_zone)(void); +static void (__stdcall *p___std_tzdb_delete_current_zone)(struct tzdb_current_zone *);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) @@ -84,6 +92,8 @@ static HMODULE init(void) SET(p___std_release_shared_mutex_for_instance, "__std_release_shared_mutex_for_instance"); SET(p___std_tzdb_get_time_zones, "__std_tzdb_get_time_zones"); SET(p___std_tzdb_delete_time_zones, "__std_tzdb_delete_time_zones"); + SET(p___std_tzdb_get_current_zone, "__std_tzdb_get_current_zone"); + SET(p___std_tzdb_delete_current_zone, "__std_tzdb_delete_current_zone"); return msvcp; }
@@ -347,6 +357,7 @@ static void test___std_acquire_shared_mutex_for_instance(void)
static void test___std_tzdb(void) { + struct tzdb_current_zone *c; struct tzdb_time_zones *z; unsigned int i;
@@ -369,11 +380,18 @@ static void test___std_tzdb(void) ok(z->count, "got 0.\n");
trace("ver %s.\n", debugstr_a(z->ver)); + c = p___std_tzdb_get_current_zone(); + ok(!!c, "got NULL.\n"); + ok(!!c->name, "got NULL.\n"); + ok(!c->error, "got %u.\n", c->error); for (i = 0; i < z->count; ++i) { - ok(!!z->names[i], "got NULL.\n"); + if (!strcmp(c->name, z->names[i])) + break; } + ok(i < z->count, "current zone %s not found.\n", c->name);
+ p___std_tzdb_delete_current_zone(c); p___std_tzdb_delete_time_zones(z); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/msvcp140_atomic_wait/main.c | 26 +++++++++++++++++++ .../msvcp140_atomic_wait.spec | 4 +-- .../tests/msvcp140_atomic_wait.c | 23 ++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-)
diff --git a/dlls/msvcp140_atomic_wait/main.c b/dlls/msvcp140_atomic_wait/main.c index 8d9136fbc7b..035d470920f 100644 --- a/dlls/msvcp140_atomic_wait/main.c +++ b/dlls/msvcp140_atomic_wait/main.c @@ -17,6 +17,7 @@ */
#include <stdarg.h> +#include "stdint.h" #include "windef.h" #include "winbase.h" #include "wine/debug.h" @@ -210,6 +211,16 @@ struct tzdb_current_zone char *name; };
+struct tzdb_leap_second +{ + uint16_t year; + uint16_t month; + uint16_t day; + uint16_t hour; + uint16_t negative; + uint16_t reserved; +}; + struct tzdb_time_zones * __stdcall __std_tzdb_get_time_zones(void) { DYNAMIC_TIME_ZONE_INFORMATION tzd; @@ -286,3 +297,18 @@ void __stdcall __std_tzdb_delete_current_zone(struct tzdb_current_zone *c) free(c->name); free(c); } + +struct tzdb_leap_second * __stdcall __std_tzdb_get_leap_seconds(size_t prev_size, size_t *new_size) +{ + FIXME("(%#Ix %p) stub\n", prev_size, new_size); + + *new_size = 0; + return NULL; +} + +void __stdcall __std_tzdb_delete_leap_seconds(struct tzdb_leap_second *l) +{ + TRACE("(%p)\n", l); + + free(l); +} diff --git a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec index 164e562baa8..5d23b217b72 100644 --- a/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec +++ b/dlls/msvcp140_atomic_wait/msvcp140_atomic_wait.spec @@ -22,11 +22,11 @@ @ stdcall __std_release_shared_mutex_for_instance(ptr) @ stdcall __std_submit_threadpool_work(ptr) @ stdcall __std_tzdb_delete_current_zone(ptr) -@ stub __std_tzdb_delete_leap_seconds +@ stdcall __std_tzdb_delete_leap_seconds(ptr) @ stub __std_tzdb_delete_sys_info @ stdcall __std_tzdb_delete_time_zones(ptr) @ stdcall __std_tzdb_get_current_zone() -@ stub __std_tzdb_get_leap_seconds +@ stdcall __std_tzdb_get_leap_seconds(ptr ptr) @ stub __std_tzdb_get_sys_info @ stdcall __std_tzdb_get_time_zones() @ stdcall __std_wait_for_threadpool_work_callbacks(ptr long) diff --git a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c index 2c7cd8664a7..f0e007df699 100644 --- a/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c +++ b/dlls/msvcp140_atomic_wait/tests/msvcp140_atomic_wait.c @@ -19,6 +19,7 @@ #include <stdio.h> #include <process.h>
+#include "stdint.h" #include "windef.h" #include "winbase.h" #include "wine/test.h" @@ -50,6 +51,16 @@ struct tzdb_current_zone char *name; };
+struct tzdb_leap_second +{ + uint16_t year; + uint16_t month; + uint16_t day; + uint16_t hour; + uint16_t negative; + uint16_t reserved; +}; + static unsigned int (__stdcall *p___std_parallel_algorithms_hw_threads)(void);
static void (__stdcall *p___std_bulk_submit_threadpool_work)(PTP_WORK, size_t); @@ -67,6 +78,8 @@ static struct tzdb_time_zones * (__stdcall *p___std_tzdb_get_time_zones)(void); static void (__stdcall *p___std_tzdb_delete_time_zones)(struct tzdb_time_zones *); static struct tzdb_current_zone * (__stdcall *p___std_tzdb_get_current_zone)(void); static void (__stdcall *p___std_tzdb_delete_current_zone)(struct tzdb_current_zone *); +static struct tzdb_leap_second * (__stdcall *p___std_tzdb_get_leap_seconds)(size_t, size_t *); +static void (__stdcall *p___std_tzdb_delete_leap_seconds)(struct tzdb_leap_second *);
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y) #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0) @@ -94,6 +107,8 @@ static HMODULE init(void) SET(p___std_tzdb_delete_time_zones, "__std_tzdb_delete_time_zones"); SET(p___std_tzdb_get_current_zone, "__std_tzdb_get_current_zone"); SET(p___std_tzdb_delete_current_zone, "__std_tzdb_delete_current_zone"); + SET(p___std_tzdb_get_leap_seconds, "__std_tzdb_get_leap_seconds"); + SET(p___std_tzdb_delete_leap_seconds, "__std_tzdb_delete_leap_seconds"); return msvcp; }
@@ -359,7 +374,9 @@ static void test___std_tzdb(void) { struct tzdb_current_zone *c; struct tzdb_time_zones *z; + void *leap_seconds; unsigned int i; + size_t size;
if (!p___std_tzdb_get_time_zones) { @@ -393,6 +410,12 @@ static void test___std_tzdb(void)
p___std_tzdb_delete_current_zone(c); p___std_tzdb_delete_time_zones(z); + + size = 0xdeadbeef; + leap_seconds = p___std_tzdb_get_leap_seconds(100, &size); + ok(!leap_seconds, "got %p.\n", leap_seconds); + ok(!size, "got %#Ix.\n", size); + p___std_tzdb_delete_leap_seconds(leap_seconds); }
START_TEST(msvcp140_atomic_wait)
v3: - don't leak names and links in __std_tzdb_delete_time_zones(); - remove check for 'ver' write access.
This merge request was approved by Piotr Caban.