2 * Copyright 2012 Piotr Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/test.h"
34 #define __thiscall __stdcall
36 #define __thiscall __cdecl
39 /* Emulate a __thiscall */
45 BYTE pop_eax
; /* popl %eax (ret addr) */
46 BYTE pop_edx
; /* popl %edx (func) */
47 BYTE pop_ecx
; /* popl %ecx (this) */
48 BYTE push_eax
; /* pushl %eax */
49 WORD jmp_edx
; /* jmp *%edx */
53 static void * (WINAPI
*call_thiscall_func1
)( void *func
, void *this );
54 static void * (WINAPI
*call_thiscall_func2
)( void *func
, void *this, const void *a
);
56 static void init_thiscall_thunk(void)
58 struct thiscall_thunk
*thunk
= VirtualAlloc( NULL
, sizeof(*thunk
),
59 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
60 thunk
->pop_eax
= 0x58; /* popl %eax */
61 thunk
->pop_edx
= 0x5a; /* popl %edx */
62 thunk
->pop_ecx
= 0x59; /* popl %ecx */
63 thunk
->push_eax
= 0x50; /* pushl %eax */
64 thunk
->jmp_edx
= 0xe2ff; /* jmp *%edx */
65 call_thiscall_func1
= (void *)thunk
;
66 call_thiscall_func2
= (void *)thunk
;
69 #define call_func1(func,_this) call_thiscall_func1(func,_this)
70 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)a)
74 #define init_thiscall_thunk()
75 #define call_func1(func,_this) func(_this)
76 #define call_func2(func,_this,a) func(_this,a)
80 static _Yarn_char
* (__thiscall
*_Yarn_char_ctor_cstr
)(_Yarn_char
*this, const char *str
);
81 static _Yarn_char
* (__thiscall
*_Yarn_char_copy_ctor
)(_Yarn_char
*this, const _Yarn_char
*copy
);
82 static void (__thiscall
*_Yarn_char_dtor
)(_Yarn_char
*this);
83 static const char* (__thiscall
*_Yarn_char_c_str
)(const _Yarn_char
*this);
84 static char (__thiscall
*_Yarn_char_empty
)(const _Yarn_char
*this);
86 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
87 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
88 static BOOL
init(void)
90 HMODULE msvcp
= LoadLibraryA("msvcp100.dll");
92 win_skip("msvcp100.dll not installed\n");
96 if(sizeof(void*) == 8) { /* 64-bit initialization */
97 SET(_Yarn_char_ctor_cstr
, "??0?$_Yarn@D@std@@QEAA@PEBD@Z");
98 SET(_Yarn_char_copy_ctor
, "??0?$_Yarn@D@std@@QEAA@AEBV01@@Z");
99 SET(_Yarn_char_dtor
, "??1?$_Yarn@D@std@@QEAA@XZ");
100 SET(_Yarn_char_c_str
, "?_C_str@?$_Yarn@D@std@@QEBAPEBDXZ");
101 SET(_Yarn_char_empty
, "?_Empty@?$_Yarn@D@std@@QEBA_NXZ");
103 SET(_Yarn_char_ctor_cstr
, "??0?$_Yarn@D@std@@QAE@PBD@Z");
104 SET(_Yarn_char_copy_ctor
, "??0?$_Yarn@D@std@@QAE@ABV01@@Z");
105 SET(_Yarn_char_dtor
, "??1?$_Yarn@D@std@@QAE@XZ");
106 SET(_Yarn_char_c_str
, "?_C_str@?$_Yarn@D@std@@QBEPBDXZ");
107 SET(_Yarn_char_empty
, "?_Empty@?$_Yarn@D@std@@QBE_NXZ");
110 init_thiscall_thunk();
114 static void test__Yarn_char(void)
120 call_func2(_Yarn_char_ctor_cstr
, &c1
, NULL
);
121 ok(!c1
.str
, "c1.str = %s\n", c1
.str
);
122 ok(!c1
.null_str
, "c1.null_str = %d\n", c1
.null_str
);
123 bool_ret
= (char)(INT_PTR
)call_func1(_Yarn_char_empty
, &c1
);
124 ok(bool_ret
== 1, "ret = %d\n", bool_ret
);
125 str
= call_func1(_Yarn_char_c_str
, &c1
);
126 ok(str
== &c1
.null_str
, "str = %p, expected %p\n", str
, &c1
.null_str
);
127 call_func1(_Yarn_char_dtor
, &c1
);
129 call_func2(_Yarn_char_ctor_cstr
, &c1
, "");
130 ok(c1
.str
!= NULL
, "c1.str = NULL\n");
131 ok(!strcmp(c1
.str
, ""), "c1.str = %s\n", c1
.str
);
132 ok(!c1
.null_str
, "c1.null_str = %d\n", c1
.null_str
);
133 bool_ret
= (char)(INT_PTR
)call_func1(_Yarn_char_empty
, &c1
);
134 ok(bool_ret
== 0, "ret = %d\n", bool_ret
);
135 str
= call_func1(_Yarn_char_c_str
, &c1
);
136 ok(str
== c1
.str
, "str = %p, expected %p\n", str
, c1
.str
);
137 call_func1(_Yarn_char_dtor
, &c1
);
139 call_func2(_Yarn_char_ctor_cstr
, &c1
, "test");
140 ok(!strcmp(c1
.str
, "test"), "c1.str = %s\n", c1
.str
);
141 ok(!c1
.null_str
, "c1.null_str = %d\n", c1
.null_str
);
142 bool_ret
= (char)(INT_PTR
)call_func1(_Yarn_char_empty
, &c1
);
143 ok(bool_ret
== 0, "ret = %d\n", bool_ret
);
144 str
= call_func1(_Yarn_char_c_str
, &c1
);
145 ok(str
== c1
.str
, "str = %p, expected %p\n", str
, c1
.str
);
147 call_func2(_Yarn_char_copy_ctor
, &c2
, &c1
);
148 ok(c1
.str
!= c2
.str
, "c1.str = c2.str\n");
149 ok(!strcmp(c2
.str
, "test"), "c2.str = %s\n", c2
.str
);
150 ok(!c2
.null_str
, "c2.null_str = %d\n", c2
.null_str
);
151 call_func1(_Yarn_char_dtor
, &c2
);
154 call_func2(_Yarn_char_copy_ctor
, &c2
, &c1
);
155 ok(c1
.str
!= c2
.str
, "c1.str = c2.str\n");
156 ok(!strcmp(c2
.str
, "test"), "c2.str = %s\n", c2
.str
);
157 ok(!c2
.null_str
, "c2.null_str = %d\n", c2
.null_str
);
158 call_func1(_Yarn_char_dtor
, &c2
);
159 call_func1(_Yarn_char_dtor
, &c1
);