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
23 #include "wine/test.h"
25 struct __Container_proxy
;
28 struct __Container_proxy
*proxy
;
31 typedef struct __Iterator_base12
{
32 struct __Container_proxy
*proxy
;
33 struct __Iterator_base12
*next
;
36 typedef struct __Container_proxy
{
37 const _Container_base12
*cont
;
38 _Iterator_base12
*head
;
48 #define __thiscall __stdcall
50 #define __thiscall __cdecl
53 static _Container_base12
* (__thiscall
*p__Container_base12_copy_ctor
)(_Container_base12
*, _Container_base12
*);
54 static _Container_base12
* (__thiscall
*p__Container_base12_ctor
)(_Container_base12
*);
55 static void (__thiscall
*p__Container_base12__Orphan_all
)(_Container_base12
*);
56 static void (__thiscall
*p__Container_base12_dtor
)(_Container_base12
*);
57 static _Iterator_base12
** (__thiscall
*p__Container_base12__Getpfirst
)(_Container_base12
*);
58 static void (__thiscall
*p__Container_base12__Swap_all
)(_Container_base12
*, _Container_base12
*);
59 static _Runtime_object
* (__thiscall
*p__Runtime_object_ctor
)(_Runtime_object
*);
60 static _Runtime_object
* (__thiscall
*p__Runtime_object_ctor_id
)(_Runtime_object
*, int);
62 /* Emulate a __thiscall */
68 BYTE pop_eax
; /* popl %eax (ret addr) */
69 BYTE pop_edx
; /* popl %edx (func) */
70 BYTE pop_ecx
; /* popl %ecx (this) */
71 BYTE push_eax
; /* pushl %eax */
72 WORD jmp_edx
; /* jmp *%edx */
76 static void * (WINAPI
*call_thiscall_func1
)( void *func
, void *this );
77 static void * (WINAPI
*call_thiscall_func2
)( void *func
, void *this, const void *a
);
79 static void init_thiscall_thunk(void)
81 struct thiscall_thunk
*thunk
= VirtualAlloc( NULL
, sizeof(*thunk
),
82 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
83 thunk
->pop_eax
= 0x58; /* popl %eax */
84 thunk
->pop_edx
= 0x5a; /* popl %edx */
85 thunk
->pop_ecx
= 0x59; /* popl %ecx */
86 thunk
->push_eax
= 0x50; /* pushl %eax */
87 thunk
->jmp_edx
= 0xe2ff; /* jmp *%edx */
88 call_thiscall_func1
= (void *)thunk
;
89 call_thiscall_func2
= (void *)thunk
;
92 #define call_func1(func,_this) call_thiscall_func1(func,_this)
93 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a))
97 #define init_thiscall_thunk()
98 #define call_func1(func,_this) func(_this)
99 #define call_func2(func,_this,a) func(_this,a)
101 #endif /* __i386__ */
103 static HMODULE msvcp
;
104 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
105 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
106 static BOOL
init(void)
108 msvcp
= LoadLibraryA("msvcp100.dll");
110 win_skip("msvcp100.dll not installed\n");
114 if(sizeof(void*) == 8) { /* 64-bit initialization */
115 SET(p__Container_base12_copy_ctor
, "??0_Container_base12@std@@QEAA@AEBU01@@Z");
116 SET(p__Container_base12_ctor
, "??0_Container_base12@std@@QEAA@XZ");
117 SET(p__Container_base12__Orphan_all
, "?_Orphan_all@_Container_base12@std@@QEAAXXZ");
118 SET(p__Container_base12_dtor
, "??1_Container_base12@std@@QEAA@XZ");
119 SET(p__Container_base12__Getpfirst
, "?_Getpfirst@_Container_base12@std@@QEBAPEAPEAU_Iterator_base12@2@XZ");
120 SET(p__Container_base12__Swap_all
, "?_Swap_all@_Container_base12@std@@QEAAXAEAU12@@Z");
121 SET(p__Runtime_object_ctor
, "??0_Runtime_object@details@Concurrency@@QEAA@XZ");
122 SET(p__Runtime_object_ctor_id
, "??0_Runtime_object@details@Concurrency@@QEAA@H@Z");
125 SET(p__Container_base12_copy_ctor
, "??0_Container_base12@std@@QAA@ABU01@@Z");
126 SET(p__Container_base12_ctor
, "??0_Container_base12@std@@QAA@XZ");
127 SET(p__Container_base12__Orphan_all
, "?_Orphan_all@_Container_base12@std@@QAAXXZ");
128 SET(p__Container_base12_dtor
, "??1_Container_base12@std@@QAA@XZ");
129 SET(p__Container_base12__Getpfirst
, "?_Getpfirst@_Container_base12@std@@QBAPAPAU_Iterator_base12@2@XZ");
130 SET(p__Container_base12__Swap_all
, "?_Swap_all@_Container_base12@std@@QAAXAAU12@@Z");
131 SET(p__Runtime_object_ctor
, "??0_Runtime_object@details@Concurrency@@QAA@XZ");
132 SET(p__Runtime_object_ctor_id
, "??0_Runtime_object@details@Concurrency@@QAA@H@Z");
134 SET(p__Container_base12_copy_ctor
, "??0_Container_base12@std@@QAE@ABU01@@Z");
135 SET(p__Container_base12_ctor
, "??0_Container_base12@std@@QAE@XZ");
136 SET(p__Container_base12__Orphan_all
, "?_Orphan_all@_Container_base12@std@@QAEXXZ");
137 SET(p__Container_base12_dtor
, "??1_Container_base12@std@@QAE@XZ");
138 SET(p__Container_base12__Getpfirst
, "?_Getpfirst@_Container_base12@std@@QBEPAPAU_Iterator_base12@2@XZ");
139 SET(p__Container_base12__Swap_all
, "?_Swap_all@_Container_base12@std@@QAEXAAU12@@Z");
140 SET(p__Runtime_object_ctor
, "??0_Runtime_object@details@Concurrency@@QAE@XZ");
141 SET(p__Runtime_object_ctor_id
, "??0_Runtime_object@details@Concurrency@@QAE@H@Z");
145 init_thiscall_thunk();
149 static void test__Container_base12(void)
151 _Container_base12 c1
, c2
;
152 _Iterator_base12 i1
, i2
, **pi
;
153 _Container_proxy p1
, p2
;
155 call_func1(p__Container_base12_ctor
, &c1
);
156 ok(c1
.proxy
== NULL
, "c1.proxy != NULL\n");
161 call_func2(p__Container_base12_copy_ctor
, &c2
, &c1
);
162 ok(c1
.proxy
== &p1
, "c1.proxy = %p, expected %p\n", c1
.proxy
, &p1
);
163 ok(c2
.proxy
== NULL
, "c2.proxy != NULL\n");
170 pi
= call_func1(p__Container_base12__Getpfirst
, &c1
);
171 ok(pi
== &p1
.head
, "pi = %p, expected %p\n", pi
, &p1
.head
);
172 pi
= call_func1(p__Container_base12__Getpfirst
, &c2
);
173 ok(pi
== NULL
, "pi != NULL\n");
176 call_func1(p__Container_base12_dtor
, &c1
);
177 ok(p1
.cont
== &c1
, "p1.cont = %p, expected %p\n", p1
.cont
, &c1
);
178 ok(p1
.head
== &i1
, "p1.head = %p, expected %p\n", p1
.head
, &i1
);
179 ok(i1
.proxy
== &p1
, "i1.proxy = %p, expected %p\n", i1
.proxy
, &p1
);
180 ok(i1
.next
== &i2
, "i1.next = %p, expected %p\n", i1
.next
, &i2
);
181 ok(i2
.proxy
== &p1
, "i2.proxy = %p, expected %p\n", i2
.proxy
, &p1
);
182 ok(i2
.next
== NULL
, "i2.next != NULL\n");
184 call_func1(p__Container_base12__Orphan_all
, &c1
);
185 ok(p1
.cont
== &c1
, "p1.cont = %p, expected %p\n", p1
.cont
, &c1
);
186 ok(p1
.head
== &i1
, "p1.head = %p, expected %p\n", p1
.head
, &i1
);
187 ok(i1
.proxy
== &p1
, "i1.proxy = %p, expected %p\n", i1
.proxy
, &p1
);
188 ok(i1
.next
== &i2
, "i1.next = %p, expected %p\n", i1
.next
, &i2
);
189 ok(i2
.proxy
== &p1
, "i2.proxy = %p, expected %p\n", i2
.proxy
, &p1
);
190 ok(i2
.next
== NULL
, "i2.next != NULL\n");
193 call_func2(p__Container_base12__Swap_all
, &c1
, &c2
);
194 ok(c1
.proxy
== NULL
, "c1.proxy != NULL\n");
195 ok(c2
.proxy
== &p1
, "c2.proxy = %p, expected %p\n", c2
.proxy
, &p2
);
196 ok(p1
.cont
== &c2
, "p1.cont = %p, expected %p\n", p1
.cont
, &c2
);
199 p2
.cont
= (void*)0xdeadbeef;
200 p2
.head
= (void*)0xdeadbeef;
202 call_func2(p__Container_base12__Swap_all
, &c1
, &c2
);
203 ok(c1
.proxy
== &p1
, "c1.proxt = %p, expected %p\n", c1
.proxy
, &p1
);
204 ok(p1
.cont
== &c1
, "p1.cont = %p, expected %p\n", p1
.cont
, &c1
);
205 ok(p1
.head
== &i1
, "p1.head = %p, expected %p\n", p1
.head
, &i1
);
206 ok(c2
.proxy
== &p2
, "c2.proxy = %p, expected %p\n", c2
.proxy
, &p2
);
207 ok(p2
.cont
== &c2
, "p2.cont = %p, expected %p\n", p2
.cont
, &c2
);
208 ok(p2
.head
== (void*)0xdeadbeef, "p2.head = %p, expected 0xdeadbeef\n", p2
.head
);
213 const char* export_name
;
214 } vbtable_size_exports_list
[] = {
215 {{0x18, 0x18}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_istream@DU?$char_traits@D@std@@@1@@"},
216 {{ 0x8, 0x8}, "??_8?$basic_iostream@DU?$char_traits@D@std@@@std@@7B?$basic_ostream@DU?$char_traits@D@std@@@1@@"},
217 {{0x18, 0x18}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_istream@GU?$char_traits@G@std@@@1@@"},
218 {{ 0x8, 0x8}, "??_8?$basic_iostream@GU?$char_traits@G@std@@@std@@7B?$basic_ostream@GU?$char_traits@G@std@@@1@@"},
219 {{0x18, 0x18}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_istream@_WU?$char_traits@_W@std@@@1@@"},
220 {{ 0x8, 0x8}, "??_8?$basic_iostream@_WU?$char_traits@_W@std@@@std@@7B?$basic_ostream@_WU?$char_traits@_W@std@@@1@@"},
221 {{0x10, 0x10}, "??_8?$basic_istream@DU?$char_traits@D@std@@@std@@7B@"},
222 {{0x10, 0x10}, "??_8?$basic_istream@GU?$char_traits@G@std@@@std@@7B@"},
223 {{0x10, 0x10}, "??_8?$basic_istream@_WU?$char_traits@_W@std@@@std@@7B@"},
224 {{ 0x8, 0x8}, "??_8?$basic_ostream@DU?$char_traits@D@std@@@std@@7B@"},
225 {{ 0x8, 0x8}, "??_8?$basic_ostream@GU?$char_traits@G@std@@@std@@7B@"},
226 {{ 0x8, 0x8}, "??_8?$basic_ostream@_WU?$char_traits@_W@std@@@std@@7B@"},
230 static void test_vbtable_size_exports(void)
233 const int *p_vbtable
;
234 int arch_idx
= (sizeof(void*) == 8);
236 for (i
= 0; vbtable_size_exports_list
[i
].export_name
; i
++)
238 SET(p_vbtable
, vbtable_size_exports_list
[i
].export_name
);
240 ok(p_vbtable
[0] == 0, "vbtable[0] wrong, got 0x%x\n", p_vbtable
[0]);
241 ok(p_vbtable
[1] == vbtable_size_exports_list
[i
].value
[arch_idx
],
242 "%d: %s[1] wrong, got 0x%x\n", i
, vbtable_size_exports_list
[i
].export_name
, p_vbtable
[1]);
246 static void test__Runtime_object(void)
249 memset(&ro
, 0, sizeof(ro
));
251 call_func1(p__Runtime_object_ctor
, &ro
);
252 ok(ro
.id
== 0, "ro.id = %d\n", ro
.id
);
253 call_func1(p__Runtime_object_ctor
, &ro
);
254 ok(ro
.id
== 2, "ro.id = %d\n", ro
.id
);
255 call_func1(p__Runtime_object_ctor
, &ro
);
256 ok(ro
.id
== 4, "ro.id = %d\n", ro
.id
);
257 call_func2(p__Runtime_object_ctor_id
, &ro
, 0);
258 ok(ro
.id
== 0, "ro.id = %d\n", ro
.id
);
259 call_func2(p__Runtime_object_ctor_id
, &ro
, 1);
260 ok(ro
.id
== 1, "ro.id = %d\n", ro
.id
);
261 call_func2(p__Runtime_object_ctor_id
, &ro
, 10);
262 ok(ro
.id
== 10, "ro.id = %d\n", ro
.id
);
263 call_func1(p__Runtime_object_ctor
, &ro
);
264 ok(ro
.id
== 6, "ro.id = %d\n", ro
.id
);
272 test__Container_base12();
273 test_vbtable_size_exports();
274 test__Runtime_object();