ucrtbase: Add _set_thread_local_invalid_parameter_handler implementation.
Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
025c543442
commit
c35d07fcd1
|
@ -433,6 +433,16 @@ void CDECL _seterrormode(int mode)
|
||||||
void __cdecl MSVCRT__invalid_parameter(const MSVCRT_wchar_t *expr, const MSVCRT_wchar_t *func,
|
void __cdecl MSVCRT__invalid_parameter(const MSVCRT_wchar_t *expr, const MSVCRT_wchar_t *func,
|
||||||
const MSVCRT_wchar_t *file, unsigned int line, MSVCRT_uintptr_t arg)
|
const MSVCRT_wchar_t *file, unsigned int line, MSVCRT_uintptr_t arg)
|
||||||
{
|
{
|
||||||
|
#if _MSVCR_VER >= 140
|
||||||
|
thread_data_t *data = msvcrt_get_thread_data();
|
||||||
|
|
||||||
|
if (data->invalid_parameter_handler)
|
||||||
|
{
|
||||||
|
data->invalid_parameter_handler( expr, func, file, line, arg );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg );
|
if (invalid_parameter_handler) invalid_parameter_handler( expr, func, file, line, arg );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -474,13 +484,14 @@ MSVCRT_invalid_parameter_handler CDECL _set_invalid_parameter_handler(
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if _MSVCR_VER >= 140
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* _get_thread_local_invalid_parameter_handler (UCRTBASE.@)
|
* _get_thread_local_invalid_parameter_handler (UCRTBASE.@)
|
||||||
*/
|
*/
|
||||||
MSVCRT_invalid_parameter_handler CDECL _get_thread_local_invalid_parameter_handler(void)
|
MSVCRT_invalid_parameter_handler CDECL _get_thread_local_invalid_parameter_handler(void)
|
||||||
{
|
{
|
||||||
FIXME(" stub\n");
|
TRACE("\n");
|
||||||
return NULL;
|
return msvcrt_get_thread_data()->invalid_parameter_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
@ -489,6 +500,12 @@ MSVCRT_invalid_parameter_handler CDECL _get_thread_local_invalid_parameter_handl
|
||||||
MSVCRT_invalid_parameter_handler CDECL _set_thread_local_invalid_parameter_handler(
|
MSVCRT_invalid_parameter_handler CDECL _set_thread_local_invalid_parameter_handler(
|
||||||
MSVCRT_invalid_parameter_handler handler)
|
MSVCRT_invalid_parameter_handler handler)
|
||||||
{
|
{
|
||||||
FIXME("(%p) stub\n", handler);
|
thread_data_t *data = msvcrt_get_thread_data();
|
||||||
return NULL;
|
MSVCRT_invalid_parameter_handler old = data->invalid_parameter_handler;
|
||||||
|
|
||||||
|
TRACE("(%p)\n", handler);
|
||||||
|
|
||||||
|
data->invalid_parameter_handler = handler;
|
||||||
|
return old;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -266,6 +266,9 @@ struct __thread_data {
|
||||||
DWORD cached_cp;
|
DWORD cached_cp;
|
||||||
char cached_locale[131];
|
char cached_locale[131];
|
||||||
void *unk10[100];
|
void *unk10[100];
|
||||||
|
#if _MSVCR_VER >= 140
|
||||||
|
MSVCRT_invalid_parameter_handler invalid_parameter_handler;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct __thread_data thread_data_t;
|
typedef struct __thread_data thread_data_t;
|
||||||
|
|
|
@ -27,6 +27,33 @@
|
||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
#include "wine/test.h"
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
#define DEFINE_EXPECT(func) \
|
||||||
|
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
|
||||||
|
|
||||||
|
#define SET_EXPECT(func) \
|
||||||
|
expect_ ## func = TRUE
|
||||||
|
|
||||||
|
#define CHECK_EXPECT2(func) \
|
||||||
|
do { \
|
||||||
|
ok(expect_ ##func, "unexpected call " #func "\n"); \
|
||||||
|
called_ ## func = TRUE; \
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
#define CHECK_EXPECT(func) \
|
||||||
|
do { \
|
||||||
|
CHECK_EXPECT2(func); \
|
||||||
|
expect_ ## func = FALSE; \
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
#define CHECK_CALLED(func) \
|
||||||
|
do { \
|
||||||
|
ok(called_ ## func, "expected " #func "\n"); \
|
||||||
|
expect_ ## func = called_ ## func = FALSE; \
|
||||||
|
}while(0)
|
||||||
|
|
||||||
|
DEFINE_EXPECT(global_invalid_parameter_handler);
|
||||||
|
DEFINE_EXPECT(thread_invalid_parameter_handler);
|
||||||
|
|
||||||
typedef int (CDECL *MSVCRT__onexit_t)(void);
|
typedef int (CDECL *MSVCRT__onexit_t)(void);
|
||||||
|
|
||||||
typedef struct MSVCRT__onexit_table_t
|
typedef struct MSVCRT__onexit_table_t
|
||||||
|
@ -41,6 +68,11 @@ static int (CDECL *p_register_onexit_function)(MSVCRT__onexit_table_t *table, MS
|
||||||
static int (CDECL *p_execute_onexit_table)(MSVCRT__onexit_table_t *table);
|
static int (CDECL *p_execute_onexit_table)(MSVCRT__onexit_table_t *table);
|
||||||
static int (CDECL *p___fpe_flt_rounds)(void);
|
static int (CDECL *p___fpe_flt_rounds)(void);
|
||||||
static unsigned int (CDECL *p__controlfp)(unsigned int, unsigned int);
|
static unsigned int (CDECL *p__controlfp)(unsigned int, unsigned int);
|
||||||
|
static _invalid_parameter_handler (CDECL *p__set_invalid_parameter_handler)(_invalid_parameter_handler);
|
||||||
|
static _invalid_parameter_handler (CDECL *p__get_invalid_parameter_handler)(void);
|
||||||
|
static _invalid_parameter_handler (CDECL *p__set_thread_local_invalid_parameter_handler)(_invalid_parameter_handler);
|
||||||
|
static _invalid_parameter_handler (CDECL *p__get_thread_local_invalid_parameter_handler)(void);
|
||||||
|
static int (CDECL *p__ltoa_s)(LONG, char*, size_t, int);
|
||||||
|
|
||||||
static void test__initialize_onexit_table(void)
|
static void test__initialize_onexit_table(void)
|
||||||
{
|
{
|
||||||
|
@ -223,6 +255,63 @@ static void test___fpe_flt_rounds(void)
|
||||||
ok(ret == 0, "__fpe_flt_rounds returned %d\n", ret);
|
ok(ret == 0, "__fpe_flt_rounds returned %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __cdecl global_invalid_parameter_handler(
|
||||||
|
const wchar_t *expression, const wchar_t *function,
|
||||||
|
const wchar_t *file, unsigned line, uintptr_t arg)
|
||||||
|
{
|
||||||
|
CHECK_EXPECT(global_invalid_parameter_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __cdecl thread_invalid_parameter_handler(
|
||||||
|
const wchar_t *expression, const wchar_t *function,
|
||||||
|
const wchar_t *file, unsigned line, uintptr_t arg)
|
||||||
|
{
|
||||||
|
CHECK_EXPECT(thread_invalid_parameter_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_invalid_parameter_handler(void)
|
||||||
|
{
|
||||||
|
_invalid_parameter_handler ret;
|
||||||
|
|
||||||
|
ret = p__get_invalid_parameter_handler();
|
||||||
|
ok(!ret, "ret != NULL\n");
|
||||||
|
|
||||||
|
ret = p__get_thread_local_invalid_parameter_handler();
|
||||||
|
ok(!ret, "ret != NULL\n");
|
||||||
|
|
||||||
|
ret = p__set_thread_local_invalid_parameter_handler(thread_invalid_parameter_handler);
|
||||||
|
ok(!ret, "ret != NULL\n");
|
||||||
|
|
||||||
|
ret = p__get_thread_local_invalid_parameter_handler();
|
||||||
|
ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
|
||||||
|
|
||||||
|
ret = p__get_invalid_parameter_handler();
|
||||||
|
ok(!ret, "ret != NULL\n");
|
||||||
|
|
||||||
|
ret = p__set_invalid_parameter_handler(global_invalid_parameter_handler);
|
||||||
|
ok(!ret, "ret != NULL\n");
|
||||||
|
|
||||||
|
ret = p__get_invalid_parameter_handler();
|
||||||
|
ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret);
|
||||||
|
|
||||||
|
ret = p__get_thread_local_invalid_parameter_handler();
|
||||||
|
ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
|
||||||
|
|
||||||
|
SET_EXPECT(thread_invalid_parameter_handler);
|
||||||
|
p__ltoa_s(0, NULL, 0, 0);
|
||||||
|
CHECK_CALLED(thread_invalid_parameter_handler);
|
||||||
|
|
||||||
|
ret = p__set_thread_local_invalid_parameter_handler(NULL);
|
||||||
|
ok(ret == thread_invalid_parameter_handler, "ret = %p\n", ret);
|
||||||
|
|
||||||
|
SET_EXPECT(global_invalid_parameter_handler);
|
||||||
|
p__ltoa_s(0, NULL, 0, 0);
|
||||||
|
CHECK_CALLED(global_invalid_parameter_handler);
|
||||||
|
|
||||||
|
ret = p__set_invalid_parameter_handler(NULL);
|
||||||
|
ok(ret == global_invalid_parameter_handler, "ret = %p\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL init(void)
|
static BOOL init(void)
|
||||||
{
|
{
|
||||||
HMODULE module = LoadLibraryA("ucrtbase.dll");
|
HMODULE module = LoadLibraryA("ucrtbase.dll");
|
||||||
|
@ -237,6 +326,11 @@ static BOOL init(void)
|
||||||
p_execute_onexit_table = (void*)GetProcAddress(module, "_execute_onexit_table");
|
p_execute_onexit_table = (void*)GetProcAddress(module, "_execute_onexit_table");
|
||||||
p___fpe_flt_rounds = (void*)GetProcAddress(module, "__fpe_flt_rounds");
|
p___fpe_flt_rounds = (void*)GetProcAddress(module, "__fpe_flt_rounds");
|
||||||
p__controlfp = (void*)GetProcAddress(module, "_controlfp");
|
p__controlfp = (void*)GetProcAddress(module, "_controlfp");
|
||||||
|
p__set_invalid_parameter_handler = (void*)GetProcAddress(module, "_set_invalid_parameter_handler");
|
||||||
|
p__get_invalid_parameter_handler = (void*)GetProcAddress(module, "_get_invalid_parameter_handler");
|
||||||
|
p__set_thread_local_invalid_parameter_handler = (void*)GetProcAddress(module, "_set_thread_local_invalid_parameter_handler");
|
||||||
|
p__get_thread_local_invalid_parameter_handler = (void*)GetProcAddress(module, "_get_thread_local_invalid_parameter_handler");
|
||||||
|
p__ltoa_s = (void*)GetProcAddress(module, "_ltoa_s");
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -246,6 +340,7 @@ START_TEST(misc)
|
||||||
if(!init())
|
if(!init())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
test_invalid_parameter_handler();
|
||||||
test__initialize_onexit_table();
|
test__initialize_onexit_table();
|
||||||
test__register_onexit_function();
|
test__register_onexit_function();
|
||||||
test__execute_onexit_table();
|
test__execute_onexit_table();
|
||||||
|
|
Loading…
Reference in New Issue