2016-04-11 23:19:00 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Daniel Lehman (Esri)
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <wchar.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <windef.h>
|
|
|
|
#include <winbase.h>
|
|
|
|
#include "wine/test.h"
|
|
|
|
|
|
|
|
typedef unsigned char MSVCRT_bool;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
const char *what;
|
|
|
|
MSVCRT_bool dofree;
|
|
|
|
} __std_exception_data;
|
|
|
|
|
2016-08-04 16:29:06 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
char mangled[32];
|
|
|
|
} type_info140;
|
|
|
|
|
|
|
|
typedef struct _type_info_list
|
|
|
|
{
|
|
|
|
SLIST_ENTRY entry;
|
|
|
|
char name[1];
|
|
|
|
} type_info_list;
|
|
|
|
|
|
|
|
static void* (CDECL *p_malloc)(size_t);
|
2016-04-11 23:19:00 +02:00
|
|
|
static void (CDECL *p___std_exception_copy)(const __std_exception_data*, __std_exception_data*);
|
|
|
|
static void (CDECL *p___std_exception_destroy)(__std_exception_data*);
|
2016-08-04 16:29:06 +02:00
|
|
|
static int (CDECL *p___std_type_info_compare)(const type_info140*, const type_info140*);
|
|
|
|
static const char* (CDECL *p___std_type_info_name)(type_info140*, SLIST_HEADER*);
|
|
|
|
static void (CDECL *p___std_type_info_destroy_list)(SLIST_HEADER*);
|
2016-09-14 15:34:02 +02:00
|
|
|
static size_t (CDECL *p___std_type_info_hash)(type_info140*);
|
2022-02-07 17:44:46 +01:00
|
|
|
static char* (__cdecl *p___unDName)(char*,const char*,int,void*,void*,unsigned short int);
|
2016-04-11 23:19:00 +02:00
|
|
|
|
|
|
|
static BOOL init(void)
|
|
|
|
{
|
|
|
|
HMODULE module;
|
|
|
|
|
|
|
|
module = LoadLibraryA("ucrtbase.dll");
|
|
|
|
if (!module)
|
|
|
|
{
|
|
|
|
win_skip("ucrtbase.dll not installed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-08-04 16:29:06 +02:00
|
|
|
p_malloc = (void*)GetProcAddress(module, "malloc");
|
2016-04-11 23:19:00 +02:00
|
|
|
p___std_exception_copy = (void*)GetProcAddress(module, "__std_exception_copy");
|
|
|
|
p___std_exception_destroy = (void*)GetProcAddress(module, "__std_exception_destroy");
|
2016-08-04 16:29:06 +02:00
|
|
|
p___std_type_info_compare = (void*)GetProcAddress(module, "__std_type_info_compare");
|
|
|
|
p___std_type_info_name = (void*)GetProcAddress(module, "__std_type_info_name");
|
|
|
|
p___std_type_info_destroy_list = (void*)GetProcAddress(module, "__std_type_info_destroy_list");
|
2016-09-14 15:34:02 +02:00
|
|
|
p___std_type_info_hash = (void*)GetProcAddress(module, "__std_type_info_hash");
|
2022-02-07 17:44:46 +01:00
|
|
|
p___unDName = (void*)GetProcAddress(module, "__unDName");
|
2016-04-11 23:19:00 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test___std_exception(void)
|
|
|
|
{
|
|
|
|
__std_exception_data src;
|
|
|
|
__std_exception_data dst;
|
|
|
|
|
|
|
|
if (0) /* crash on Windows */
|
|
|
|
{
|
|
|
|
p___std_exception_copy(NULL, &src);
|
|
|
|
p___std_exception_copy(&dst, NULL);
|
|
|
|
|
|
|
|
src.what = "invalid free";
|
|
|
|
src.dofree = 1;
|
|
|
|
p___std_exception_destroy(&src);
|
|
|
|
p___std_exception_destroy(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
src.what = "what";
|
|
|
|
src.dofree = 0;
|
|
|
|
p___std_exception_copy(&src, &dst);
|
|
|
|
ok(dst.what == src.what, "expected what to be same, got src %p dst %p\n", src.what, dst.what);
|
|
|
|
ok(!dst.dofree, "expected 0, got %d\n", dst.dofree);
|
|
|
|
|
|
|
|
src.dofree = 0x42;
|
|
|
|
p___std_exception_copy(&src, &dst);
|
|
|
|
ok(dst.what != src.what, "expected what to be different, got src %p dst %p\n", src.what, dst.what);
|
|
|
|
ok(dst.dofree == 1, "expected 1, got %d\n", dst.dofree);
|
|
|
|
|
|
|
|
p___std_exception_destroy(&dst);
|
|
|
|
ok(!dst.what, "expected NULL, got %p\n", dst.what);
|
|
|
|
ok(!dst.dofree, "expected 0, got %d\n", dst.dofree);
|
|
|
|
|
|
|
|
src.what = NULL;
|
|
|
|
src.dofree = 0;
|
|
|
|
p___std_exception_copy(&src, &dst);
|
|
|
|
ok(!dst.what, "dst.what != NULL\n");
|
|
|
|
ok(!dst.dofree, "dst.dofree != FALSE\n");
|
|
|
|
|
|
|
|
src.what = NULL;
|
|
|
|
src.dofree = 1;
|
|
|
|
p___std_exception_copy(&src, &dst);
|
|
|
|
ok(!dst.what, "dst.what != NULL\n");
|
|
|
|
ok(!dst.dofree, "dst.dofree != FALSE\n");
|
|
|
|
}
|
|
|
|
|
2016-08-04 16:29:06 +02:00
|
|
|
static void test___std_type_info(void)
|
|
|
|
{
|
|
|
|
type_info140 ti1 = { NULL, ".?AVa@@" };
|
|
|
|
type_info140 ti2 = { NULL, ".?AVb@@" };
|
|
|
|
type_info140 ti3 = ti1;
|
|
|
|
SLIST_HEADER header;
|
|
|
|
type_info_list *elem;
|
|
|
|
const char *ret;
|
2016-09-14 15:34:02 +02:00
|
|
|
size_t hash1, hash2;
|
2016-08-04 16:29:06 +02:00
|
|
|
int eq;
|
|
|
|
|
|
|
|
|
|
|
|
InitializeSListHead(&header);
|
|
|
|
p___std_type_info_destroy_list(&header);
|
|
|
|
|
|
|
|
elem = p_malloc(sizeof(*elem));
|
|
|
|
memset(elem, 0, sizeof(*elem));
|
|
|
|
InterlockedPushEntrySList(&header, &elem->entry);
|
|
|
|
p___std_type_info_destroy_list(&header);
|
|
|
|
ok(!InterlockedPopEntrySList(&header), "list is not empty\n");
|
|
|
|
|
|
|
|
ret = p___std_type_info_name(&ti1, &header);
|
|
|
|
ok(!strcmp(ret, "class a"), "__std_type_info_name(&ti1) = %s\n", ret);
|
|
|
|
ok(ti1.name == ret, "ti1.name = %p, ret = %p\n", ti1.name, ret);
|
|
|
|
|
|
|
|
p___std_type_info_destroy_list(&header);
|
|
|
|
ok(!InterlockedPopEntrySList(&header), "list is not empty\n");
|
|
|
|
ok(ti1.name == ret, "ti1.name = %p, ret = %p\n", ti1.name, ret);
|
|
|
|
ti1.name = NULL;
|
|
|
|
|
|
|
|
eq = p___std_type_info_compare(&ti1, &ti1);
|
|
|
|
ok(eq == 0, "__std_type_info_compare(&ti1, &ti1) = %d\n", eq);
|
|
|
|
|
|
|
|
eq = p___std_type_info_compare(&ti1, &ti2);
|
|
|
|
ok(eq == -1, "__std_type_info_compare(&ti1, &ti2) = %d\n", eq);
|
|
|
|
|
|
|
|
eq = p___std_type_info_compare(&ti1, &ti3);
|
|
|
|
ok(eq == 0, "__std_type_info_compare(&ti1, &ti3) = %d\n", eq);
|
2016-09-14 15:34:02 +02:00
|
|
|
|
|
|
|
ti1.mangled[0] = 0;
|
|
|
|
ti1.mangled[1] = 0;
|
|
|
|
ti1.mangled[2] = 0;
|
|
|
|
hash1 = p___std_type_info_hash(&ti1);
|
|
|
|
#ifdef _WIN64
|
2016-10-05 20:51:52 +02:00
|
|
|
ok(hash1 == 0xcbf29ce44fd0bfc1, "hash = %p\n", (void*)hash1);
|
2016-09-14 15:34:02 +02:00
|
|
|
#else
|
|
|
|
ok(hash1 == 0x811c9dc5, "hash = %p\n", (void*)hash1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ti1.mangled[0] = 1;
|
|
|
|
hash2 = p___std_type_info_hash(&ti1);
|
2016-10-05 20:51:52 +02:00
|
|
|
ok(hash1 == hash2, "hash1 != hash2 (first char not ignored)\n");
|
2016-09-14 15:34:02 +02:00
|
|
|
|
|
|
|
ti1.mangled[1] = 1;
|
|
|
|
hash1 = p___std_type_info_hash(&ti1);
|
2016-10-05 20:51:52 +02:00
|
|
|
#ifdef _WIN64
|
|
|
|
ok(hash1 == 0xaf63bc4c29620a60, "hash = %p\n", (void*)hash1);
|
|
|
|
#else
|
|
|
|
ok(hash1 == 0x40c5b8c, "hash = %p\n", (void*)hash1);
|
|
|
|
#endif
|
2016-09-14 15:34:02 +02:00
|
|
|
ok(hash1 != hash2, "hash1 == hash2 for different strings\n");
|
|
|
|
|
|
|
|
ti1.mangled[1] = 2;
|
|
|
|
hash2 = p___std_type_info_hash(&ti1);
|
|
|
|
ok(hash1 != hash2, "hash1 == hash2 for different strings\n");
|
|
|
|
|
|
|
|
hash1 = p___std_type_info_hash(&ti2);
|
|
|
|
ok(hash1 != hash2, "hash1 == hash2 for different strings\n");
|
2016-08-04 16:29:06 +02:00
|
|
|
}
|
|
|
|
|
2022-02-07 17:44:46 +01:00
|
|
|
static void test___unDName(void)
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
name = p___unDName(0, "??4QDnsDomainNameRecord@@QAEAAV0@$$QAV0@@Z", 0, malloc, free, 0);
|
|
|
|
ok(!strcmp(name, "public: class QDnsDomainNameRecord & __thiscall "
|
|
|
|
"QDnsDomainNameRecord::operator=(class QDnsDomainNameRecord &&)"),
|
|
|
|
"unDName returned %s\n", wine_dbgstr_a(name));
|
|
|
|
free(name);
|
|
|
|
|
|
|
|
name = p___unDName(0, "??4QDnsDomainNameRecord@@QAEAAV0@$$QEAV0@@Z", 0, malloc, free, 0);
|
|
|
|
ok(!strcmp(name, "public: class QDnsDomainNameRecord & __thiscall "
|
|
|
|
"QDnsDomainNameRecord::operator=(class QDnsDomainNameRecord && __ptr64)"),
|
|
|
|
"unDName returned %s\n", wine_dbgstr_a(name));
|
|
|
|
free(name);
|
|
|
|
}
|
|
|
|
|
2016-04-11 23:19:00 +02:00
|
|
|
START_TEST(cpp)
|
|
|
|
{
|
|
|
|
if (!init()) return;
|
|
|
|
test___std_exception();
|
2016-08-04 16:29:06 +02:00
|
|
|
test___std_type_info();
|
2022-02-07 17:44:46 +01:00
|
|
|
test___unDName();
|
2016-04-11 23:19:00 +02:00
|
|
|
}
|