Module: wine Branch: master Commit: f3465ecbae0b7f99008c4ad63680b7315a247eec URL: http://source.winehq.org/git/wine.git/?a=commit;h=f3465ecbae0b7f99008c4ad636...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Wed Apr 27 09:21:12 2016 +0300
ucrtbase: Implement _execute_onexit_table().
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
.../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcrt/exit.c | 27 ++++++++ dlls/ucrtbase/tests/misc.c | 74 ++++++++++++++++++++++ dlls/ucrtbase/ucrtbase.spec | 2 +- 4 files changed, 103 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 ceb4e35..e138bf6 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 @@ -34,7 +34,7 @@ @ cdecl _endthread() ucrtbase._endthread @ cdecl _endthreadex(long) ucrtbase._endthreadex @ cdecl _errno() ucrtbase._errno -@ stub _execute_onexit_table +@ cdecl _execute_onexit_table(ptr) ucrtbase._execute_onexit_table @ cdecl _exit(long) ucrtbase._exit @ cdecl _fpieee_flt(long ptr ptr) ucrtbase._fpieee_flt @ cdecl _fpreset() ucrtbase._fpreset diff --git a/dlls/msvcrt/exit.c b/dlls/msvcrt/exit.c index 60aa85d..9ba0891 100644 --- a/dlls/msvcrt/exit.c +++ b/dlls/msvcrt/exit.c @@ -400,6 +400,33 @@ int CDECL MSVCRT__register_onexit_function(MSVCRT__onexit_table_t *table, MSVCRT }
/********************************************************************* + * _execute_onexit_table (UCRTBASE.@) + */ +int CDECL MSVCRT__execute_onexit_table(MSVCRT__onexit_table_t *table) +{ + MSVCRT__onexit_t *func; + + TRACE("(%p)\n", table); + + if (!table) + return -1; + + if (!table->_first || table->_first >= table->_last) + return 0; + + for (func = table->_last - 1; func >= table->_first; func--) + { + if (*func) + (*func)(); + } + + MSVCRT_free(table->_first); + memset(table, 0, sizeof(*table)); + MSVCRT__initialize_onexit_table(table); + 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 0b77066..63ea465 100644 --- a/dlls/ucrtbase/tests/misc.c +++ b/dlls/ucrtbase/tests/misc.c @@ -37,6 +37,7 @@ typedef struct 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 int (CDECL *p_execute_onexit_table)(MSVCRT__onexit_table_t *table);
static void test__initialize_onexit_table(void) { @@ -98,8 +99,17 @@ static void test__initialize_onexit_table(void) table._first, table._last, table._end); }
+static int g_onexit_called; static int CDECL onexit_func(void) { + g_onexit_called++; + return 0; +} + +static int CDECL onexit_func2(void) +{ + ok(g_onexit_called == 0, "got %d\n", g_onexit_called); + g_onexit_called++; return 0; }
@@ -139,12 +149,75 @@ static void test__register_onexit_function(void) ok(f != table._last, "got %p, initial %p\n", table._last, f); }
+static void test__execute_onexit_table(void) +{ + MSVCRT__onexit_table_t table; + int ret; + + if (!p_execute_onexit_table) + { + win_skip("_execute_onexit_table() is not available.\n"); + return; + } + + ret = p_execute_onexit_table(NULL); + ok(ret == -1, "got %d\n", ret); + + memset(&table, 0, sizeof(table)); + ret = p_initialize_onexit_table(&table); + ok(ret == 0, "got %d\n", ret); + + /* execute empty table */ + ret = p_execute_onexit_table(&table); + ok(ret == 0, "got %d\n", ret); + + /* same functions registered twice */ + ret = p_register_onexit_function(&table, onexit_func); + ok(ret == 0, "got %d\n", ret); + + ret = p_register_onexit_function(&table, NULL); + ok(ret == 0, "got %d\n", ret); + + ret = p_register_onexit_function(&table, onexit_func); + ok(ret == 0, "got %d\n", ret); + + ok(table._first != table._end, "got %p, %p\n", table._first, table._end); + g_onexit_called = 0; + ret = p_execute_onexit_table(&table); + ok(ret == 0, "got %d\n", ret); + ok(g_onexit_called == 2, "got %d\n", g_onexit_called); + ok(table._first == table._end, "got %p, %p\n", table._first, table._end); + + /* execute again, table is already empty */ + g_onexit_called = 0; + ret = p_execute_onexit_table(&table); + ok(ret == 0, "got %d\n", ret); + ok(g_onexit_called == 0, "got %d\n", g_onexit_called); + + /* check call order */ + memset(&table, 0, sizeof(table)); + ret = p_initialize_onexit_table(&table); + ok(ret == 0, "got %d\n", ret); + + ret = p_register_onexit_function(&table, onexit_func); + ok(ret == 0, "got %d\n", ret); + + ret = p_register_onexit_function(&table, onexit_func2); + ok(ret == 0, "got %d\n", ret); + + g_onexit_called = 0; + ret = p_execute_onexit_table(&table); + ok(ret == 0, "got %d\n", ret); + ok(g_onexit_called == 2, "got %d\n", g_onexit_called); +} + 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"); + p_execute_onexit_table = (void*)GetProcAddress(module, "_execute_onexit_table"); }
START_TEST(misc) @@ -153,4 +226,5 @@ START_TEST(misc)
test__initialize_onexit_table(); test__register_onexit_function(); + test__execute_onexit_table(); } diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 3ac30eb..cfb2a0a 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -279,7 +279,7 @@ @ varargs _execle(str str) @ varargs _execlp(str str) @ varargs _execlpe(str str) -@ stub _execute_onexit_table +@ cdecl _execute_onexit_table(ptr) MSVCRT__execute_onexit_table @ cdecl _execv(str ptr) @ cdecl _execve(str ptr ptr) MSVCRT__execve @ cdecl _execvp(str ptr)