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
;
43 #define __thiscall __stdcall
45 #define __thiscall __cdecl
48 static _Container_base12
* (__thiscall
*p__Container_base12_copy_ctor
)(_Container_base12
*, _Container_base12
*);
49 static _Container_base12
* (__thiscall
*p__Container_base12_ctor
)(_Container_base12
*);
50 static void (__thiscall
*p__Container_base12__Orphan_all
)(_Container_base12
*);
51 static void (__thiscall
*p__Container_base12_dtor
)(_Container_base12
*);
52 static _Iterator_base12
** (__thiscall
*p__Container_base12__Getpfirst
)(_Container_base12
*);
53 static void (__thiscall
*p__Container_base12__Swap_all
)(_Container_base12
*, _Container_base12
*);
55 /* Emulate a __thiscall */
61 BYTE pop_eax
; /* popl %eax (ret addr) */
62 BYTE pop_edx
; /* popl %edx (func) */
63 BYTE pop_ecx
; /* popl %ecx (this) */
64 BYTE push_eax
; /* pushl %eax */
65 WORD jmp_edx
; /* jmp *%edx */
69 static void * (WINAPI
*call_thiscall_func1
)( void *func
, void *this );
70 static void * (WINAPI
*call_thiscall_func2
)( void *func
, void *this, const void *a
);
72 static void init_thiscall_thunk(void)
74 struct thiscall_thunk
*thunk
= VirtualAlloc( NULL
, sizeof(*thunk
),
75 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
76 thunk
->pop_eax
= 0x58; /* popl %eax */
77 thunk
->pop_edx
= 0x5a; /* popl %edx */
78 thunk
->pop_ecx
= 0x59; /* popl %ecx */
79 thunk
->push_eax
= 0x50; /* pushl %eax */
80 thunk
->jmp_edx
= 0xe2ff; /* jmp *%edx */
81 call_thiscall_func1
= (void *)thunk
;
82 call_thiscall_func2
= (void *)thunk
;
85 #define call_func1(func,_this) call_thiscall_func1(func,_this)
86 #define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)a)
90 #define init_thiscall_thunk()
91 #define call_func1(func,_this) func(_this)
92 #define call_func2(func,_this,a) func(_this,a)
96 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
97 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
98 static BOOL
init(void)
100 HMODULE msvcp
= LoadLibraryA("msvcp100.dll");
102 win_skip("msvcp100.dll not installed\n");
106 if(sizeof(void*) == 8) { /* 64-bit initialization */
107 SET(p__Container_base12_copy_ctor
, "??0_Container_base12@std@@QEAA@AEBU01@@Z");
108 SET(p__Container_base12_ctor
, "??0_Container_base12@std@@QEAA@XZ");
109 SET(p__Container_base12__Orphan_all
, "?_Orphan_all@_Container_base12@std@@QEAAXXZ");
110 SET(p__Container_base12_dtor
, "??1_Container_base12@std@@QEAA@XZ");
111 SET(p__Container_base12__Getpfirst
, "?_Getpfirst@_Container_base12@std@@QEBAPEAPEAU_Iterator_base12@2@XZ");
112 SET(p__Container_base12__Swap_all
, "?_Swap_all@_Container_base12@std@@QEAAXAEAU12@@Z");
114 SET(p__Container_base12_copy_ctor
, "??0_Container_base12@std@@QAE@ABU01@@Z");
115 SET(p__Container_base12_ctor
, "??0_Container_base12@std@@QAE@XZ");
116 SET(p__Container_base12__Orphan_all
, "?_Orphan_all@_Container_base12@std@@QAEXXZ");
117 SET(p__Container_base12_dtor
, "??1_Container_base12@std@@QAE@XZ");
118 SET(p__Container_base12__Getpfirst
, "?_Getpfirst@_Container_base12@std@@QBEPAPAU_Iterator_base12@2@XZ");
119 SET(p__Container_base12__Swap_all
, "?_Swap_all@_Container_base12@std@@QAEXAAU12@@Z");
122 init_thiscall_thunk();
126 static void test__Container_base12(void)
128 _Container_base12 c1
, c2
;
129 _Iterator_base12 i1
, i2
, **pi
;
130 _Container_proxy p1
, p2
;
132 call_func1(p__Container_base12_ctor
, &c1
);
133 ok(c1
.proxy
== NULL
, "c1.proxy != NULL\n");
138 call_func2(p__Container_base12_copy_ctor
, &c2
, &c1
);
139 ok(c1
.proxy
== &p1
, "c1.proxy = %p, expected %p\n", c1
.proxy
, &p1
);
140 ok(c2
.proxy
== NULL
, "c2.proxy != NULL\n");
147 pi
= call_func1(p__Container_base12__Getpfirst
, &c1
);
148 ok(pi
== &p1
.head
, "pi = %p, expected %p\n", pi
, &p1
.head
);
149 pi
= call_func1(p__Container_base12__Getpfirst
, &c2
);
150 ok(pi
== NULL
, "pi != NULL\n");
153 call_func1(p__Container_base12_dtor
, &c1
);
154 ok(p1
.cont
== &c1
, "p1.cont = %p, expected %p\n", p1
.cont
, &c1
);
155 ok(p1
.head
== &i1
, "p1.head = %p, expected %p\n", p1
.head
, &i1
);
156 ok(i1
.proxy
== &p1
, "i1.proxy = %p, expected %p\n", i1
.proxy
, &p1
);
157 ok(i1
.next
== &i2
, "i1.next = %p, expected %p\n", i1
.next
, &i2
);
158 ok(i2
.proxy
== &p1
, "i2.proxy = %p, expected %p\n", i2
.proxy
, &p1
);
159 ok(i2
.next
== NULL
, "i2.next != NULL\n");
161 call_func1(p__Container_base12__Orphan_all
, &c1
);
162 ok(p1
.cont
== &c1
, "p1.cont = %p, expected %p\n", p1
.cont
, &c1
);
163 ok(p1
.head
== &i1
, "p1.head = %p, expected %p\n", p1
.head
, &i1
);
164 ok(i1
.proxy
== &p1
, "i1.proxy = %p, expected %p\n", i1
.proxy
, &p1
);
165 ok(i1
.next
== &i2
, "i1.next = %p, expected %p\n", i1
.next
, &i2
);
166 ok(i2
.proxy
== &p1
, "i2.proxy = %p, expected %p\n", i2
.proxy
, &p1
);
167 ok(i2
.next
== NULL
, "i2.next != NULL\n");
170 call_func2(p__Container_base12__Swap_all
, &c1
, &c2
);
171 ok(c1
.proxy
== NULL
, "c1.proxy != NULL\n");
172 ok(c2
.proxy
== &p1
, "c2.proxy = %p, expected %p\n", c2
.proxy
, &p2
);
173 ok(p1
.cont
== &c2
, "p1.cont = %p, expected %p\n", p1
.cont
, &c2
);
176 p2
.cont
= (void*)0xdeadbeef;
177 p2
.head
= (void*)0xdeadbeef;
179 call_func2(p__Container_base12__Swap_all
, &c1
, &c2
);
180 ok(c1
.proxy
== &p1
, "c1.proxt = %p, expected %p\n", c1
.proxy
, &p1
);
181 ok(p1
.cont
== &c1
, "p1.cont = %p, expected %p\n", p1
.cont
, &c1
);
182 ok(p1
.head
== &i1
, "p1.head = %p, expected %p\n", p1
.head
, &i1
);
183 ok(c2
.proxy
== &p2
, "c2.proxy = %p, expected %p\n", c2
.proxy
, &p2
);
184 ok(p2
.cont
== &c2
, "p2.cont = %p, expected %p\n", p2
.cont
, &c2
);
185 ok(p2
.head
== (void*)0xdeadbeef, "p2.head = %p, expected 0xdeadbeef\n", p2
.head
);
193 test__Container_base12();