2 * Copyright 2020 Daniel Lehman
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
19 #include "wine/test.h"
25 BYTE pop_eax
; /* popl %eax (ret addr) */
26 BYTE pop_edx
; /* popl %edx (func) */
27 BYTE pop_ecx
; /* popl %ecx (this) */
28 BYTE push_eax
; /* pushl %eax */
29 WORD jmp_edx
; /* jmp *%edx */
33 static ULONG_PTR (WINAPI
*call_thiscall_func1
)( void *func
, void *this );
34 static ULONG_PTR (WINAPI
*call_thiscall_func3
)( void *func
,
35 void *this, const void *a
, const void *b
);
37 static void init_thiscall_thunk(void)
39 struct thiscall_thunk
*thunk
= VirtualAlloc( NULL
, sizeof(*thunk
),
40 MEM_COMMIT
, PAGE_EXECUTE_READWRITE
);
41 thunk
->pop_eax
= 0x58; /* popl %eax */
42 thunk
->pop_edx
= 0x5a; /* popl %edx */
43 thunk
->pop_ecx
= 0x59; /* popl %ecx */
44 thunk
->push_eax
= 0x50; /* pushl %eax */
45 thunk
->jmp_edx
= 0xe2ff; /* jmp *%edx */
46 call_thiscall_func1
= (void *)thunk
;
47 call_thiscall_func3
= (void *)thunk
;
50 #define call_func1(func,_this) call_thiscall_func1(func,_this)
51 #define call_func3(func,_this,a,b) call_thiscall_func3(func,_this,(const void*)(a),(const void*)(b))
55 #define init_thiscall_thunk()
56 #define call_func1(func,_this) func(_this)
57 #define call_func3(func,_this,a,b) func(_this,a,b)
63 #define __thiscall __stdcall
65 #define __thiscall __cdecl
68 typedef void (*vtable_ptr
)(void);
71 const vtable_ptr
*vtable
;
79 const vtable_ptr
*vtable
;
85 static Context
* (__cdecl
*p_Context_CurrentContext
)(void);
86 static _Context
* (__cdecl
*p__Context__CurrentContext
)(_Context
*);
88 static _Timer
* (__thiscall
*p__Timer_ctor
)(_Timer
*,unsigned int,unsigned char);
89 static void (__thiscall
*p__Timer_dtor
)(_Timer
*);
90 static void (__thiscall
*p__Timer__Start
)(_Timer
*);
91 static void (__thiscall
*p__Timer__Stop
)(_Timer
*);
93 static const BYTE
*p_byte_reverse_table
;
95 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(module,y)
96 #define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
98 static BOOL
init(void)
102 module
= LoadLibraryA("concrt140.dll");
105 win_skip("concrt140.dll not installed\n");
109 SET(p__Context__CurrentContext
,
110 "?_CurrentContext@_Context@details@Concurrency@@SA?AV123@XZ");
111 if(sizeof(void*) == 8) { /* 64-bit initialization */
112 SET(p_Context_CurrentContext
,
113 "?CurrentContext@Context@Concurrency@@SAPEAV12@XZ");
115 "??0_Timer@details@Concurrency@@IEAA@I_N@Z");
117 "??1_Timer@details@Concurrency@@MEAA@XZ");
119 "?_Start@_Timer@details@Concurrency@@IEAAXXZ");
121 "?_Stop@_Timer@details@Concurrency@@IEAAXXZ");
123 SET(p_Context_CurrentContext
,
124 "?CurrentContext@Context@Concurrency@@SAPAV12@XZ");
127 "??0_Timer@details@Concurrency@@IAA@I_N@Z");
129 "??1_Timer@details@Concurrency@@MAA@XZ");
131 "?_Start@_Timer@details@Concurrency@@IAAXXZ");
133 "?_Stop@_Timer@details@Concurrency@@IAAXXZ");
136 "??0_Timer@details@Concurrency@@IAE@I_N@Z");
138 "??1_Timer@details@Concurrency@@MAE@XZ");
140 "?_Start@_Timer@details@Concurrency@@IAEXXZ");
142 "?_Stop@_Timer@details@Concurrency@@IAEXXZ");
146 init_thiscall_thunk();
147 SET(p_byte_reverse_table
, "?_Byte_reverse_table@details@Concurrency@@3QBEB");
151 static void test_CurrentContext(void)
156 ctx
= p_Context_CurrentContext();
157 ok(!!ctx
, "got NULL\n");
159 memset(&_ctx
, 0xcc, sizeof(_ctx
));
160 ret
= p__Context__CurrentContext(&_ctx
);
161 ok(_ctx
.ctx
== ctx
, "expected %p, got %p\n", ctx
, _ctx
.ctx
);
162 ok(ret
== &_ctx
, "expected %p, got %p\n", &_ctx
, ret
);
165 static HANDLE callback_called
;
166 static void __cdecl
timer_callback(_Timer
*this)
168 SetEvent(callback_called
);
171 static void test_Timer(void)
173 vtable_ptr vtable
[2];
177 callback_called
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
178 ok(callback_called
!= NULL
, "CreateEvent failed\n");
180 call_func3(p__Timer_ctor
, &timer
, 1, TRUE
);
181 ok(!timer
.timer
, "timer already set to %p\n", timer
.timer
);
182 ok(timer
.elapse
== 1, "elapse = %u, expected 0\n", timer
.elapse
);
183 ok(timer
.repeat
, "timer.repeat = FALSE\n");
184 vtable
[0] = timer
.vtable
[0];
185 vtable
[1] = (vtable_ptr
)timer_callback
;
186 timer
.vtable
= vtable
;
187 call_func1(p__Timer__Start
, &timer
);
188 ok(timer
.timer
!= NULL
, "timer = NULL\n");
189 ret
= WaitForSingleObject(callback_called
, 1000);
190 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lu\n", ret
);
191 ret
= WaitForSingleObject(callback_called
, 1000);
192 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lu\n", ret
);
193 call_func1(p__Timer__Stop
, &timer
);
194 ok(!timer
.timer
, "timer != NULL\n");
195 call_func1(p__Timer_dtor
, &timer
);
196 ResetEvent(callback_called
);
198 call_func3(p__Timer_ctor
, &timer
, 1, FALSE
);
199 timer
.vtable
= vtable
;
200 call_func1(p__Timer__Start
, &timer
);
201 ok(timer
.timer
!= NULL
, "timer = NULL\n");
202 ret
= WaitForSingleObject(callback_called
, 1000);
203 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lu\n", ret
);
204 ret
= WaitForSingleObject(callback_called
, 100);
205 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lu\n", ret
);
206 call_func1(p__Timer_dtor
, &timer
);
208 call_func3(p__Timer_ctor
, &timer
, 0, TRUE
);
209 timer
.vtable
= vtable
;
210 call_func1(p__Timer__Start
, &timer
);
211 ok(timer
.timer
!= NULL
, "timer = NULL\n");
212 ret
= WaitForSingleObject(callback_called
, 1000);
213 ok(ret
== WAIT_OBJECT_0
, "WaitForSingleObject returned %lu\n", ret
);
214 ret
= WaitForSingleObject(callback_called
, 100);
215 ok(ret
== WAIT_TIMEOUT
, "WaitForSingleObject returned %lu\n", ret
);
216 call_func1(p__Timer__Stop
, &timer
);
217 ok(!timer
.timer
, "timer != NULL\n");
218 call_func1(p__Timer_dtor
, &timer
);
220 CloseHandle(callback_called
);
223 static BYTE
byte_reverse(BYTE b
)
225 b
= ((b
& 0xf0) >> 4) | ((b
& 0x0f) << 4);
226 b
= ((b
& 0xcc) >> 2) | ((b
& 0x33) << 2);
227 b
= ((b
& 0xaa) >> 1) | ((b
& 0x55) << 1);
231 static void test_data_exports(void)
235 ok(IsBadWritePtr((BYTE
*)p_byte_reverse_table
, 256), "byte_reverse_table is writeable.\n");
236 for (i
= 0; i
< 256; ++i
)
238 ok(p_byte_reverse_table
[i
] == byte_reverse(i
), "Got unexpected byte %#x, expected %#x.\n",
239 p_byte_reverse_table
[i
], byte_reverse(i
));
243 START_TEST(concrt140
)
246 test_CurrentContext();