From 5f490de4592eccc08681fa8131670ca6826a5dbb Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 26 Apr 2016 14:13:40 +0300 Subject: [PATCH] ucrtbase: Implement _register_onexit_function(). Signed-off-by: Nikolay Sivov Signed-off-by: Piotr Caban Signed-off-by: Alexandre Julliard --- .../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcrt/exit.c | 42 +++++++++++++++++++++ dlls/ucrtbase/tests/misc.c | 44 ++++++++++++++++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 9c365833de2..ceb4e358c71 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -60,7 +60,7 @@ @ stub _invalid_parameter_noinfo_noreturn @ stub _invoke_watson @ stub _query_app_type -@ stub _register_onexit_function +@ cdecl _register_onexit_function(ptr ptr) ucrtbase._register_onexit_function @ stub _register_thread_local_exe_atexit_callback @ cdecl _resetstkoflw() ucrtbase._resetstkoflw @ cdecl -arch=i386,x86_64,arm _seh_filter_dll(long ptr) ucrtbase._seh_filter_dll diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c index 0cddd3fc91d..60aa85d4d8a 100644 --- a/dlls/msvcrt/exit.c +++ b/dlls/msvcrt/exit.c @@ -358,6 +358,48 @@ int CDECL MSVCRT__initialize_onexit_table(MSVCRT__onexit_table_t *table) } /********************************************************************* + * _register_onexit_function (UCRTBASE.@) + */ +int CDECL MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT__onexit_t func) +{ + TRACE("(%p %p)\n", table, func); + + if (!table) + return -1; + + if (!table->_first) + { + table->_first = MSVCRT_calloc(32, sizeof(void *)); + if (!table->_first) + { + WARN("failed to allocate initial table.\n"); + return -1; + } + table->_last = table->_first; + table->_end = table->_first + 32; + } + + /* grow if full */ + if (table->_last == table->_end) + { + int len = table->_end - table->_first; + MSVCRT__onexit_t *tmp = MSVCRT_realloc(table->_first, 2 * len * sizeof(void *)); + if (!tmp) + { + WARN("failed to grow table.\n"); + return -1; + } + table->_first = tmp; + table->_end = table->_first + 2 * len; + table->_last = table->_first + len; + } + + *table->_last = func; + table->_last++; + return 0; +} + +/********************************************************************* * _set_purecall_handler (MSVCR71.@) */ MSVCRT_purecall_handler CDECL _set_purecall_handler(MSVCRT_purecall_handler function) diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c index 5e22601570e..0b77066ad0c 100644 --- a/dlls/ucrtbase/tests/misc.c +++ b/dlls/ucrtbase/tests/misc.c @@ -36,6 +36,7 @@ typedef struct MSVCRT__onexit_table_t } MSVCRT__onexit_table_t; static int (CDECL *p_initialize_onexit_table)(MSVCRT__onexit_table_t *table); +static int (CDECL *p_register_onexit_function)(MSVCRT__onexit_table_t *table, MSVCRT__onexit_t func); static void test__initialize_onexit_table(void) { @@ -97,11 +98,53 @@ static void test__initialize_onexit_table(void) table._first, table._last, table._end); } +static int CDECL onexit_func(void) +{ + return 0; +} + +static void test__register_onexit_function(void) +{ + MSVCRT__onexit_table_t table; + MSVCRT__onexit_t *f; + int ret; + + if (!p_register_onexit_function) + { + win_skip("_register_onexit_function() is not available.\n"); + return; + } + + memset(&table, 0, sizeof(table)); + ret = p_initialize_onexit_table(&table); + ok(ret == 0, "got %d\n", ret); + + ret = p_register_onexit_function(NULL, NULL); + ok(ret == -1, "got %d\n", ret); + + ret = p_register_onexit_function(NULL, onexit_func); + ok(ret == -1, "got %d\n", ret); + + f = table._last; + ret = p_register_onexit_function(&table, NULL); + ok(ret == 0, "got %d\n", ret); + ok(f != table._last, "got %p, initial %p\n", table._last, f); + + ret = p_register_onexit_function(&table, onexit_func); + ok(ret == 0, "got %d\n", ret); + + f = table._last; + ret = p_register_onexit_function(&table, onexit_func); + ok(ret == 0, "got %d\n", ret); + ok(f != table._last, "got %p, initial %p\n", table._last, f); +} + static void init(void) { HMODULE module = LoadLibraryA("ucrtbase.dll"); p_initialize_onexit_table = (void*)GetProcAddress(module, "_initialize_onexit_table"); + p_register_onexit_function = (void*)GetProcAddress(module, "_register_onexit_function"); } START_TEST(misc) @@ -109,4 +152,5 @@ START_TEST(misc) init(); test__initialize_onexit_table(); + test__register_onexit_function(); } diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index c436779e1e6..3ac30eb99b8 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -1861,7 +1861,7 @@ @ cdecl _read(long ptr long) MSVCRT__read @ stub _realloc_base @ cdecl _recalloc(ptr long long) -@ stub _register_onexit_function +@ cdecl _register_onexit_function(ptr ptr) MSVCRT__register_onexit_function @ stub _register_thread_local_exe_atexit_callback @ cdecl _resetstkoflw() MSVCRT__resetstkoflw @ cdecl _rmdir(str) MSVCRT__rmdir -- 2.11.4.GIT