[v4 PATCH 2/3] ucrtbase: Implement _register_onexit_function()

Nikolay Sivov nsivov at codeweavers.com
Tue Apr 26 06:13:40 CDT 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

v4: initialize table structure before using it
v3: allocation failures are handled now

 .../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 9c36583..ceb4e35 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 5317dd4..5fc5fc8 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 5e22601..0b77066 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 c436779..3ac30eb 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.8.0.rc3




More information about the wine-patches mailing list