26#define WIN32_NO_STATUS
81static void (
WINAPI *pRtlGetCallersAddress)(
void**,
void**);
102static BOOLEAN (
CDECL *pRtlDeleteFunctionTable)(RUNTIME_FUNCTION*);
111#define RTL_UNLOAD_EVENT_TRACE_NUMBER 64
126#if defined(__x86_64__)
197 ok(
arg2 == 0x5678,
"wrong arg2 %Ix\n",
arg2 );
198 ok(
arg3 == 0xdeadbeef,
"wrong arg3 %Ix\n",
arg3 );
202#if defined(__i386__) || defined(__x86_64__)
215 if (!pRtlGetEnabledExtendedFeatures || !pRtlGetEnabledExtendedFeatures(1 <<
XSTATE_AVX))
221 length =
sizeof(context_buffer);
223 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
226 ok(!!ymm,
"Got zero ymm.\n");
227 memset(ymm, 0xcc,
sizeof(*ymm));
230 ok(
length ==
sizeof(*xmm) * (
sizeof(
void *) == 8 ? 16 : 8),
"Got unexpected length %#lx.\n",
length);
231 ok(!!xmm,
"Got zero xmm.\n");
238 xs = (
XSTATE *)((
char *)c_ex + c_ex->XState.Offset);
251 ok(!!xmm,
"Got zero xmm.\n");
253 xmm[0].Low = 0x2828282828282828;
254 xmm[0].High = xmm[0].Low;
255 ymm->
Ymm0.Low = 0x4848484848484848;
262#define check_context_exception_request( a, b ) check_context_exception_request_( a, b, __LINE__ )
263static void check_context_exception_request_(
DWORD flags,
BOOL hardware_exception,
unsigned int line )
271 ok_(__FILE__,
line)( (
flags & exception_reporting_flags) == expected_flags,
"got %#lx, expected %#lx.\n",
272 flags, expected_flags );
275static BOOL test_hwbpt_in_syscall_trap;
281 test_hwbpt_in_syscall_trap =
TRUE;
286static void test_hwbpt_in_syscall(
void)
297 handler = AddVectoredExceptionHandler(
TRUE, test_hwbpt_in_syscall_handler);
301 c.Dr7 = 3 | (3 << 16) | (3 << 18);
304 test_hwbpt_in_syscall_trap =
FALSE;
305 teb->
TlsSlots[ind] = (
void *)0xdeadbeef;
306 ok(test_hwbpt_in_syscall_trap,
"expected trap.\n");
308 test_hwbpt_in_syscall_trap =
FALSE;
311 ok(!test_hwbpt_in_syscall_trap,
"got trap.\n");
316 RemoveVectoredExceptionHandler(
handler);
323#ifndef __WINE_WINTRNL_H
324#define ProcessExecuteFlags 0x22
325#define MEM_EXECUTE_OPTION_DISABLE 0x01
326#define MEM_EXECUTE_OPTION_ENABLE 0x02
327#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION 0x04
328#define MEM_EXECUTE_OPTION_PERMANENT 0x08
362 { { 0xe4, 0x11, 0xc3 },
364 { { 0xe5, 0x11, 0xc3 },
366 { { 0xe6, 0x11, 0xc3 },
368 { { 0xe7, 0x11, 0xc3 },
383 { { 0xea, 0, 0, 0, 0, 0, 0, 0xc3 },
388 { { 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0xcf, 0x83, 0xc4, 0x0c, 0xc3 },
393 { { 0xb8, 0xef, 0xbe, 0x00, 0x00, 0x8e, 0xe8, 0xc3 },
397 { { 0x06, 0x31, 0xc0, 0x8e, 0xc0, 0x26, 0xa1, 0, 0, 0, 0, 0x07, 0xc3 },
400 { { 0x0f, 0xa8, 0x31, 0xc0, 0x8e, 0xe8, 0x65, 0xa1, 0, 0, 0, 0, 0x0f, 0xa9, 0xc3 },
405 { { 0x0e, 0x17, 0x58, 0xc3 },
410 { { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
413 { { 0x64,0x64,0x64,0x64,0xfa,0xc3 },
417 { { 0xcd, 0xff, 0xc3 },
421 { { 0x0f, 0x20, 0xc0, 0xc3 },
423 { { 0x0f, 0x20, 0xe0, 0xc3 },
426 { { 0x0f, 0x22, 0xc0, 0xc3 },
428 { { 0x0f, 0x22, 0xe0, 0xc3 },
432 { { 0x0f, 0x21, 0xc0, 0xc3 },
434 { { 0x0f, 0x21, 0xc8, 0xc3 },
436 { { 0x0f, 0x21, 0xf8, 0xc3 },
439 { { 0x0f, 0x23, 0xc0, 0xc3 },
441 { { 0x0f, 0x23, 0xc8, 0xc3 },
443 { { 0x0f, 0x23, 0xf8, 0xc3 },
447 { { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xc3 },
449 { { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xc3 },
452 { { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xc3 },
454 { { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xc3 },
458 { { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xc3 },
460 { { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xc3 },
462 { { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xc3 },
465 { { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xc3 },
469 { { 0x1e, 0x06, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfa, 0x07, 0x1f, 0xc3 },
473 { { 0xf1, 0x90, 0xc3 },
475 { { 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
476 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
477 0xba, 0xba, 0xba, 0xba, 0xba,
485 const void *
code,
unsigned int code_size,
493 DWORD oldaccess, oldaccess2;
495 exc_frame.frame.Handler =
handler;
496 exc_frame.frame.Prev =
NtCurrentTeb()->Tib.ExceptionList;
505 NtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
521 ok((
void *)
context->Eax == pRtlRaiseException ||
523 "debugger managed to modify Eax to %lx should be %p\n",
524 context->Eax, pRtlRaiseException);
534 "Eip at %lx instead of %lx or %lx\n",
context->Eip,
552 trace(
"exception: %08lx flags:%lx addr:%p context: Eip:%lx\n",
561 "wrong context flags %lx\n",
context->ContextFlags );
571 "Eip at %lx instead of %lx or %lx\n",
context->Eip,
582 ok(
context->Eax == 0xf00f00f0,
"Eax is %lx, should have been set to 0xf00f00f0 in vectored handler\n",
598static const BYTE call_one_arg_code[] = {
599 0x8b, 0x44, 0x24, 0x08,
601 0x8b, 0x44, 0x24, 0x08,
611static void run_rtlraiseexception_test(
DWORD exceptioncode)
619 record.ExceptionCode = exceptioncode;
620 record.ExceptionFlags = 0;
623 record.NumberParameters = 0;
625 frame.
Handler = rtlraiseexception_handler;
633 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &rtlraiseexception_vectored_handler);
634 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
639 "address set to %p instead of %p\n",
record.ExceptionAddress, (
char *)
code_mem + 0x0b );
642 pRtlRemoveVectoredExceptionHandler(vectored_handler);
646static void test_rtlraiseexception(
void)
648 if (!pRtlRaiseException)
650 skip(
"RtlRaiseException not found\n");
655 run_rtlraiseexception_test(0x12345);
660static DWORD unwind_expected_eax;
665 trace(
"exception: %08lx flags:%lx addr:%p context: Eip:%lx\n",
674 ok(
context->Eax == unwind_expected_eax,
"context->Eax is %08lx instead of %08lx\n",
675 context->Eax, unwind_expected_eax);
681static const BYTE call_unwind_code[] = {
686 0xe8, 0x00, 0x00, 0x00, 0x00,
688 0x05, 0x1e, 0x00, 0x00, 0x00,
689 0xff, 0x74, 0x24, 0x20,
690 0xff, 0x74, 0x24, 0x20,
692 0xff, 0x74, 0x24, 0x24,
693 0x8B, 0x44, 0x24, 0x24,
703static void test_unwind(
void)
712 frame1->Handler = unwind_handler;
717 frame2->
Handler = unwind_handler;
722 unwind_expected_eax = 0xDEAD0000;
724 ok(
retval == 0xDEAD0000,
"RtlUnwind returned eax %08lx instead of %08x\n",
retval, 0xDEAD0000);
725 ok(
NtCurrentTeb()->Tib.ExceptionList == frame2,
"Exception record points to %p instead of %p\n",
729 unwind_expected_eax = 0xDEAD0000;
731 ok(
retval == 0xDEAD0001,
"RtlUnwind returned eax %08lx instead of %08x\n",
retval, 0xDEAD0001);
732 ok(
NtCurrentTeb()->Tib.ExceptionList == frame1,
"Exception record points to %p instead of %p\n",
743 unsigned int i, parameter_count,
entry =
except - exceptions;
746 trace(
"exception %u: %lx flags:%lx addr:%p\n",
753 "%u: Unexpected eip %#lx/%#lx\n",
entry,
757 "%u: Unexpected exception address %p/%p\n",
entry,
763 parameter_count =
except->nb_params;
765 parameter_count =
except->alt_nb_params;
772 if (
except->nb_params == 2 &&
except->params[1] >= 0xfffffffd)
790 "%u: Wrong parameter %d: %Ix/%lx\n",
797 "%u: Wrong parameter %d: %Ix/%lx\n",
806static void test_prot_fault(
void)
814 skip(
"Exception %u broken on Wow64\n",
i );
818 run_exception_test(prot_fault_handler, &exceptions[
i], &exceptions[
i].
code,
819 sizeof(exceptions[
i].
code), 0);
822 trace(
"No exception, assuming win9x, no point in testing further\n" );
831 DWORD dr0, dr1, dr2, dr3, dr6, dr7;
838 const struct dbgreg_test *
test = *(
const struct dbgreg_test **)(frame + 1);
850#define CHECK_DEBUG_REG(n, m) \
851 ok((ctx.Dr##n & m) == test->dr##n, "(%d) failed to set debug register " #n " to %lx, got %lx\n", \
852 test_num, test->dr##n, ctx.Dr##n)
854static void check_debug_registers(
int test_num,
const struct dbgreg_test *
test)
863 CHECK_DEBUG_REG(0, ~0);
864 CHECK_DEBUG_REG(1, ~0);
865 CHECK_DEBUG_REG(2, ~0);
866 CHECK_DEBUG_REG(3, ~0);
867 CHECK_DEBUG_REG(6, 0x0f);
868 CHECK_DEBUG_REG(7, ~0xdc00);
871static const BYTE segfault_code[5] = {
882 ok (!(
context->EFlags & 0x100),
"eflags has single stepping bit set\n");
890 "exception is not EXCEPTION_SINGLE_STEP: %lx\n", rec->
ExceptionCode);
896static const BYTE single_stepcode[] = {
909static const BYTE align_check_code[] = {
928 ok (!(
context->EFlags & 0x40000),
"eflags has AC bit set\n");
934static const BYTE direction_flag_code[] = {
950 if (
flags & 0x400)
trace(
"eflags has DF bit set\n" );
952 ok(
context->EFlags & 0x400,
"context eflags has DF bit cleared\n" );
971 ok( (
context->Dr6 & 0xf) == 1,
"B0 flag is not set in Dr6\n");
972 ok( !(
context->Dr6 & 0x4000),
"BS flag is set in Dr6\n");
979 ok( (
context->Dr6 & 0x4000),
"BS flag is not set in Dr6\n");
987 ok( (
context->Dr6 & 0xf) == 1,
"B0 flag is not set in Dr6\n");
988 ok( !(
context->Dr6 & 0x4000),
"BS flag is set in Dr6\n");
995 ok( (
context->Dr6 & 0xf) == 0,
"B0...3 flags in Dr6 shouldn't be set\n");
996 ok( (
context->Dr6 & 0x4000),
"BS flag is not set in Dr6\n");
1003static const BYTE dummy_code[] = { 0x90, 0x90, 0xc3 };
1017static const BYTE int3_code[] = { 0xCC, 0xc3 };
1023 run_exception_test( bpx_handler,
NULL, dummy_code,
sizeof(dummy_code), 0 );
1028static void test_exceptions(
void)
1032 struct dbgreg_test dreg_test;
1035 if (!pNtGetContextThread || !pNtSetContextThread)
1037 skip(
"NtGetContextThread/NtSetContextThread not found\n" );
1042 memset(&dreg_test, 0,
sizeof(dreg_test));
1044 dreg_test.dr0 = 0x42424240;
1045 dreg_test.dr2 = 0x126bb070;
1046 dreg_test.dr3 = 0x0badbad0;
1047 dreg_test.dr7 = 0xffff0115;
1048 run_exception_test(dreg_handler, &dreg_test, &segfault_code,
sizeof(segfault_code), 0);
1049 check_debug_registers(1, &dreg_test);
1051 dreg_test.dr0 = 0x42424242;
1052 dreg_test.dr2 = 0x100f0fe7;
1053 dreg_test.dr3 = 0x0abebabe;
1054 dreg_test.dr7 = 0x115;
1055 run_exception_test(dreg_handler, &dreg_test, &segfault_code,
sizeof(segfault_code), 0);
1056 check_debug_registers(2, &dreg_test);
1058#if defined(__REACTOS__)
1061 skip(
"Skipping test of single stepping behavior and int3 handling on ReactOS due to crashes\n");
1068 run_exception_test(single_step_handler,
NULL, &single_stepcode,
sizeof(single_stepcode), 0);
1073 run_exception_test(align_check_handler,
NULL, align_check_code,
sizeof(align_check_code), 0);
1078 run_exception_test(direction_flag_handler,
NULL, direction_flag_code,
sizeof(direction_flag_code), 0);
1090 run_exception_test(bpx_handler,
NULL, dummy_code,
sizeof(dummy_code), 0);
1094 run_exception_test(int3_handler,
NULL, int3_code,
sizeof(int3_code), 0);
1106 res = pNtGetContextThread(
h, &
ctx );
1108 ok(
ctx.Dr0 == 0,
"dr0 %lx\n",
ctx.Dr0 );
1109 ok(
ctx.Dr7 == 0,
"dr7 %lx\n",
ctx.Dr7 );
1112 res = pNtSetContextThread(
h, &
ctx );
1130 DWORD continuestatus;
1138 if(!pNtGetContextThread || !pNtSetContextThread || !pNtReadVirtualMemory || !pNtTerminateProcess)
1140 skip(
"NtGetContextThread, NtSetContextThread, NtReadVirtualMemory or NtTerminateProcess not found\n");
1144 if (with_WaitForDebugEventEx && !pWaitForDebugEventEx)
1146 skip(
"WaitForDebugEventEx not found, skipping unicode strings in OutputDebugStringW\n");
1158 continuestatus = cont_status;
1160 ok(
ret,
"reading debug event\n");
1163 ok(!
ret,
"ContinueDebugEvent unexpectedly succeeded\n");
1177 skip(
"child process loaded at different address, terminating it\n");
1188 sizeof(code_mem_address), &size_read);
1191 sizeof(stage), &size_read);
1199 "got %#lx.\n",
ctx.ContextFlags);
1201 trace(
"exception 0x%lx at %p firstchance=%ld Eip=0x%lx, Eax=0x%lx ctx.ContextFlags %#lx\n",
1207 ok(
FALSE,
"got way too many exceptions, probably caught in an infinite loop, terminating child\n");
1218 "wrong eip %p ntdll %p-%p\n", (
void *)
ctx.Eip,
ntdll,
1220 check_context_exception_request(
ctx.ContextFlags,
TRUE );
1226 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xb,
"Eip at %lx instead of %p\n",
1227 ctx.Eip, (
char *)code_mem_address + 0xb);
1231 ctx.Eax = 0xf00f00f1;
1234 check_context_exception_request(
ctx.ContextFlags, !
is_wow64 );
1241 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xb,
"Eip at 0x%lx instead of %p\n",
1242 ctx.Eip, (
char *)code_mem_address + 0xb);
1244 ctx.Eax = 0xf00f00f1;
1255 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xa ||
1256 (
is_wow64 && (
char *)
ctx.Eip == (
char *)code_mem_address + 0xb) ||
1257 broken((
char *)
ctx.Eip == (
char *)code_mem_address + 0xd) ,
1258 "Eip at 0x%lx instead of %p\n",
1259 ctx.Eip, (
char *)code_mem_address + 0xa);
1261 if ((
char *)
ctx.Eip == (
char *)code_mem_address + 0xa)
1265 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0xb ||
1266 broken((
char *)
ctx.Eip == (
char *)code_mem_address + 0xd) ,
1267 "Eip at 0x%lx instead of %p\n",
1268 ctx.Eip, (
char *)code_mem_address + 0xb);
1271 check_context_exception_request(
ctx.ContextFlags, !
is_wow64 );
1277 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 0x1d,
1278 "expected Eip = %p, got 0x%lx\n", (
char *)code_mem_address + 0x1d,
ctx.Eip);
1281 check_context_exception_request(
ctx.ContextFlags,
TRUE );
1287 ok((
char *)
ctx.Eip == (
char *)code_mem_address + 2,
1288 "expected Eip = %p, got 0x%lx\n", (
char *)code_mem_address + 2,
ctx.Eip);
1291 check_context_exception_request(
ctx.ContextFlags,
TRUE );
1302 check_context_exception_request(
ctx.ContextFlags, !
is_wow64 );
1308 check_context_exception_request(
ctx.ContextFlags, !
is_wow64 );
1312 check_context_exception_request(
ctx.ContextFlags,
TRUE );
1318#if defined(__REACTOS__) && defined(_MSC_VER)
1320 __asm mov [segss],
ss
1325 ok(
ctx.SegSs ==
ss,
"wrong ss %04lx / %04x\n",
ctx.SegSs,
ss );
1326 ok(
ctx.SegFs !=
ctx.SegSs,
"wrong fs %04lx / %04lx\n",
ctx.SegFs,
ctx.SegSs );
1329 ok(
ctx.SegDs ==
ctx.SegSs,
"wrong ds %04lx / %04lx\n",
ctx.SegDs,
ctx.SegSs );
1330 ok(
ctx.SegEs ==
ctx.SegSs,
"wrong es %04lx / %04lx\n",
ctx.SegEs,
ctx.SegSs );
1331 ok(
ctx.SegGs ==
ctx.SegSs,
"wrong gs %04lx / %04lx\n",
ctx.SegGs,
ctx.SegSs );
1335 ok( !
ctx.SegDs,
"wrong ds %04lx / %04lx\n",
ctx.SegDs,
ctx.SegSs );
1336 ok( !
ctx.SegEs,
"wrong es %04lx / %04lx\n",
ctx.SegEs,
ctx.SegSs );
1337 ok( !
ctx.SegGs,
"wrong gs %04lx / %04lx\n",
ctx.SegGs,
ctx.SegSs );
1339 check_context_exception_request(
ctx.ContextFlags,
TRUE );
1342 ok(
FALSE,
"unexpected stage %u\n", stage);
1355 sizeof(stage), &size_read);
1359 ok(with_WaitForDebugEventEx &&
1361 "unexpected unicode debug string event\n");
1364 "unexpected ansi debug string event %u %s %lx\n",
1365 stage, with_WaitForDebugEventEx ?
"with" :
"without", cont_status);
1394 sizeof(stage), &size_read);
1399 ok(de.
u.
RipInfo.
dwError == 0x11223344,
"got unexpected rip error code %08lx, expected %08x\n",
1401 ok(de.
u.
RipInfo.
dwType == 0x55667788,
"got unexpected rip type %08lx, expected %08x\n",
1405 ok(
FALSE,
"unexpected stage %x\n", stage);
1426 int *stage = *(
int **)(frame + 1);
1435 else if ( *stage == 2 || *stage == 3 ) {
1439 skip(
"system doesn't support SIMD exceptions\n");
1442 "exception code: %#lx, should be %#lx\n",
1454 ok(
FALSE,
"unexpected stage %x\n", *stage);
1459static const BYTE simd_exception_test[] = {
1461 0x0f, 0xae, 0x1c, 0x24,
1463 0x66, 0x81, 0x24, 0x24, 0xff, 0xfd,
1464 0x0f, 0xae, 0x14, 0x24,
1469 0x0f, 0x10, 0x0c, 0x24,
1474 0x0f, 0xae, 0x14, 0x24,
1479static const BYTE simd_exception_test2[] = {
1481 0x0f, 0xae, 0x1c, 0x24,
1483 0x66, 0x81, 0x24, 0x24, 0x7f, 0xff,
1484 0x0f, 0xae, 0x14, 0x24,
1489 0x0f, 0xae, 0x14, 0x24,
1494static const BYTE sse_check[] = {
1499static void test_simd_exceptions(
void)
1506 run_exception_test(simd_fault_handler, &stage, sse_check,
sizeof(sse_check), 0);
1508 skip(
"system doesn't support SSE\n");
1515 run_exception_test(simd_fault_handler, &stage, simd_exception_test,
1516 sizeof(simd_exception_test), 0);
1522 run_exception_test(simd_fault_handler, &stage, simd_exception_test2,
1523 sizeof(simd_exception_test2), 0);
1527struct fpu_exception_info
1530 DWORD exception_offset;
1537 struct fpu_exception_info *
info = *(
struct fpu_exception_info **)(frame + 1);
1547static void test_fpu_exceptions(
void)
1549 static const BYTE fpu_exception_test_ie[] =
1552 0x66, 0xc7, 0x04, 0x24, 0xfe, 0x03,
1553 0x9b, 0xd9, 0x7c, 0x24, 0x02,
1562 0xd9, 0x6c, 0x24, 0x02,
1567 static const BYTE fpu_exception_test_de[] =
1570 0x66, 0xc7, 0x04, 0x24, 0xfb, 0x03,
1571 0x9b, 0xd9, 0x7c, 0x24, 0x02,
1581 0xd9, 0x6c, 0x24, 0x02,
1586 struct fpu_exception_info
info;
1589 run_exception_test(fpu_exception_handler, &
info, fpu_exception_test_ie,
sizeof(fpu_exception_test_ie), 0);
1591 "Got exception code %#lx, expected EXCEPTION_FLT_STACK_CHECK\n",
info.exception_code);
1592 ok(
info.exception_offset == 0x19 ||
info.exception_offset ==
info.eip_offset,
1593 "Got exception offset %#lx, expected 0x19\n",
info.exception_offset);
1594 ok(
info.eip_offset == 0x1b,
"Got EIP offset %#lx, expected 0x1b\n",
info.eip_offset);
1597 run_exception_test(fpu_exception_handler, &
info, fpu_exception_test_de,
sizeof(fpu_exception_test_de), 0);
1599 "Got exception code %#lx, expected EXCEPTION_FLT_DIVIDE_BY_ZERO\n",
info.exception_code);
1600 ok(
info.exception_offset == 0x17 ||
info.exception_offset ==
info.eip_offset,
1601 "Got exception offset %#lx, expected 0x17\n",
info.exception_offset);
1602 ok(
info.eip_offset == 0x19,
"Got EIP offset %#lx, expected 0x19\n",
info.eip_offset);
1605struct dpe_exception_info {
1606 BOOL exception_caught;
1614 struct dpe_exception_info *
info = *(
struct dpe_exception_info **)(frame + 1);
1621 "Exception address: %p, expected %p\n",
1631static void test_dpe_exceptions(
void)
1633 static const BYTE single_ret[] = {0xC3};
1634 struct dpe_exception_info
info;
1636 BOOL has_hw_support;
1645 skip(
"This software platform does not support DEP\n");
1655 ok(
len ==
sizeof val,
"returned length: %ld\n",
len);
1658 skip(
"toggling DEP impossible - status locked\n");
1659 is_permanent =
TRUE;
1661 can_test_without =
FALSE;
1663 can_test_with =
FALSE;
1679 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_NOACCESS);
1680 ok(
info.exception_caught ==
TRUE,
"Execution of disabled memory succeeded\n");
1683 "Access violation type: %08x\n", (
unsigned)
info.exception_info);
1685 trace(
"DEP hardware support: %s\n", has_hw_support?
"Yes":
"No");
1689 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_READWRITE);
1692 ok(
info.exception_caught ==
TRUE,
"Execution of data memory succeeded\n");
1694 "Access violation type: %08x\n", (
unsigned)
info.exception_info);
1697 ok(
info.exception_caught ==
FALSE,
"Execution trapped without hardware support\n");
1700 skip(
"DEP is in AlwaysOff state\n");
1711 if(can_test_without)
1715 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_READWRITE);
1716 ok(
info.exception_caught ==
FALSE,
"Execution trapped with DEP turned off\n");
1721 run_exception_test(dpe_exception_handler, &
info, single_ret,
sizeof(single_ret),
PAGE_NOACCESS);
1722 ok(
info.exception_caught ==
TRUE,
"Execution of disabled memory succeeded\n");
1724 "Access violation type: %08x\n", (
unsigned)
info.exception_info);
1727 skip(
"DEP is in AlwaysOn state\n");
1748static void test_thread_context(
void)
1754 DWORD Eax, Ebx, Ecx, Edx, Esi, Edi, Ebp, Esp, Eip,
1755 SegCs, SegDs, SegEs, SegFs, SegGs, SegSs, EFlags, prev_frame,
1760 DWORD new_x87_control;
1762 static const BYTE call_func[] =
1792 0x68, 0x7f, 0x04, 0x00, 0x00,
1811#define COMPARE(reg) \
1812 ok( context.reg == expect.reg, "wrong " #reg " %08lx/%08lx\n", context.reg, expect.reg )
1817 trace(
"expect: eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx "
1818 "eip=%08lx cs=%04lx ds=%04lx es=%04lx fs=%04lx gs=%04lx ss=%04lx flags=%08lx prev=%08lx\n",
1822 trace(
"actual: eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx "
1823 "eip=%08lx cs=%04lx ds=%04lx es=%04lx fs=%04lx gs=%04lx ss=%04lx flags=%08lx\n",
1830 "wrong flags %08lx\n",
context.ContextFlags );
1856 trace(
"expect: eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx "
1857 "eip=%08lx cs=%04lx ds=%04lx es=%04lx fs=%04lx gs=%04lx ss=%04lx flags=%08lx prev=%08lx\n",
1861 trace(
"actual: eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx ebp=%08lx esp=%08lx "
1862 "eip=%08lx cs=%04lx ds=%04lx es=%04lx fs=%04lx gs=%04lx ss=%04lx flags=%08lx\n",
1875 ok( (
char *)
context.Eip >= (
char *)pNtGetContextThread - 0x40000 &&
1876 (
char *)
context.Eip <= (
char *)pNtGetContextThread + 0x40000,
1877 "wrong Eip %08lx/%08lx\n",
context.Eip, (
DWORD)pNtGetContextThread );
1887 "wrong x87 control word %#lx/%#lx.\n",
context.FloatSave.ControlWord,
expect.x87_control );
1889 "x87 control word changed in NtGetContextThread() %#x/%#x.\n",
1895static BYTE saved_KiUserExceptionDispatcher_bytes[7];
1896static BOOL hook_called;
1897static void *hook_KiUserExceptionDispatcher_eip;
1898static void *dbg_except_continue_handler_eip;
1899static void *hook_exception_address;
1916test_kiuserexceptiondispatcher_regs;
1921 ok(hook_called,
"Hook was not called.\n");
1926 dbg_except_continue_handler_eip = (
void *)
context->Eip;
1932 pRtlUnwind(
NtCurrentTeb()->Tib.ExceptionList, (
void *)
context->Eip, rec, (
void *)0xdeadbeef);
1941 trace(
"dbg_except_continue_vectored_handler, code %#lx, eip %#lx, ExceptionAddress %p.\n",
1966 trace(
"rec %p context %p context->Eip %#lx, context->Esp %#lx (%x), ContextFlags %#lx.\n",
1973 (
char *)(rec + 1) >= (
char *)
context,
"wrong ptrs %p / %p\n", rec,
context );
1980 hook_KiUserExceptionDispatcher_eip = (
void *)
context->Eip;
1983 sizeof(saved_KiUserExceptionDispatcher_bytes));
1987static void test_KiUserExceptionDispatcher(
void)
1989 PVOID vectored_handler;
1990 static BYTE except_code[] =
1994 0x00, 0x00, 0x00, 0x00,
2012 0x00, 0x00, 0x00, 0x00,
2024 static BYTE hook_trampoline[] =
2028 0x00, 0x00, 0x00, 0x00,
2031 void *phook_KiUserExceptionDispatcher = hook_KiUserExceptionDispatcher;
2032 BYTE patched_KiUserExceptionDispatcher_bytes[7];
2033 DWORD old_protect1, old_protect2;
2041 win_skip(
"RtlUnwind is not available.\n");
2048 win_skip(
"Skipping test that hangs on WOW64\n");
2053 *(
DWORD *)(except_code + 1) = (
DWORD)&test_kiuserexceptiondispatcher_regs;
2054 *(
DWORD *)(except_code + 0x1d) = (
DWORD)&test_kiuserexceptiondispatcher_regs.new_eax;
2056 *(
unsigned int *)(hook_trampoline + 2) = (
ULONG_PTR)&phook_KiUserExceptionDispatcher;
2066 sizeof(saved_KiUserExceptionDispatcher_bytes));
2068 ptr = patched_KiUserExceptionDispatcher_bytes;
2071 *(
void **)
ptr = hook_trampoline;
2072 ptr +=
sizeof(
void *);
2078 sizeof(patched_KiUserExceptionDispatcher_bytes));
2080 run_exception_test(dbg_except_continue_handler,
NULL, except_code,
sizeof(except_code),
2084 ok(hook_called,
"Hook was not called.\n");
2086 ok(test_kiuserexceptiondispatcher_regs.new_eax == 0xdeadbeef,
"Got unexpected eax %#lx.\n",
2087 test_kiuserexceptiondispatcher_regs.new_eax);
2088 ok(test_kiuserexceptiondispatcher_regs.new_esi == 0xdeadbeef,
"Got unexpected esi %#lx.\n",
2089 test_kiuserexceptiondispatcher_regs.new_esi);
2090 ok(test_kiuserexceptiondispatcher_regs.old_edi
2091 == test_kiuserexceptiondispatcher_regs.new_edi,
"edi does not match.\n");
2092 ok(test_kiuserexceptiondispatcher_regs.old_ebp
2093 == test_kiuserexceptiondispatcher_regs.new_ebp,
"ebp does not match.\n");
2097 ok(hook_exception_address == bpt_address ||
broken(!hook_exception_address) ,
2098 "Got unexpected exception address %p, expected %p.\n",
2099 hook_exception_address, bpt_address);
2100 ok(hook_KiUserExceptionDispatcher_eip == bpt_address,
"Got unexpected exception address %p, expected %p.\n",
2101 hook_KiUserExceptionDispatcher_eip, bpt_address);
2102 ok(dbg_except_continue_handler_eip == bpt_address,
"Got unexpected exception address %p, expected %p.\n",
2103 dbg_except_continue_handler_eip, bpt_address);
2105 record.ExceptionCode = 0x80000003;
2106 record.ExceptionFlags = 0;
2109 record.NumberParameters = 0;
2111 vectored_handler = AddVectoredExceptionHandler(
TRUE, dbg_except_continue_vectored_handler);
2114 sizeof(patched_KiUserExceptionDispatcher_bytes));
2116 hook_called =
FALSE;
2118 pRtlRaiseException(&
record);
2121 ok(hook_called ||
broken(!hook_called) ,
"Hook was not called.\n");
2124 sizeof(saved_KiUserExceptionDispatcher_bytes));
2126 RemoveVectoredExceptionHandler(vectored_handler);
2128 old_protect2, &old_protect2);
2134static BYTE saved_KiUserApcDispatcher[7];
2142 ok(
arg2 == 0x5678,
"wrong arg2 %Ix\n",
arg2 );
2143 ok(
arg3 == 0xdeadbeef,
"wrong arg3 %Ix\n",
arg3 );
2145 if (
context->ContextFlags != 1)
2147 trace(
"context %p eip %lx ebp %lx esp %lx (%x)\n",
2158 trace(
"alertable %lx context %p eip %lx ebp %lx esp %lx (%x)\n", *alertable,
2160 if ((
void *)(xctx + 1) < (
void *)
context->Esp)
2177static void test_KiUserApcDispatcher(
void)
2179 BYTE hook_trampoline[] =
2183 0x00, 0x00, 0x00, 0x00,
2187 BYTE patched_KiUserApcDispatcher[7];
2188 void *phook_KiUserApcDispatcher = hook_KiUserApcDispatcher;
2201 ptr = patched_KiUserApcDispatcher;
2205 ptr +=
sizeof(
void *);
2212 hook_called =
FALSE;
2216 ok( hook_called,
"hook was not called\n" );
2235 trace(
"eip %p id %lx args %p (%x) len %lx unk1 %lx unk2 %lx args %lx,%lx\n",
2238 if (
args[0] != arg0)
2240 void *esp = (
void *)arg0;
2243 ok( (
char *)esp - ((
char *)
args +
len) < 0x10,
"wrong esp offset %p / %p\n", esp,
args );
2251 if (win32u)
ok(
mod == win32u,
"ret address %p not in win32u %p\n", eip, win32u );
2252 else trace(
"ret address %p in %p\n", eip,
mod );
2257static void test_KiUserCallbackDispatcher(
void)
2259 BYTE saved_code[7], patched_code[7];
2272 *(
void **)
ptr = hook_KiUserCallbackDispatcher;
2273 ptr +=
sizeof(
void *);
2279 DestroyWindow(
CreateWindowA(
"Static",
"test", 0, 0, 0, 0, 0, 0, 0, 0, 0 ));
2285static void test_instrumentation_callback(
void)
2287 static const BYTE instrumentation_callback[] =
2290 0x00, 0x00, 0x00, 0x00,
2294 unsigned int instrumentation_call_count;
2299 memcpy(
code_mem, instrumentation_callback,
sizeof(instrumentation_callback) );
2300 *(
volatile void **)((
char *)
code_mem + 2) = &instrumentation_call_count;
2305 instrumentation_call_count = 0;
2312 win_skip(
"Failed setting instrumenation callback.\n" );
2315 DestroyWindow(
CreateWindowA(
"Static",
"test", 0, 0, 0, 0, 0, 0, 0, 0, 0 ));
2316 todo_wine ok( instrumentation_call_count,
"got %u.\n", instrumentation_call_count );
2319 instrumentation_call_count = 0;
2322 ok( !instrumentation_call_count,
"got %u.\n", instrumentation_call_count );
2325#elif defined(__x86_64__)
2327static LONG consolidate_dummy_called;
2335 ok(
ctx->Rip == 0xdeadbeef,
"RtlRestoreContext wrong Rip, expected: 0xdeadbeef, got: %Ix\n",
ctx->Rip);
2339 ok(
ctx->Rip != 0xdeadbeef,
"RtlUnwindEx wrong Rip, got: %Ix\n",
ctx->Rip );
2359 for (
i = 0;
i < 8;
i++)
2360 ok(regs->
FpNvRegs[
i] == ec_ctx->V[
i + 8].D[0],
"wrong reg D%u, expected: %g, got: %g\n",
2361 i + 8, regs->
FpNvRegs[
i], ec_ctx->V[
i + 8].D[0] );
2369static void test_restore_context(
void)
2371 SETJMP_FLOAT128 *fltsave;
2378 if (!pRtlUnwindEx || !pRtlRestoreContext || !pRtlCaptureContext)
2380 skip(
"RtlUnwindEx/RtlCaptureContext/RtlRestoreContext not found\n");
2389 pRtlCaptureContext(&
ctx);
2392 pRtlRestoreContext(&
ctx,
NULL);
2393 ok(0,
"shouldn't be reached\n");
2411 ok(
buf.FpCsr == 0x27f,
"Got unexpected FpCsr %#x.\n",
buf.FpCsr);
2415 pRtlRestoreContext(&
ctx, &rec);
2416 ok(0,
"shouldn't be reached\n");
2420 ok(
buf.Rbx ==
ctx.Rbx,
"longjmp failed for Rbx, expected: %Ix, got: %Ix\n",
buf.Rbx,
ctx.Rbx);
2421 ok(
buf.Rsp ==
ctx.Rsp,
"longjmp failed for Rsp, expected: %Ix, got: %Ix\n",
buf.Rsp,
ctx.Rsp);
2422 ok(
buf.Rbp ==
ctx.Rbp,
"longjmp failed for Rbp, expected: %Ix, got: %Ix\n",
buf.Rbp,
ctx.Rbp);
2423 ok(
buf.Rsi ==
ctx.Rsi,
"longjmp failed for Rsi, expected: %Ix, got: %Ix\n",
buf.Rsi,
ctx.Rsi);
2424 ok(
buf.Rdi ==
ctx.Rdi,
"longjmp failed for Rdi, expected: %Ix, got: %Ix\n",
buf.Rdi,
ctx.Rdi);
2425 ok(
buf.R12 ==
ctx.R12,
"longjmp failed for R12, expected: %Ix, got: %Ix\n",
buf.R12,
ctx.R12);
2426 ok(
buf.R13 ==
ctx.R13,
"longjmp failed for R13, expected: %Ix, got: %Ix\n",
buf.R13,
ctx.R13);
2427 ok(
buf.R14 ==
ctx.R14,
"longjmp failed for R14, expected: %Ix, got: %Ix\n",
buf.R14,
ctx.R14);
2428 ok(
buf.R15 ==
ctx.R15,
"longjmp failed for R15, expected: %Ix, got: %Ix\n",
buf.R15,
ctx.R15);
2430 fltsave = &
buf.Xmm6;
2431 for (
i = 0;
i < 10;
i++)
2433 ok(fltsave[
i].Part[0] ==
ctx.FltSave.XmmRegisters[
i + 6].Low,
2434 "longjmp failed for Xmm%d, expected %Ix, got %Ix\n",
i + 6,
2435 fltsave[
i].Part[0],
ctx.FltSave.XmmRegisters[
i + 6].Low);
2437 ok(fltsave[
i].Part[1] ==
ctx.FltSave.XmmRegisters[
i + 6].High,
2438 "longjmp failed for Xmm%d, expected %Ix, got %Ix\n",
i + 6,
2439 fltsave[
i].Part[1],
ctx.FltSave.XmmRegisters[
i + 6].High);
2441 ok(
ctx.FltSave.ControlWord == 0x7f,
"Got unexpected float control word %#x.\n",
ctx.FltSave.ControlWord);
2442 ok(
ctx.MxCsr == 0x3f80,
"Got unexpected MxCsr %#lx.\n",
ctx.MxCsr);
2443 ok(
ctx.FltSave.MxCsr == 0x3f80,
"Got unexpected MxCsr %#lx.\n",
ctx.FltSave.MxCsr);
2446 pRtlRestoreContext(&
ctx, &rec);
2447 ok(0,
"shouldn't be reached\n");
2451 ok(
ctx.FltSave.ControlWord == 0x27f,
"Got unexpected float control word %#x.\n",
ctx.FltSave.ControlWord);
2452 ok(
ctx.FltSave.MxCsr == 0x1f80,
"Got unexpected MxCsr %#lx.\n",
ctx.MxCsr);
2455 ok(0,
"unexpected pass %ld\n",
pass);
2460 pRtlCaptureContext(&
ctx);
2471 pRtlUnwindEx((
void*)
buf.Frame, (
void*)0xdeadbeef, &rec,
NULL, &
ctx,
NULL);
2472 ok(0,
"shouldn't be reached\n");
2475 ok(
pass == 4,
"unexpected pass %ld\n",
pass);
2491 ctx.Rip = 0xdeadbeef;
2493 pRtlRestoreContext(&
ctx, &rec);
2494 ok(0,
"shouldn't be reached\n");
2497 ok(consolidate_dummy_called == 1,
"test_consolidate_dummy not called\n");
2499 ok(0,
"unexpected pass %ld\n",
pass);
2504 pRtlCaptureContext(&
ctx);
2515 ctx.Rip = 0xdeadbeef;
2518 pRtlUnwindEx((
void*)
buf.Frame, (
void*)0xdeadbeef, &rec,
NULL, &
ctx,
NULL);
2519 ok(0,
"shouldn't be reached\n");
2522 ok(consolidate_dummy_called == 2,
"test_consolidate_dummy not called\n");
2524 ok(0,
"unexpected pass %ld\n",
pass);
2527static int termination_handler_called;
2530 termination_handler_called++;
2533 ok(frame == 0x1234,
"frame = %p\n", (
void*)frame);
2536static void test___C_specific_handler(
void)
2543 SCOPE_TABLE scope_table;
2545 if (!p__C_specific_handler)
2547 win_skip(
"__C_specific_handler not available\n");
2551 memset(&rec, 0,
sizeof(rec));
2557 dispatch.HandlerData = &scope_table;
2559 scope_table.Count = 1;
2560 scope_table.ScopeRecord[0].BeginAddress = 0x200;
2561 scope_table.ScopeRecord[0].EndAddress = 0x400;
2562 scope_table.ScopeRecord[0].HandlerAddress = (
ULONG_PTR)termination_handler-
dispatch.ImageBase;
2563 scope_table.ScopeRecord[0].JumpTarget = 0;
2566 termination_handler_called = 0;
2569 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2570 termination_handler_called);
2575 ok(termination_handler_called == 1,
"termination_handler_called = %d\n",
2576 termination_handler_called);
2590 DWORD alt_nb_params;
2607 { { 0xe4, 0x11, 0xc3 },
2609 { { 0xe5, 0x11, 0xc3 },
2611 { { 0xe6, 0x11, 0xc3 },
2613 { { 0xe7, 0x11, 0xc3 },
2628 { { 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x00, 0xcf, 0x48, 0x83, 0xc4, 0x18, 0xc3 },
2633 { { 0xb8, 0xef, 0xbe, 0x00, 0x00, 0x8e, 0xe8, 0xc3 },
2637 { { 0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0xfa,0xc3 },
2642 { { 0xcd, 0xff, 0xc3 },
2646 { { 0x0f, 0x20, 0xc0, 0xc3 },
2648 { { 0x0f, 0x20, 0xe0, 0xc3 },
2651 { { 0x0f, 0x22, 0xc0, 0xc3 },
2653 { { 0x0f, 0x22, 0xe0, 0xc3 },
2657 { { 0x0f, 0x21, 0xc0, 0xc3 },
2659 { { 0x0f, 0x21, 0xc8, 0xc3 },
2661 { { 0x0f, 0x21, 0xf8, 0xc3 },
2664 { { 0x0f, 0x23, 0xc0, 0xc3 },
2666 { { 0x0f, 0x23, 0xc8, 0xc3 },
2668 { { 0x0f, 0x23, 0xf8, 0xc3 },
2672 { { 0xa1, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2674 { { 0xa1, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2677 { { 0xa1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2679 { { 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2683 { { 0xa3, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2685 { { 0xa3, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2687 { { 0xa3, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2690 { { 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3 },
2737 { { 0xf1, 0x90, 0xc3 },
2739 { { 0xcd, 0x2c, 0xc3 },
2741 { { 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
2742 0xcd, 0x2d, 0xfa, 0xc3 },
2745 { { 0xb8, 0x01, 0x00, 0x00, 0x00,
2746 0xcd, 0x2d, 0xfa, 0xc3 },
2752static void run_exception_test_flags(
void *
handler,
const void*
context,
2753 const void *
code,
unsigned int code_size,
2756 unsigned char buf[2 + 8 + 2 + 8 + 8];
2757 RUNTIME_FUNCTION runtime_func;
2760 DWORD oldaccess, oldaccess2;
2762 runtime_func.BeginAddress = 0;
2763 runtime_func.EndAddress = code_size;
2764 runtime_func.UnwindData = 0x1000;
2767 unwind->
Flags = handler_flags;
2790 pRtlDeleteFunctionTable(&runtime_func);
2796static void run_exception_test(
void *
handler,
const void*
context,
2797 const void *
code,
unsigned int code_size,
2807 unsigned int i, parameter_count,
entry =
except - exceptions;
2825#if defined(__REACTOS__) && defined(_MSC_VER)
2832 __asm__ volatile(
"movw %%ds,%0" :
"=g" (
ds) );
2833 __asm__ volatile(
"movw %%es,%0" :
"=g" (
es) );
2834 __asm__ volatile(
"movw %%fs,%0" :
"=g" (
fs) );
2835 __asm__ volatile(
"movw %%gs,%0" :
"=g" (
gs) );
2836 __asm__ volatile(
"movw %%ss,%0" :
"=g" (
ss) );
2844 "ds %#x does not match ss %#x\n",
context->SegDs,
context->SegSs );
2846 "es %#x does not match ss %#x\n",
context->SegEs,
context->SegSs );
2848 "gs %#x does not match ss %#x\n",
context->SegGs,
context->SegSs );
2850 "got fs %#x\n",
context->SegFs );
2855 parameter_count = 1;
2857 parameter_count =
except->nb_params;
2859 parameter_count =
except->alt_nb_params;
2862 "Unexpected parameter count %lu/%u\n", rec->
NumberParameters, parameter_count );
2866 if (
except->nb_params == 2 &&
except->params[1] >= 0xfffffffffffffffd)
2884 "Wrong parameter %d: %Ix/%Ix\n",
2891 "Wrong parameter %d: %Ix/%Ix\n",
2902static const BYTE segfault_code[5] =
2917 const struct dbgreg_test *
test = *(
const struct dbgreg_test **)dispatcher->
HandlerData;
2929#define CHECK_DEBUG_REG(n, m) \
2930 ok((ctx.Dr##n & m) == test->dr##n, "(%d) failed to set debug register " #n " to %p, got %p\n", \
2931 test_num, (void *)test->dr##n, (void *)ctx.Dr##n)
2933static int check_debug_registers(
int test_num,
const struct dbgreg_test *
test)
2944 win_skip(
"debug registers broken\n" );
2947 CHECK_DEBUG_REG(0, ~0);
2948 CHECK_DEBUG_REG(1, ~0);
2949 CHECK_DEBUG_REG(2, ~0);
2950 CHECK_DEBUG_REG(3, ~0);
2951 CHECK_DEBUG_REG(6, 0x0f);
2952 CHECK_DEBUG_REG(7, ~0xdc00);
2956static const BYTE single_stepcode[] =
2975 ok (!(
context->EFlags & 0x100),
"eflags has single stepping bit set\n");
2983 "exception is not EXCEPTION_SINGLE_STEP: %lx\n", rec->
ExceptionCode);
2989static const BYTE align_check_code[] =
3010 __asm__ volatile(
"pushfq; andl $~0x40000,(%rsp); popfq" );
3012 ok (
context->EFlags & 0x40000,
"eflags has AC bit unset\n");
3016 ok(
broken(1) ,
"exception should occur only once");
3023static const BYTE direction_flag_code[] =
3037 if (
flags & 0x400)
trace(
"eflags has DF bit set\n" );
3039 ok(
context->EFlags & 0x400,
"context eflags has DF bit cleared\n" );
3047static const BYTE dummy_code[] = { 0x90, 0x90, 0x90, 0xc3 };
3060 ok( (
context->Dr6 & 0xf) == 1,
"B0 flag is not set in Dr6\n");
3061 ok( !(
context->Dr6 & 0x4000),
"BS flag is set in Dr6\n");
3066 ok( (
char *)
context->Rip == (
char *)
code_mem + 1,
"rip is wrong: %p instead of %p\n",
3068 ok( (
context->Dr6 & 0x4000),
"BS flag is not set in Dr6\n");
3072 ok( (
void *)
context->Rip == (
char *)
code_mem + 1,
"rip is wrong: %p instead of %p\n",
3074 ok( (
context->Dr6 & 0xf) == 1,
"B0 flag is not set in Dr6\n");
3075 ok( !(
context->Dr6 & 0x4000),
"BS flag is set in Dr6\n");
3080 ok( (
void *)
context->Rip == (
char *)
code_mem + 2,
"rip is wrong: %p instead of %p\n",
3082 ok( (
context->Dr6 & 0xf) == 0,
"B0...3 flags in Dr6 shouldn't be set\n");
3083 ok( (
context->Dr6 & 0x4000),
"BS flag is not set in Dr6\n");
3091static const BYTE int3_code[] = { 0xcc, 0xc3 };
3107 printf(
"%04lx unhandled exception %08lx at %p rip %p eflags %lx\n",
3115static void test_exceptions(
void)
3119 struct dbgreg_test dreg_test;
3122 memset(&dreg_test, 0,
sizeof(dreg_test));
3124 dreg_test.dr0 = 0x42424240;
3125 dreg_test.dr2 = 0x126bb070;
3126 dreg_test.dr3 = 0x0badbad0;
3127 dreg_test.dr7 = 0xffff0115;
3128 run_exception_test(dreg_handler, &dreg_test, &segfault_code,
sizeof(segfault_code), 0);
3129 if (check_debug_registers(1, &dreg_test))
3131 dreg_test.dr0 = 0x42424242;
3132 dreg_test.dr2 = 0x100f0fe7;
3133 dreg_test.dr3 = 0x0abebabe;
3134 dreg_test.dr7 = 0x115;
3135 run_exception_test(dreg_handler, &dreg_test, &segfault_code,
sizeof(segfault_code), 0);
3136 check_debug_registers(2, &dreg_test);
3147 run_exception_test(bpx_handler,
NULL, dummy_code,
sizeof(dummy_code), 0);
3151#if defined(__REACTOS__)
3154 skip(
"Skipping tests that crash\n");
3162 run_exception_test(single_step_handler,
NULL, &single_stepcode,
sizeof(single_stepcode), 0);
3167 run_exception_test(align_check_handler,
NULL, align_check_code,
sizeof(align_check_code), 0);
3173 run_exception_test(direction_flag_handler,
NULL, direction_flag_code,
sizeof(direction_flag_code), 0);
3176#if defined(__REACTOS__ ) && defined(_MSC_VER)
3184 run_exception_test(int3_handler,
NULL, int3_code,
sizeof(int3_code), 0);
3194#if defined(__REACTOS__) && defined(_MSC_VER)
3201 __asm__ volatile(
"movw %%ds,%0" :
"=g" (
ds) );
3202 __asm__ volatile(
"movw %%es,%0" :
"=g" (
es) );
3203 __asm__ volatile(
"movw %%fs,%0" :
"=g" (
fs) );
3204 __asm__ volatile(
"movw %%gs,%0" :
"=g" (
gs) );
3205 __asm__ volatile(
"movw %%ss,%0" :
"=g" (
ss) );
3207 ok(
ctx.SegDs ==
ds,
"wrong ds %04x / %04x\n",
ctx.SegDs,
ds );
3208 ok(
ctx.SegEs ==
es,
"wrong es %04x / %04x\n",
ctx.SegEs,
es );
3209 ok(
ctx.SegFs ==
fs,
"wrong fs %04x / %04x\n",
ctx.SegFs,
fs );
3210 ok(
ctx.SegGs ==
gs || !
gs,
"wrong gs %04x / %04x\n",
ctx.SegGs,
gs );
3211 ok(
ctx.SegSs ==
ss,
"wrong ss %04x / %04x\n",
ctx.SegSs,
ss );
3212 ok(
ctx.SegDs ==
ctx.SegSs,
"wrong ds %04x / %04x\n",
ctx.SegDs,
ctx.SegSs );
3213 ok(
ctx.SegEs ==
ctx.SegSs,
"wrong es %04x / %04x\n",
ctx.SegEs,
ctx.SegSs );
3214 ok(
ctx.SegFs !=
ctx.SegSs,
"wrong fs %04x / %04x\n",
ctx.SegFs,
ctx.SegSs );
3215 ok(
ctx.SegGs ==
ctx.SegSs,
"wrong gs %04x / %04x\n",
ctx.SegGs,
ctx.SegSs );
3221#if defined(__REACTOS__) && defined(_MSC_VER)
3228 __asm__ volatile(
"movw %%ds,%0" :
"=g" (
ds) );
3229 __asm__ volatile(
"movw %%es,%0" :
"=g" (
es) );
3230 __asm__ volatile(
"movw %%fs,%0" :
"=g" (
fs) );
3231 __asm__ volatile(
"movw %%gs,%0" :
"=g" (
gs) );
3232 __asm__ volatile(
"movw %%ss,%0" :
"=g" (
ss) );
3236 ok(
ctx.SegDs ==
ds,
"wrong ds %04x / %04x\n",
ctx.SegDs,
ds );
3237 ok(
ctx.SegEs ==
es,
"wrong es %04x / %04x\n",
ctx.SegEs,
es );
3238 ok(
ctx.SegFs ==
fs,
"wrong fs %04x / %04x\n",
ctx.SegFs,
fs );
3239 ok(
ctx.SegGs ==
gs || !
gs,
"wrong gs %04x / %04x\n",
ctx.SegGs,
gs );
3240 ok(
ctx.SegSs ==
ss,
"wrong ss %04x / %04x\n",
ctx.SegSs,
ss );
3241 ok(
ctx.SegDs ==
ctx.SegSs,
"wrong ds %04x / %04x\n",
ctx.SegDs,
ctx.SegSs );
3242 ok(
ctx.SegEs ==
ctx.SegSs,
"wrong es %04x / %04x\n",
ctx.SegEs,
ctx.SegSs );
3243 ok(
ctx.SegFs !=
ctx.SegSs,
"wrong fs %04x / %04x\n",
ctx.SegFs,
ctx.SegSs );
3244 ok(
ctx.SegGs ==
ctx.SegSs,
"wrong gs %04x / %04x\n",
ctx.SegGs,
ctx.SegSs );
3262 else if (*stage == 2 || *stage == 3 )
3267 skip(
"system doesn't support SIMD exceptions\n");
3281 ok(
FALSE,
"unexpected stage %x\n", *stage);
3286static const BYTE simd_exception_test[] =
3288 0x48, 0x83, 0xec, 0x8,
3289 0x0f, 0xae, 0x1c, 0x24,
3291 0x66, 0x81, 0x24, 0x24, 0xff, 0xfd,
3292 0x0f, 0xae, 0x14, 0x24,
3293 0xb9, 0x01, 0x00, 0x00, 0x00,
3294 0x66, 0x48, 0x0f, 0x6e, 0xc9,
3298 0x0f, 0xae, 0x14, 0x24,
3299 0x48, 0x83, 0xc4, 0x08,
3303static const BYTE simd_exception_test2[] =
3305 0x48, 0x83, 0xec, 0x8,
3306 0x0f, 0xae, 0x1c, 0x24,
3308 0x66, 0x81, 0x24, 0x24, 0x7f, 0xff,
3309 0x0f, 0xae, 0x14, 0x24,
3314 0x0f, 0xae, 0x14, 0x24,
3315 0x48, 0x83, 0xc4, 0x08,
3319static const BYTE sse_check[] =
3325static void test_simd_exceptions(
void)
3332 run_exception_test(simd_fault_handler, &stage, sse_check,
sizeof(sse_check), 0);
3334 skip(
"system doesn't support SSE\n");
3341 run_exception_test(simd_fault_handler, &stage, simd_exception_test,
3342 sizeof(simd_exception_test), 0);
3348 run_exception_test(simd_fault_handler, &stage, simd_exception_test2,
3349 sizeof(simd_exception_test2), 0);
3353static void test_prot_fault(
void)
3360 run_exception_test(prot_fault_handler, &exceptions[
i], &exceptions[
i].
code,
3361 sizeof(exceptions[
i].
code), 0);
3387static void test_dpe_exceptions(
void)
3389 static const BYTE ret[] = {0xc3};
3402 "wrong val %08lx\n",
val );
3404 else ok(
len == 0xdeadbeef,
"wrong len %lu\n",
len );
3412 handler = pRtlAddVectoredExceptionHandler(
TRUE, &dpe_handler);
3413 ok(!!
handler,
"RtlAddVectoredExceptionHandler failed\n");
3431 pRtlRemoveVectoredExceptionHandler(
handler);
3434static const BYTE call_one_arg_code[] = {
3435 0x48, 0x83, 0xec, 0x28,
3443 0x48, 0x83, 0xc4, 0x28,
3447static int rtlraiseexception_unhandled_handler_called;
3448static int rtlraiseexception_teb_handler_called;
3449static int rtlraiseexception_handler_called;
3452 void *dispatcher,
BOOL unhandled_handler )
3456 trace(
"exception: %08lx flags:%lx addr:%p context: Rip:%p\n",
3462 "ExceptionAddress not in entry thunk %p (ntdll+%Ix)\n",
3465 "wrong context flags %lx\n",
context->ContextFlags );
3470 "ExceptionAddress at %p instead of %p\n",
addr, (
char *)
code_mem + 0x0c );
3474 "wrong context flags %lx\n",
context->ContextFlags );
3494 rtlraiseexception_unhandled_handler_called = 1;
3510 rtlraiseexception_teb_handler_called = 1;
3511 rtlraiseexception_handler_(rec, frame,
context, dispatcher,
FALSE);
3526 "wrong non volatile reg x19 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[0], ec_ctx->X19 );
3528 "wrong non volatile reg x20 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[1], ec_ctx->X20 );
3530 "wrong non volatile reg x21 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[2], ec_ctx->X21 );
3532 "wrong non volatile reg x22 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[3], ec_ctx->X22 );
3533 ok( nonvol_regs->
GpNvRegs[4] == 0,
"wrong non volatile reg x23 %I64x\n", nonvol_regs->
GpNvRegs[4] );
3534 ok( nonvol_regs->
GpNvRegs[5] == 0,
"wrong non volatile reg x24 %I64x\n", nonvol_regs->
GpNvRegs[5] );
3536 "wrong non volatile reg x25 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[6], ec_ctx->X25 );
3538 "wrong non volatile reg x26 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[7], ec_ctx->X26 );
3540 "wrong non volatile reg x27 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[8], ec_ctx->X27 );
3541 ok( nonvol_regs->
GpNvRegs[9] == 0,
"wrong non volatile reg x28 %I64x\n", nonvol_regs->
GpNvRegs[9] );
3543 "wrong non volatile reg x29 %I64x / %I64x\n", nonvol_regs->
GpNvRegs[10], ec_ctx->Fp );
3547 "wrong non volatile reg d%u %g / %g\n",
i + 8,
3548 nonvol_regs->
FpNvRegs[
i] , ec_ctx->V[
i + 8].D[0] );
3550 rtlraiseexception_handler_called = 1;
3551 rtlraiseexception_handler_(rec, frame,
context, dispatcher,
FALSE);
3563 "ExceptionAddress not in entry thunk %p (ntdll+%Ix)\n",
3567 "ExceptionAddress at %p instead of %p\n",
addr, (
char *)
code_mem + 0xc );
3585static void run_rtlraiseexception_test(
DWORD exceptioncode)
3587 unsigned char buf[4 + 4 + 4 + 8 + 2 + 8 + 2];
3588 RUNTIME_FUNCTION runtime_func;
3596 record.ExceptionCode = exceptioncode;
3597 record.ExceptionFlags = 0;
3600 record.NumberParameters = 0;
3602 runtime_func.BeginAddress = 0;
3603 runtime_func.EndAddress =
sizeof(call_one_arg_code);
3604 runtime_func.UnwindData = 0x1000;
3607 unwind->
Flags = UNW_FLAG_EHANDLER;
3614 *(
const void **)&
buf[12] =
NULL;
3618 *(
void **)&
buf[22] = rtlraiseexception_handler;
3626 frame.
Handler = rtlraiseexception_teb_handler;
3634 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, rtlraiseexception_vectored_handler);
3635 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
3637 if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(rtlraiseexception_unhandled_handler);
3639 rtlraiseexception_handler_called = 0;
3640 rtlraiseexception_teb_handler_called = 0;
3641 rtlraiseexception_unhandled_handler_called = 0;
3645 "ExceptionAddress not in entry thunk %p (ntdll+%Ix)\n",
3649 "address set to %p instead of %p\n",
record.ExceptionAddress, (
char *)
code_mem + 0x0c );
3652 ok( !rtlraiseexception_teb_handler_called,
"Frame TEB handler called\n" );
3653 ok( rtlraiseexception_handler_called,
"Frame handler called\n" );
3654 ok( rtlraiseexception_unhandled_handler_called,
"UnhandledExceptionFilter wasn't called\n" );
3657 pRtlRemoveVectoredExceptionHandler(vectored_handler);
3659 if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(
NULL);
3660 pRtlDeleteFunctionTable( &runtime_func );
3664static void test_rtlraiseexception(
void)
3666#if defined(__REACTOS__)
3669 skip(
"Skipping tests that crash\n");
3673 if (!pRtlRaiseException)
3675 skip(
"RtlRaiseException not found\n");
3680 run_rtlraiseexception_test(0x12345);
3691 DWORD continuestatus;
3699 if(!pNtGetContextThread || !pNtSetContextThread || !pNtReadVirtualMemory || !pNtTerminateProcess)
3701 skip(
"NtGetContextThread, NtSetContextThread, NtReadVirtualMemory or NtTerminateProcess not found\n");
3705 if (with_WaitForDebugEventEx && !pWaitForDebugEventEx)
3707 skip(
"WaitForDebugEventEx not found, skipping unicode strings in OutputDebugStringW\n");
3719 continuestatus = cont_status;
3721 ok(
ret,
"reading debug event\n");
3724 ok(!
ret,
"ContinueDebugEvent unexpectedly succeeded\n");
3738 skip(
"child process loaded at different address, terminating it\n");
3749 sizeof(code_mem_address), &size_read);
3752 sizeof(stage), &size_read);
3760 trace(
"exception 0x%lx at %p firstchance=%ld Rip=%p, Rax=%p\n",
3767 ok(
FALSE,
"got way too many exceptions, probably caught in an infinite loop, terminating child\n");
3777 "wrong rip %p ntdll %p-%p\n", (
void *)
ctx.Rip,
hntdll,
3779 check_context_exception_request(
ctx.ContextFlags,
TRUE );
3787 "Rip not in entry thunk %p (ntdll+%Ix)\n",
3790 ok((
char *)
ctx.Rip == (
char *)code_mem_address + 0x0c,
"Rip at %p instead of %p\n",
3791 (
char *)
ctx.Rip, (
char *)code_mem_address + 0x0c);
3795 ctx.Rax = 0xf00f00f1;
3798 check_context_exception_request(
ctx.ContextFlags,
FALSE );
3806 "Rip not in entry thunk %p (ntdll+%Ix)\n",
3809 ok((
char *)
ctx.Rip == (
char *)code_mem_address + 0x0c,
3810 "Rip at %p instead of %p\n",
3811 (
char *)
ctx.Rip, (
char *)code_mem_address + 0x0c);
3815 ctx.Rax = 0xf00f00f1;
3825 "Rip not in entry thunk %p (ntdll+%Ix)\n",
3829 ok((
char *)
ctx.Rip == (
char *)code_mem_address + 0xb,
"Rip at %p instead of %p\n",
3830 (
char *)
ctx.Rip, (
char *)code_mem_address + 0xb);
3833 else ok((
char *)
ctx.Rip == (
char *)code_mem_address + 0x0c,
"Rip at 0x%I64x instead of %p\n",
3834 ctx.Rip, (
char *)code_mem_address + 0x0c);
3837 check_context_exception_request(
ctx.ContextFlags,
FALSE );
3843 ok((
char *)
ctx.Rip == (
char *)code_mem_address + 0x30,
3844 "expected Rip = %p, got %p\n", (
char *)code_mem_address + 0x30, (
char *)
ctx.Rip);
3846 check_context_exception_request(
ctx.ContextFlags,
TRUE );
3852 ok((
char *)
ctx.Rip == (
char *)code_mem_address + 2,
3853 "expected Rip = %p, got %p\n", (
char *)code_mem_address + 2, (
char *)
ctx.Rip);
3855 check_context_exception_request(
ctx.ContextFlags,
TRUE );
3866 check_context_exception_request(
ctx.ContextFlags,
FALSE );
3872 check_context_exception_request(
ctx.ContextFlags,
FALSE );
3876 check_context_exception_request(
ctx.ContextFlags,
TRUE );
3883#elif defined(__REACTOS__) && defined(_MSC_VER)
3889 ok(
ctx.SegSs ==
ss,
"wrong ss %04x / %04x\n",
ctx.SegSs,
ss );
3890 ok(
ctx.SegDs ==
ctx.SegSs,
"wrong ds %04x / %04x\n",
ctx.SegDs,
ctx.SegSs );
3891 ok(
ctx.SegEs ==
ctx.SegSs,
"wrong es %04x / %04x\n",
ctx.SegEs,
ctx.SegSs );
3892 ok(
ctx.SegFs !=
ctx.SegSs,
"wrong fs %04x / %04x\n",
ctx.SegFs,
ctx.SegSs );
3893 ok(
ctx.SegGs ==
ctx.SegSs,
"wrong gs %04x / %04x\n",
ctx.SegGs,
ctx.SegSs );
3903 ok(
ctx.SegDs ==
ctx.SegSs,
"wrong ds %04x / %04x\n",
ctx.SegDs,
ctx.SegSs );
3904 ok(
ctx.SegEs ==
ctx.SegSs,
"wrong es %04x / %04x\n",
ctx.SegEs,
ctx.SegSs );
3906 ok(
ctx.SegGs ==
ctx.SegSs,
"wrong gs %04x / %04x\n",
ctx.SegGs,
ctx.SegSs );
3907 check_context_exception_request(
ctx.ContextFlags,
TRUE );
3910 ok(
FALSE,
"unexpected stage %u\n", stage);
3923 sizeof(stage), &size_read);
3927 ok(with_WaitForDebugEventEx &&
3929 "unexpected unicode debug string event\n");
3932 "unexpected ansi debug string event %u %s %lx\n",
3933 stage, with_WaitForDebugEventEx ?
"with" :
"without", cont_status);
3962 sizeof(stage), &size_read);
3967 ok(de.
u.
RipInfo.
dwError == 0x11223344,
"got unexpected rip error code %08lx, expected %08x\n",
3969 ok(de.
u.
RipInfo.
dwType == 0x55667788,
"got unexpected rip type %08lx, expected %08x\n",
3973 ok(
FALSE,
"unexpected stage %x\n", stage);
3989static void test_thread_context(
void)
3996 ULONG64 Rax, Rbx, Rcx, Rdx, Rsi, Rdi,
R8,
R9,
R10,
R11,
4000 WORD SegCs, SegDs, SegEs, SegFs, SegGs, SegSs;
4004 static const BYTE call_func[] =
4008 0x48, 0x8d, 0x64, 0x24, 0xd0,
4010 0x49, 0x89, 0x58, 0x08,
4011 0x49, 0x89, 0x48, 0x10,
4012 0x49, 0x89, 0x50, 0x18,
4013 0x49, 0x89, 0x70, 0x20,
4014 0x49, 0x89, 0x78, 0x28,
4015 0x4d, 0x89, 0x40, 0x30,
4016 0x4d, 0x89, 0x48, 0x38,
4017 0x4d, 0x89, 0x50, 0x40,
4018 0x4d, 0x89, 0x58, 0x48,
4019 0x4d, 0x89, 0x60, 0x50,
4020 0x4d, 0x89, 0x68, 0x58,
4021 0x4d, 0x89, 0x70, 0x60,
4022 0x4d, 0x89, 0x78, 0x68,
4023 0x49, 0x89, 0x68, 0x70,
4024 0x49, 0x89, 0x60, 0x78,
4026 0x41, 0x8f, 0x80, 0x80, 0x00, 0x00, 0x00,
4028 0x41, 0x8f, 0x80, 0x88, 0x00, 0x00, 0x00,
4030 0x41, 0x8f, 0x80, 0x90, 0x00, 0x00, 0x00,
4031 0x41, 0x0f, 0xae, 0x98, 0x98, 0x00, 0x00, 0x00,
4032 0x41, 0x0f, 0xae, 0x80, 0xa0, 0x00, 0x00, 0x00,
4033 0x66, 0x41, 0x0f, 0x7f, 0x80, 0x40, 0x01, 0x00, 0x00,
4034 0x66, 0x41, 0x0f, 0x7f, 0x88, 0x50, 0x01, 0x00, 0x00,
4035 0x66, 0x41, 0x0f, 0x7f, 0x90, 0x60, 0x01, 0x00, 0x00,
4036 0x66, 0x41, 0x0f, 0x7f, 0x98, 0x70, 0x01, 0x00, 0x00,
4037 0x66, 0x41, 0x0f, 0x7f, 0xa0, 0x80, 0x01, 0x00, 0x00,
4038 0x66, 0x41, 0x0f, 0x7f, 0xa8, 0x90, 0x01, 0x00, 0x00,
4039 0x66, 0x41, 0x0f, 0x7f, 0xb0, 0xa0, 0x01, 0x00, 0x00,
4040 0x66, 0x41, 0x0f, 0x7f, 0xb8, 0xb0, 0x01, 0x00, 0x00,
4041 0x66, 0x45, 0x0f, 0x7f, 0x80, 0xc0, 0x01, 0x00, 0x00,
4042 0x66, 0x45, 0x0f, 0x7f, 0x88, 0xd0, 0x01, 0x00, 0x00,
4043 0x66, 0x45, 0x0f, 0x7f, 0x90, 0xe0, 0x01, 0x00, 0x00,
4044 0x66, 0x45, 0x0f, 0x7f, 0x98, 0xf0, 0x01, 0x00, 0x00,
4045 0x66, 0x45, 0x0f, 0x7f, 0xa0, 0x00, 0x02, 0x00, 0x00,
4046 0x66, 0x45, 0x0f, 0x7f, 0xa8, 0x10, 0x02, 0x00, 0x00,
4047 0x66, 0x45, 0x0f, 0x7f, 0xb0, 0x20, 0x02, 0x00, 0x00,
4048 0x66, 0x45, 0x0f, 0x7f, 0xb8, 0x30, 0x02, 0x00, 0x00,
4049 0x41, 0x8c, 0x88, 0xa0, 0x02, 0x00, 0x00,
4050 0x41, 0x8c, 0x98, 0xa2, 0x02, 0x00, 0x00,
4051 0x41, 0x8c, 0x80, 0xa4, 0x02, 0x00, 0x00,
4052 0x41, 0x8c, 0xa0, 0xa6, 0x02, 0x00, 0x00,
4053 0x41, 0x8c, 0xa8, 0xa8, 0x02, 0x00, 0x00,
4054 0x41, 0x8c, 0x90, 0xaa, 0x02, 0x00, 0x00,
4062#define COMPARE(reg) \
4063 ok( context.reg == expect.reg, "wrong " #reg " %p/%p\n", (void *)(ULONG64)context.reg, (void *)(ULONG64)expect.reg )
4072 "wrong flags %08lx\n",
context.ContextFlags );
4073 ok( (
context.EFlags & ~0xd5) == (
expect.EFlags & ~0xd5),
"wrong EFlags %lx / %I64x\n",
4085 "wrong flags %08lx\n",
context.ContextFlags );
4101 "wrong FltSave\n" );
4113 COMPARE( FltSave.MxCsr );
4114 COMPARE( FltSave.ControlWord );
4115 COMPARE( FltSave.StatusWord );
4116 for (
i = 0;
i < 16;
i++)
4118 "wrong xmm%u\n",
i );
4121 "wrong Rip %p/%p\n", (
void *)
context.Rip, (
char *)
func_ptr +
sizeof(call_func) - 2 );
4134 "wrong Rsp %p/%p\n", (
void *)
context.Rsp, (
void *)
expect.Rsp );
4149 "wrong Rsp %p/%p\n", (
void *)
context.Rsp, (
void *)
expect.Rsp );
4151 ok( (
char *)
context.Rip >= (
char *)pNtGetContextThread - 0x40000 &&
4152 (
char *)
context.Rip <= (
char *)pNtGetContextThread + 0x40000,
4153 "wrong Rip %p/%p\n", (
void *)
context.Rip, (
void *)pNtGetContextThread );
4160 if (
expect.SegGs) COMPARE( SegGs );
4169 for (
i = 6;
i < 16;
i++)
4171 "wrong xmm%u\n",
i );
4175static void test_continue(
void)
4177 struct context_pair {
4185 static const BYTE call_func[] =
4199 0x48, 0x83, 0xec, 0x28,
4200 0x48, 0x89, 0x64, 0x24, 0x20,
4203 0x48, 0x89, 0x4c, 0x24, 0x70,
4204 0x48, 0x89, 0x54, 0x24, 0x78,
4205 0x4c, 0x89, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00,
4206 0x4c, 0x89, 0x8c, 0x24, 0x88, 0x00, 0x00, 0x00,
4212 0x48, 0xb8, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde,
4229 0x66, 0x48, 0x0f, 0x6e, 0xc0,
4230 0x66, 0x0f, 0x6c, 0xc0,
4238 0x44, 0x0f, 0x28, 0xc0,
4239 0x44, 0x0f, 0x28, 0xc8,
4240 0x44, 0x0f, 0x28, 0xd0,
4241 0x44, 0x0f, 0x28, 0xd8,
4242 0x44, 0x0f, 0x28, 0xe0,
4243 0x44, 0x0f, 0x28, 0xe8,
4244 0x44, 0x0f, 0x28, 0xf0,
4245 0x44, 0x0f, 0x28, 0xf8,
4250 0x48, 0x8b, 0x4c, 0x24, 0x70,
4251 0x48, 0x8b, 0x54, 0x24, 0x78,
4252 0x48, 0x83, 0xec, 0x70,
4255 0x48, 0x8d, 0x05, 0x18, 0x00, 0x00, 0x00,
4256 0x48, 0x89, 0x81, 0xf8, 0x00, 0x00, 0x00,
4271 0x48, 0x81, 0x34, 0x24, 0xd5, 0x08, 0x00, 0x00,
4275 0xff, 0x94, 0x24, 0xf0, 0x00, 0x00, 0x00,
4278 0x48, 0x3b, 0x64, 0x24, 0x20,
4283 0x48, 0x8b, 0x4c, 0x24, 0x70,
4284 0x48, 0x81, 0xc1, 0xd0, 0x04, 0x00, 0x00,
4285 0xff, 0x94, 0x24, 0x88, 0x00, 0x00, 0x00,
4288 0x48, 0x83, 0xc4, 0x28,
4302 if (!pRtlCaptureContext)
4304 win_skip(
"RtlCaptureContext is not available.\n");
4313#define COMPARE(reg) \
4314 ok( contexts.before.reg == contexts.after.reg, "wrong " #reg " %p/%p\n", (void *)(ULONG64)contexts.before.reg, (void *)(ULONG64)contexts.after.reg )
4331 for (
i = 0;
i < 16;
i++)
4332 ok( !
memcmp( &contexts.before.Xmm0 +
i, &contexts.after.Xmm0 +
i,
sizeof(contexts.before.Xmm0) ),
4333 "wrong xmm%u %08I64x%08I64x/%08I64x%08I64x\n",
i, *(&contexts.before.Xmm0.High +
i*2), *(&contexts.before.Xmm0.Low +
i*2),
4334 *(&contexts.after.Xmm0.High +
i*2), *(&contexts.after.Xmm0.Low +
i*2) );
4345 win_skip(
"NtContinueEx not supported\n" );
4349 func_ptr( &contexts, &
args, pNtContinueEx, pRtlCaptureContext );
4351#define COMPARE(reg) \
4352 ok( contexts.before.reg == contexts.after.reg, "wrong " #reg " %p/%p\n", (void *)(ULONG64)contexts.before.reg, (void *)(ULONG64)contexts.after.reg )
4369 for (
i = 0;
i < 16;
i++)
4370 ok( !
memcmp( &contexts.before.Xmm0 +
i, &contexts.after.Xmm0 +
i,
sizeof(contexts.before.Xmm0) ),
4371 "wrong xmm%u %08I64x%08I64x/%08I64x%08I64x\n",
i, *(&contexts.before.Xmm0.High +
i*2), *(&contexts.before.Xmm0.Low +
i*2),
4372 *(&contexts.after.Xmm0.High +
i*2), *(&contexts.after.Xmm0.Low +
i*2) );
4375 func_ptr( &contexts, &
args, pNtContinueEx, pRtlCaptureContext );
4378 func_ptr( &contexts, &
args, pNtContinueEx, pRtlCaptureContext );
4384static void test_wow64_context(
void)
4386 const char appname[] =
"C:\\windows\\syswow64\\cmd.exe";
4399 BOOL r, got32, got64;
4400 unsigned int i, cs32, cs64;
4404 if ((pRtlWow64GetThreadContext ==
NULL) ||
4405 (pRtlWow64SetThreadContext ==
NULL))
4407 skip(
"RtlWow64Get/SetThreadContext not found\n");
4417 sprintf(
cmdline,
"\"%s\" /c for /l %%n in () do @echo >nul", appname );
4424 ok(!
ctx.Ebp,
"got ebp %08lx\n",
ctx.Ebp);
4425 ok(!
ctx.Ecx,
"got ecx %08lx\n",
ctx.Ecx);
4426 ok(!
ctx.Edx,
"got edx %08lx\n",
ctx.Edx);
4427 ok(!
ctx.Esi,
"got esi %08lx\n",
ctx.Esi);
4428 ok(!
ctx.Edi,
"got edi %08lx\n",
ctx.Edi);
4429 ok((
ctx.EFlags & ~2) == 0x200,
"got eflags %08lx\n",
ctx.EFlags);
4430 ok((
WORD)
ctx.FloatSave.ControlWord == 0x27f,
"got control word %08lx\n",
4431 ctx.FloatSave.ControlWord);
4432 ok(*(
WORD *)
ctx.ExtendedRegisters == 0x27f,
"got SSE control word %04x\n",
4433 *(
WORD *)
ctx.ExtendedRegisters);
4440 ok(
res ==
sizeof(teb),
"wrong len %Ix\n",
res );
4442 memset( &teb32, 0,
sizeof(teb32) );
4446 &teb32,
sizeof(teb32), &
res ))
res = 0;
4447 ok(
res ==
sizeof(teb32),
"wrong len %Ix\n",
res );
4450 "esp is not at top of stack: %08lx / %08lx\n",
ctx.Esp, teb32.
Tib.
StackBase );
4457 if (pRtlWow64GetCpuAreaInfo)
4464 ok(
res == cpu_size,
"wrong len %Ix\n",
res );
4466 ret = pRtlWow64GetCpuAreaInfo(
cpu, 0, &cpu_info );
4467 ok( !
ret,
"RtlWow64GetCpuAreaInfo failed %lx\n",
ret );
4477 ok(ctx_ptr->
Eax ==
ctx.Eax,
"got eax %08lx / %08lx\n", ctx_ptr->
Eax,
ctx.Eax);
4478 ok(ctx_ptr->
Ebx ==
ctx.Ebx,
"got ebx %08lx / %08lx\n", ctx_ptr->
Ebx,
ctx.Ebx);
4479 ok(ctx_ptr->
Ecx ==
ctx.Ecx,
"got ecx %08lx / %08lx\n", ctx_ptr->
Ecx,
ctx.Ecx);
4480 ok(ctx_ptr->
Edx ==
ctx.Edx,
"got edx %08lx / %08lx\n", ctx_ptr->
Edx,
ctx.Edx);
4481 ok(ctx_ptr->
Ebp ==
ctx.Ebp,
"got ebp %08lx / %08lx\n", ctx_ptr->
Ebp,
ctx.Ebp);
4482 ok(ctx_ptr->
Esi ==
ctx.Esi,
"got esi %08lx / %08lx\n", ctx_ptr->
Esi,
ctx.Esi);
4483 ok(ctx_ptr->
Edi ==
ctx.Edi,
"got edi %08lx / %08lx\n", ctx_ptr->
Edi,
ctx.Edi);
4484 ok(ctx_ptr->
SegCs ==
ctx.SegCs,
"got cs %04lx / %04lx\n", ctx_ptr->
SegCs,
ctx.SegCs);
4485 ok(ctx_ptr->
SegDs ==
ctx.SegDs,
"got ds %04lx / %04lx\n", ctx_ptr->
SegDs,
ctx.SegDs);
4486 ok(ctx_ptr->
SegEs ==
ctx.SegEs,
"got es %04lx / %04lx\n", ctx_ptr->
SegEs,
ctx.SegEs);
4487 ok(ctx_ptr->
SegFs ==
ctx.SegFs,
"got fs %04lx / %04lx\n", ctx_ptr->
SegFs,
ctx.SegFs);
4488 ok(ctx_ptr->
SegGs ==
ctx.SegGs,
"got gs %04lx / %04lx\n", ctx_ptr->
SegGs,
ctx.SegGs);
4489 ok(ctx_ptr->
SegSs ==
ctx.SegSs,
"got ss %04lx / %04lx\n", ctx_ptr->
SegSs,
ctx.SegSs);
4495 *(
WORD *)
ctx.ExtendedRegisters);
4498 ctx.Ecx = 0x12345678;
4502 ok(
res == cpu_size,
"wrong len %Ix\n",
res );
4504 ok( ctx_ptr->
Ecx == 0x12345678,
"got ecx %08lx\n", ctx_ptr->
Ecx );
4508 else win_skip(
"RtlWow64GetCpuAreaInfo not supported\n" );
4515 "got context flags %#lx\n",
context.ContextFlags );
4528 ok(
context.FltSave.ControlWord == 0x27f,
"wrong control %08x\n",
context.FltSave.ControlWord );
4551 for (
i = 0, got32 = got64 =
FALSE;
i < 10000 && !(got32 && got64);
i++)
4561 if (
context.SegCs == cs32 && got32)
continue;
4562 if (
context.SegCs == cs64 && got64)
continue;
4565 ok( 0,
"unexpected cs %04x\n",
context.SegCs );
4581 "got context flags %#lx\n",
ctx.ContextFlags );
4585 "got context flags %#lx\n",
ctx.ContextFlags );
4594 "got %#lx.\n",
ctx.ContextFlags );
4601 "cs32: ecx %08lx / %p\n",
ctx.Ecx, (
void *)
context.Rcx );
4605 ok(
ctx.SegCs == cs32,
"cs32: wrong cs %04lx / %04x\n",
ctx.SegCs, cs32 );
4613 "cs32: esp not inside 32-bit stack %08lx / %08lx-%08lx\n",
ctx.Esp,
4617 "cs32: r12 not pointing to the TEB %p / %p\n", (
void *)
context.R12,
info.TebBaseAddress );
4621 "cs32: r13 not pointing into cpu area %p / %p\n", (
void *)
context.R13,
4625 "cs32: r14 not inside 32-bit stack %p / %p-%p\n", (
void *)
context.R14,
4628 if (pRtlWow64GetCpuAreaInfo)
4633 ok(
res == cpu_size,
"wrong len %Ix\n",
res );
4635 "cs32: got context flags %#lx\n", ctx_ptr->
ContextFlags);
4640 context.Rcx = 0xfedcba987654321ull;
4646 ok(
ctx.Ecx == 0x87654321,
"cs32: ecx set to %08lx\n",
ctx.Ecx );
4648 ok( ctx_ptr->
Ecx == ecx,
"cs32: ecx set to %08lx\n", ctx_ptr->
Ecx );
4649 ctx.Ecx = 0x33334444;
4654 ok(
ctx.Ecx == 0x33334444,
"cs32: ecx set to %08lx\n",
ctx.Ecx );
4656 ok( ctx_ptr->
Ecx == ecx,
"cs32: ecx set to %08lx\n", ctx_ptr->
Ecx );
4661 ok(
context.Rcx == 0x33334444,
"cs32: rcx set to %p\n", (
void *)
context.Rcx );
4676 "got %#lx.\n",
ctx.ContextFlags );
4678 ok(
ctx.SegCs == cs32,
"cs64: wrong cs %04lx / %04x\n",
ctx.SegCs, cs32 );
4689 "cs64: esp not inside 32-bit stack %08lx / %08lx-%08lx\n",
ctx.Esp,
4693 "cs64: rsp not inside stack %p / 64-bit %p-%p 32-bit %p-%p\n", (
void *)
context.Rsp,
4697 if (pRtlWow64GetCpuAreaInfo)
4702 ok(
res == cpu_size,
"wrong len %Ix\n",
res );
4704 "cs64: got context flags %#lx\n", ctx_ptr->
ContextFlags);
4705 ok(ctx_ptr->
Eip ==
ctx.Eip,
"cs64: got eip %08lx / %08lx\n", ctx_ptr->
Eip,
ctx.Eip);
4706 ok(ctx_ptr->
Eax ==
ctx.Eax,
"cs64: got eax %08lx / %08lx\n", ctx_ptr->
Eax,
ctx.Eax);
4707 ok(ctx_ptr->
Ebx ==
ctx.Ebx,
"cs64: got ebx %08lx / %08lx\n", ctx_ptr->
Ebx,
ctx.Ebx);
4708 ok(ctx_ptr->
Ecx ==
ctx.Ecx,
"cs64: got ecx %08lx / %08lx\n", ctx_ptr->
Ecx,
ctx.Ecx);
4709 ok(ctx_ptr->
Edx ==
ctx.Edx,
"cs64: got edx %08lx / %08lx\n", ctx_ptr->
Edx,
ctx.Edx);
4710 ok(ctx_ptr->
Ebp ==
ctx.Ebp,
"cs64: got ebp %08lx / %08lx\n", ctx_ptr->
Ebp,
ctx.Ebp);
4711 ok(ctx_ptr->
Esi ==
ctx.Esi,
"cs64: got esi %08lx / %08lx\n", ctx_ptr->
Esi,
ctx.Esi);
4712 ok(ctx_ptr->
Edi ==
ctx.Edi,
"cs64: got edi %08lx / %08lx\n", ctx_ptr->
Edi,
ctx.Edi);
4713 ok(ctx_ptr->
EFlags ==
ctx.EFlags,
"cs64: got eflags %08lx / %08lx\n", ctx_ptr->
EFlags,
ctx.EFlags);
4718 context.Rcx = 0xfedcba987654321ull;
4723 ok(
ctx.Ecx == ecx,
"cs64: ecx set to %08lx\n",
ctx.Ecx );
4725 ok( ctx_ptr->
Ecx == ecx,
"cs64: ecx set to %08lx\n", ctx_ptr->
Ecx );
4726 ctx.Ecx = 0x22223333;
4731 ok(
ctx.Ecx == 0x22223333,
"cs64: ecx set to %08lx\n",
ctx.Ecx );
4734 ok( ctx_ptr->
Ecx == 0x22223333,
"cs64: ecx set to %08lx\n", ctx_ptr->
Ecx );
4738 ok(
context.Rcx == 0xfedcba987654321ull,
"cs64: rcx set to %p\n", (
void *)
context.Rcx );
4749 if (!got32)
skip(
"failed to test 32-bit context\n" );
4750 if (!got64)
skip(
"failed to test 64-bit context\n" );
4757static BYTE saved_KiUserExceptionDispatcher_bytes[12];
4758static BOOL hook_called;
4759static void *hook_KiUserExceptionDispatcher_rip;
4760static void *dbg_except_continue_handler_rip;
4761static void *hook_exception_address;
4777test_kiuserexceptiondispatcher_regs;
4779static ULONG64 test_kiuserexceptiondispatcher_saved_r12;
4795 dbg_except_continue_handler_rip = (
void *)
context->Rip;
4798 sizeof(saved_KiUserExceptionDispatcher_bytes));
4800 RtlUnwind((
void *)test_kiuserexceptiondispatcher_regs.old_rsp,
4815 ok(
context->P1Home == (
ULONG64)0xdeadbeeffeedcafe,
"Got unexpected context->P1Home %#Ix.\n",
context->P1Home);
4817 context->R12 = test_kiuserexceptiondispatcher_saved_r12;
4824 dbg_except_continue_handler_rip = (
void *)
context->Rip;
4829 RtlUnwind((
void *)test_kiuserexceptiondispatcher_regs.old_rsp,
4837 struct machine_frame *frame = (
struct machine_frame *)(((
ULONG_PTR)(rec + 1) + 0x0f) & ~0x0f);
4840 trace(
"rec %p context %p context->Rip %#Ix, context->Rsp %#Ix, ContextFlags %#lx.\n",
4846 "Got unexpected ExceptionCode %#lx.\n", rec->
ExceptionCode);
4852 win_skip(
"No extended context support.\n");
4861 ok( (
void *)(xctx + 1) == (
void *)rec,
"wrong ptrs %p / %p\n", xctx, rec );
4862 ok( frame->rip ==
context->Rip,
"wrong rip %Ix / %Ix\n", frame->rip,
context->Rip );
4863 ok( frame->rsp ==
context->Rsp,
"wrong rsp %Ix / %Ix\n", frame->rsp,
context->Rsp );
4868 hook_KiUserExceptionDispatcher_rip = (
void *)
context->Rip;
4871 sizeof(saved_KiUserExceptionDispatcher_bytes));
4879 trace(
"rec %p context %p context->Rip %#Ix, context->Rsp %#Ix, ContextFlags %#lx.\n",
4883 "Got unexpected ExceptionCode %#lx.\n", rec->
ExceptionCode);
4886 ok( arm64_context->Pc ==
context->Rip,
"wrong rip %Ix / %Ix\n", arm64_context->Pc,
context->Rip );
4887 ok( arm64_context->Sp ==
context->Rsp,
"wrong rsp %Ix / %Ix\n", arm64_context->Sp,
context->Rsp );
4889 hook_KiUserExceptionDispatcher_rip = (
void *)
context->Rip;
4892 sizeof(saved_KiUserExceptionDispatcher_bytes));
4896static void test_KiUserExceptionDispatcher(
void)
4899 static BYTE except_code[] =
4903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4906 0x48, 0x89, 0x51, 0x08,
4907 0x48, 0x89, 0x71, 0x10,
4908 0x48, 0x89, 0x79, 0x18,
4909 0x48, 0x89, 0x69, 0x20,
4910 0x48, 0x89, 0x61, 0x28,
4911 0x48, 0x83, 0xc1, 0x30,
4921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4924 0x48, 0x89, 0x51, 0x08,
4925 0x48, 0x89, 0x71, 0x10,
4926 0x48, 0x89, 0x79, 0x18,
4927 0x48, 0x89, 0x69, 0x20,
4928 0x48, 0x89, 0x61, 0x28,
4931 static BYTE hook_trampoline[] =
4934 0x48, 0x8d, 0x8c, 0x24, 0xf0, 0x04, 0x00, 0x00,
4944 static BYTE hook_trampoline_arm64ec[] =
4946 0x48, 0x8d, 0x54, 0x24, 0x08,
4947 0x48, 0x8d, 0x8a, 0x60, 0x08, 0x00, 0x00,
4958 BYTE patched_KiUserExceptionDispatcher_bytes[12];
4959 void *bpt_address, *trampoline_ptr;
4967 *(
ULONG64 *)(except_code + 2) = (
ULONG64)&test_kiuserexceptiondispatcher_regs;
4968 *(
ULONG64 *)(except_code + 0x2a) = (
ULONG64)&test_kiuserexceptiondispatcher_regs.new_rax;
4970 *(
ULONG_PTR *)(hook_trampoline_arm64ec + 17) = (
ULONG_PTR)hook_KiUserExceptionDispatcher_arm64ec;
4972 trampoline_ptr = (
char *)
code_mem + 1024;
4974 memcpy(trampoline_ptr, hook_trampoline_arm64ec,
sizeof(hook_trampoline_arm64ec));
4976 memcpy(trampoline_ptr, hook_trampoline,
sizeof(hook_trampoline));
4983 sizeof(saved_KiUserExceptionDispatcher_bytes));
4984 ptr = (
BYTE *)patched_KiUserExceptionDispatcher_bytes;
4988 *(
void **)
ptr = trampoline_ptr;
4995 sizeof(patched_KiUserExceptionDispatcher_bytes));
4997 run_exception_test(dbg_except_continue_handler,
NULL, except_code,
sizeof(except_code),
PAGE_EXECUTE_READ);
5000 ok(hook_called,
"Hook was not called.\n");
5001 if (!hook_called)
return;
5003 ok(test_kiuserexceptiondispatcher_regs.new_rax == 0xdeadbeef,
"Got unexpected rax %#Ix.\n",
5004 test_kiuserexceptiondispatcher_regs.new_rax);
5005 ok(test_kiuserexceptiondispatcher_regs.old_rsi
5006 == test_kiuserexceptiondispatcher_regs.new_rsi,
"rsi does not match.\n");
5007 ok(test_kiuserexceptiondispatcher_regs.old_rdi
5008 == test_kiuserexceptiondispatcher_regs.new_rdi,
"rdi does not match.\n");
5009 ok(test_kiuserexceptiondispatcher_regs.old_rbp
5010 == test_kiuserexceptiondispatcher_regs.new_rbp,
"rbp does not match.\n");
5014 ok(hook_exception_address == bpt_address ||
broken(!hook_exception_address) ,
5015 "Got unexpected exception address %p, expected %p.\n",
5016 hook_exception_address, bpt_address);
5017 ok(hook_KiUserExceptionDispatcher_rip == bpt_address,
"Got unexpected exception address %p, expected %p.\n",
5018 hook_KiUserExceptionDispatcher_rip, bpt_address);
5019 ok(dbg_except_continue_handler_rip == bpt_address,
"Got unexpected exception address %p, expected %p.\n",
5020 dbg_except_continue_handler_rip, bpt_address);
5023 record.ExceptionCode = 0x80000003;
5024 record.ExceptionFlags = 0;
5027 record.NumberParameters = 0;
5029 vectored_handler = AddVectoredExceptionHandler(
TRUE, dbg_except_continue_vectored_handler);
5032 sizeof(patched_KiUserExceptionDispatcher_bytes));
5034 hook_called =
FALSE;
5036 pRtlRaiseException(&
record);
5039 ok(!hook_called,
"Hook was called.\n");
5042 sizeof(patched_KiUserExceptionDispatcher_bytes));
5044 hook_called =
FALSE;
5047 pRtlRaiseException(&
record);
5050 ok(hook_called,
"Hook was not called.\n");
5052 ok(hook_exception_address == (
BYTE *)hook_KiUserExceptionDispatcher_rip + !
is_arm64ec
5053 ||
broken(!hook_exception_address) ,
"Got unexpected addresses %p, %p.\n",
5054 hook_KiUserExceptionDispatcher_rip, hook_exception_address);
5056 RemoveVectoredExceptionHandler(vectored_handler);
5059 sizeof(patched_KiUserExceptionDispatcher_bytes));
5061 hook_called =
FALSE;
5063 run_exception_test(dbg_except_continue_handler,
NULL, except_code,
sizeof(except_code),
PAGE_EXECUTE_READ);
5066 ok(hook_called,
"Hook was not called.\n");
5067 ok(hook_KiUserExceptionDispatcher_rip == bpt_address,
"Got unexpected exception address %p, expected %p.\n",
5068 hook_KiUserExceptionDispatcher_rip, bpt_address);
5069 ok(dbg_except_continue_handler_rip == bpt_address,
"Got unexpected exception address %p, expected %p.\n",
5070 dbg_except_continue_handler_rip, bpt_address);
5072 ok(test_kiuserexceptiondispatcher_regs.new_rax == 0xdeadbeef,
"Got unexpected rax %#Ix.\n",
5073 test_kiuserexceptiondispatcher_regs.new_rax);
5074 ok(test_kiuserexceptiondispatcher_regs.old_rsi
5075 == test_kiuserexceptiondispatcher_regs.new_rsi,
"rsi does not match.\n");
5076 ok(test_kiuserexceptiondispatcher_regs.old_rdi
5077 == test_kiuserexceptiondispatcher_regs.new_rdi,
"rdi does not match.\n");
5078 ok(test_kiuserexceptiondispatcher_regs.old_rbp
5079 == test_kiuserexceptiondispatcher_regs.new_rbp,
"rbp does not match.\n");
5083 vectored_handler = AddVectoredExceptionHandler(
TRUE, dbg_except_continue_vectored_handler);
5086 pRtlCaptureContext(&
ctx);
5090 sizeof(patched_KiUserExceptionDispatcher_bytes));
5092 hook_called =
FALSE;
5094 record.ExceptionCode = 0xceadbeef;
5095 test_kiuserexceptiondispatcher_saved_r12 =
ctx.R12;
5098#if defined(__REACTOS__) && defined(_MSC_VER)
5099 Call_NtRaiseException(&
record, &
ctx,
TRUE, pNtRaiseException);
5103 __asm__ volatile(
"movq $0xdeadcafe, %%r12" : : :
"%r12");
5107 ok(0,
"Shouldn't be reached.\n");
5111 ok(
pass == 3,
"Got unexpected pass %ld.\n",
pass);
5113 ok(hook_called,
"Hook was not called.\n");
5114 RemoveVectoredExceptionHandler(vectored_handler);
5117 old_protect, &old_protect);
5122static BYTE saved_KiUserApcDispatcher[12];
5126 struct machine_frame *frame = (
struct machine_frame *)(
context + 1);
5129 trace(
"context %p, context->Rip %#Ix, context->Rsp %#Ix (%#Ix), ContextFlags %#lx.\n",
5141 for (
i = 0;
i < 16;
i++)
5143 if (frame->rip ==
context->Rip)
break;
5144 frame = (
struct machine_frame *)((
ULONG64 *)frame + 2);
5146 ok( frame->rip ==
context->Rip,
"wrong rip %#Ix / %#Ix\n", frame->rip,
context->Rip );
5147 ok( frame->rsp ==
context->Rsp,
"wrong rsp %#Ix / %#Ix\n", frame->rsp,
context->Rsp );
5154static void test_KiUserApcDispatcher(
void)
5156 BYTE hook_trampoline[] =
5165 BYTE patched_KiUserApcDispatcher[12];
5178 ptr = patched_KiUserApcDispatcher;
5189 hook_called =
FALSE;
5195 ok(
is_arm64ec ? !hook_called : hook_called,
"hook was not called\n" );
5200static void WINAPI hook_KiUserCallbackDispatcher(
void *rsp)
5208 struct machine_frame frame;
5227 if (win32u)
ok(
mod == win32u,
"ret address %Ix not in win32u %p\n",
stack->frame.rip, win32u );
5228 else trace(
"ret address %Ix in %p\n",
stack->frame.rip,
mod );
5233static void test_KiUserCallbackDispatcher(
void)
5235 BYTE hook_trampoline[] =
5243 BYTE saved_KiUserCallbackDispatcher[12];
5244 BYTE patched_KiUserCallbackDispatcher[12];
5257 ptr = patched_KiUserCallbackDispatcher;
5268 DestroyWindow(
CreateWindowA(
"Static",
"test", 0, 0, 0, 0, 0, 0, 0, 0, 0 ));
5274static BOOL got_nested_exception, got_prev_frame_exception;
5275static void *nested_exception_initial_frame;
5280 trace(
"nested_exception_handler Rip %p, Rsp %p, code %#lx, flags %#lx, ExceptionAddress %p.\n",
5287 ok((
void *)
context->Rsp == frame,
"Got unexpected frame %p.\n", frame);
5288 ok(*(
void **)frame == (
char *)
code_mem + 5,
"Got unexpected *frame %p.\n", *(
void **)frame);
5291 nested_exception_initial_frame = frame;
5301 got_nested_exception =
TRUE;
5302 ok(frame == nested_exception_initial_frame,
"Got unexpected frame %p.\n", frame);
5309 ok(frame == (
void *)((
BYTE *)nested_exception_initial_frame + 8),
5310 "Got unexpected frame %p.\n", frame);
5311 got_prev_frame_exception =
TRUE;
5315static const BYTE nested_except_code[] =
5317 0xe8, 0x02, 0x00, 0x00, 0x00,
5326static void test_nested_exception(
void)
5328 got_nested_exception = got_prev_frame_exception =
FALSE;
5329 run_exception_test(nested_exception_handler,
NULL, nested_except_code,
sizeof(nested_except_code),
PAGE_EXECUTE_READ);
5330 ok(got_nested_exception,
"Did not get nested exception.\n");
5331 ok(got_prev_frame_exception,
"Did not get nested exception in the previous frame.\n");
5334static unsigned int collided_unwind_exception_count;
5341 trace(
"collided_exception_handler Rip %p, Rsp %p, code %#lx, flags %#lx, ExceptionAddress %p, frame %p.\n",
5344 switch(collided_unwind_exception_count++)
5349 nested_exception_initial_frame = frame;
5352 ok(0,
"shouldn't be reached\n");
5360 ok(0,
"shouldn't be reached\n");
5366 ok(frame == nested_exception_initial_frame,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
5372 ok((
char *)frame == (
char *)nested_exception_initial_frame + 8,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
5374 ok(0,
"shouldn't be reached\n");
5380 ok(frame == nested_exception_initial_frame,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
5386 ok((
char *)frame == (
char *)nested_exception_initial_frame + 8,
"got %p, expected %p.\n", frame,
5387 (
char *)nested_exception_initial_frame + 8);
5393static void test_collided_unwind(
void)
5395 got_nested_exception = got_prev_frame_exception =
FALSE;
5396 collided_unwind_exception_count = 0;
5397 run_exception_test_flags(collided_exception_handler,
NULL, nested_except_code,
sizeof(nested_except_code),
5399 ok(collided_unwind_exception_count == 6,
"got %u.\n", collided_unwind_exception_count);
5402static CONTEXT test_unwind_apc_context;
5403static BOOL test_unwind_apc_called;
5409 test_unwind_apc_called =
TRUE;
5410 memset(&rec, 0,
sizeof(rec));
5411 pRtlUnwind((
void *)test_unwind_apc_context.Rsp, (
void *)test_unwind_apc_context.Rip, &rec, (
void *)0xdeadbeef);
5412 ok(0,
"Should not get here.\n");
5415static void test_unwind_from_apc(
void)
5420 if (!pNtQueueApcThread)
5422 win_skip(
"NtQueueApcThread is not available.\n");
5433 test_unwind_apc_called =
FALSE;
5437 ok(0,
"Should not get here.\n");
5441 ok(test_unwind_apc_called,
"Test user APC was not called.\n");
5442 test_unwind_apc_called =
FALSE;
5446 ok(0,
"Should not get here.\n");
5448 ok(
pass == 4,
"Got unexpected pass %ld.\n",
pass);
5449 ok(test_unwind_apc_called,
"Test user APC was not called.\n");
5452static void test_syscall_clobbered_regs(
void)
5463 0x48, 0x8d, 0x05, 0x00, 0x10, 0x00, 0x00,
5465 0x48, 0x25, 0x00, 0xf0, 0xff, 0xff,
5467 0x48, 0x83, 0xe8, 0x08,
5473 0x53, 0x55, 0x57, 0x56, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57,
5475 0x49, 0xba, 0xef, 0xbe, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00,
5478 0x41, 0x5f, 0x41, 0x5e, 0x41, 0x5d, 0x41, 0x5c, 0x5e, 0x5f, 0x5d, 0x5b,
5481 0x49, 0x89, 0x48, 0x00,
5482 0x4d, 0x89, 0x50, 0x08,
5483 0x4d, 0x89, 0x58, 0x10,
5487 0x41, 0x89, 0x48, 0x18,
5501 ok(!!pNtCancelTimer,
"NtCancelTimer not found.\n");
5504 memset(®s, 0,
sizeof(regs));
5507 ok(regs.r11 == regs.eflags,
"Expected r11 (%#I64x) to equal EFLAGS (%#x).\n", regs.r11, regs.eflags);
5508 ok(regs.r10 != regs.rcx,
"got %#I64x.\n", regs.r10);
5511 ok((
BYTE *)regs.rcx > (
BYTE *)pNtCancelTimer && (
BYTE *)regs.rcx < (
BYTE *)pNtCancelTimer + 0x20,
5512 "Got unexpected rcx %s, pNtCancelTimer %p.\n",
wine_dbgstr_longlong(regs.rcx), pNtCancelTimer);
5516 ok((
BYTE *)regs.rcx > (
BYTE *)pNtCancelTimer && (
BYTE *)regs.rcx < (
BYTE *)pNtCancelTimer + 0x20,
5517 "Got unexpected rcx %s, pNtCancelTimer %p.\n",
wine_dbgstr_longlong(regs.rcx), pNtCancelTimer);
5518 ok(regs.r11 == regs.eflags,
"Expected r11 (%#I64x) to equal EFLAGS (%#x).\n", regs.r11, regs.eflags);
5519 ok(regs.r10 != regs.rcx,
"got %#I64x.\n", regs.r10);
5524 ok((
BYTE *)regs.rcx > (
BYTE *)pNtGetContextThread && (
BYTE *)regs.rcx < (
BYTE *)pNtGetContextThread + 0x20,
5525 "Got unexpected rcx %s, pNtGetContextThread %p.\n",
wine_dbgstr_longlong(regs.rcx), pNtGetContextThread);
5526 ok(regs.r11 == regs.eflags,
"Expected r11 (%#I64x) to equal EFLAGS (%#x).\n", regs.r11, regs.eflags);
5527 ok(regs.r10 != regs.rcx,
"got %#I64x.\n", regs.r10);
5531 ok((
BYTE *)regs.rcx > (
BYTE *)pNtGetContextThread && (
BYTE *)regs.rcx < (
BYTE *)pNtGetContextThread + 0x20,
5532 "Got unexpected rcx %s, pNtGetContextThread %p.\n",
wine_dbgstr_longlong(regs.rcx), pNtGetContextThread);
5533 ok((regs.r11 | 0x2) == regs.eflags,
"Expected r11 (%#I64x) | 0x2 to equal EFLAGS (%#x).\n", regs.r11, regs.eflags);
5534 ok(regs.r10 != regs.rcx,
"got %#I64x.\n", regs.r10);
5539 ok((
BYTE *)regs.rcx > (
BYTE *)pNtGetContextThread && (
BYTE *)regs.rcx < (
BYTE *)pNtGetContextThread + 0x20,
5540 "Got unexpected rcx %s, pNtGetContextThread %p.\n",
wine_dbgstr_longlong(regs.rcx), pNtGetContextThread);
5541 ok(regs.r11 == regs.eflags,
"Expected r11 (%#I64x) to equal EFLAGS (%#x).\n", regs.r11, regs.eflags);
5542 ok(regs.r10 != regs.rcx,
"got %#I64x.\n", regs.r10);
5546 ok((
BYTE *)regs.rcx > (
BYTE *)pNtSetContextThread && (
BYTE *)regs.rcx < (
BYTE *)pNtSetContextThread + 0x20,
5547 "Got unexpected rcx %s, pNtSetContextThread %p.\n",
wine_dbgstr_longlong(regs.rcx), pNtSetContextThread);
5548 ok(regs.r11 == regs.eflags,
"Expected r11 (%#I64x) to equal EFLAGS (%#x).\n", regs.r11, regs.eflags);
5549 ok(regs.r10 != regs.rcx,
"got %#I64x.\n", regs.r10);
5552static CONTEXT test_raiseexception_regs_context;
5558 test_raiseexception_regs_context = *
exception_info->ContextRecord;
5568static void test_raiseexception_regs(
void)
5572 0xb8, 0x00, 0xb0, 0xad, 0xde,
5599 0xb9, 0xaf, 0xbe, 0xad, 0xde,
5615 void *vectored_handler;
5620 vectored_handler = AddVectoredExceptionHandler(
TRUE, test_raiseexception_regs_handle);
5621 ok(!!vectored_handler,
"failed.\n");
5631 ok(test_raiseexception_regs_context.Rbx ==
expected,
"got %#I64x.\n", test_raiseexception_regs_context.Rbx);
5633 ok(test_raiseexception_regs_context.Rsi ==
expected,
"got %#I64x.\n", test_raiseexception_regs_context.Rsi);
5635 ok(test_raiseexception_regs_context.Rdi ==
expected,
"got %#I64x.\n", test_raiseexception_regs_context.Rdi);
5638 "got %#I64x.\n", test_raiseexception_regs_context.Rbp);
5640 ok(test_raiseexception_regs_context.
R12 ==
expected,
"got %#I64x.\n", test_raiseexception_regs_context.
R12);
5642 ok(test_raiseexception_regs_context.R13 ==
expected,
"got %#I64x.\n", test_raiseexception_regs_context.R13);
5644 ok(test_raiseexception_regs_context.R14 ==
expected,
"got %#I64x.\n", test_raiseexception_regs_context.R14);
5646 ok(test_raiseexception_regs_context.R15 ==
expected,
"got %#I64x.\n", test_raiseexception_regs_context.R15);
5648 RemoveVectoredExceptionHandler(vectored_handler);
5660static HANDLE instrumentation_callback_thread_ready, instrumentation_callback_thread_wait;
5662static DWORD WINAPI test_instrumentation_callback_thread(
void *
arg )
5664 SetEvent( instrumentation_callback_thread_ready );
5667 SetEvent( instrumentation_callback_thread_ready );
5672struct instrumentation_callback_data
5674 unsigned int call_count;
5683static void init_instrumentation_data(
struct instrumentation_callback_data *
d)
5689static void test_instrumentation_callback(
void)
5691 static const BYTE instrumentation_callback[] =
5696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5697 0xb8, 0x01, 0x00, 0x00, 0x00,
5698 0xf0, 0x0f, 0xc1, 0x02,
5701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5703 0x48, 0x8d, 0x14, 0xc2,
5705 0x48, 0x89, 0x4a, 0x08,
5711 struct instrumentation_callback_data curr_data,
data;
5714 void *pLdrInitializeThunk;
5716 void *vectored_handler;
5726 memcpy(
code_mem, instrumentation_callback,
sizeof(instrumentation_callback) );
5727 *(
void **)((
char *)
code_mem + 4) = &curr_data.call_count;
5728 *(
void **)((
char *)
code_mem + 26) = curr_data.call_data;
5732 init_instrumentation_data( &curr_data );
5739 ok( !
data.call_count,
"got %u.\n",
data.call_count );
5742 win_skip(
"Failed setting instrumenation callback.\n" );
5746 init_instrumentation_data( &curr_data );
5751 ok(
data.call_count == 1,
"got %u.\n",
data.call_count );
5755 ok(
data.call_data[0].rcx !=
data.call_data[0].r10,
"got %p.\n",
data.call_data[0].rcx );
5759 init_instrumentation_data( &curr_data );
5763 ok(
data.call_count == 1,
"got %u.\n",
data.call_count );
5765 vectored_handler = AddVectoredExceptionHandler(
TRUE, test_instrumentation_callback_handler );
5766 ok( !!vectored_handler,
"failed.\n" );
5767 init_instrumentation_data( &curr_data );
5776 pRtlCaptureContext( &
ctx );
5779 record.ExceptionCode = 0xceadbeef;
5780 record.NumberParameters = 0;
5781 init_instrumentation_data( &curr_data );
5783 ok( 0,
"Shouldn't be reached.\n" );
5791 init_instrumentation_data( &curr_data );
5793 ok( 0,
"Shouldn't be reached.\n" );
5799 ok( !
data.call_count,
"got %u.\n",
data.call_count );
5800 init_instrumentation_data( &curr_data );
5802 ok( 0,
"Shouldn't be reached.\n" );
5807 ok(
data.call_count == 1,
"got %u.\n",
data.call_count );
5808 ok(
data.call_data[0].r10 == (
void *)
ctx.Rip,
"got %p, expected %p.\n",
data.call_data[0].r10, (
void *)
ctx.Rip );
5809 init_instrumentation_data( &curr_data );
5812 RemoveVectoredExceptionHandler( vectored_handler );
5817 init_instrumentation_data( &curr_data );
5821 ok(
data.call_count == 1,
"got %u.\n",
data.call_count );
5826 init_instrumentation_data( &curr_data );
5830 ok(
data.call_count &&
data.call_count <= 256,
"got %u.\n",
data.call_count );
5832 for (
i = 0;
i <
data.call_count; ++
i)
5834 if (
data.call_data[
i].r10 == pLdrInitializeThunk)
break;
5836 ok(
i <
data.call_count,
"LdrInitializeThunk not found.\n" );
5838 init_instrumentation_data( &curr_data );
5839 SetEvent( instrumentation_callback_thread_wait );
5842 ok(
data.call_count &&
data.call_count <= 256,
"got %u.\n",
data.call_count );
5844 for (
i = 0;
i <
data.call_count; ++
i)
5851 SetEvent( instrumentation_callback_thread_wait );
5854 CloseHandle( instrumentation_callback_thread_ready );
5855 CloseHandle( instrumentation_callback_thread_wait );
5857 hwnd =
CreateWindowA(
"Static",
"test", 0, 0, 0, 0, 0, 0, 0, 0, 0 );
5858 init_instrumentation_data( &curr_data );
5861 ok(
data.call_count &&
data.call_count <= 256,
"got %u.\n",
data.call_count );
5862 for (
i = 0;
i <
data.call_count; ++
i)
5867 ok(
i <
data.call_count,
"KiUserCallbackDispatcher not found.\n" );
5869 init_instrumentation_data( &curr_data );
5874 ok( !
data.call_count,
"got %u.\n",
data.call_count );
5877static UINT32 find_syscall_nr(
const char *function)
5892static void test_direct_syscalls(
void)
5916#elif defined(__arm__)
5918static void test_thread_context(
void)
5924 DWORD R0,
R1,
R2,
R3,
R4, R5, R6, R7,
R8,
R9,
R10,
R11,
R12,
Sp, Lr, Pc, Cpsr;
5928 static const WORD call_func[] =
5949#define COMPARE(reg) \
5950 ok( context.reg == expect.reg, "wrong " #reg " %08lx/%08lx\n", context.reg, expect.reg )
5955 trace(
"expect: r0=%08lx r1=%08lx r2=%08lx r3=%08lx r4=%08lx r5=%08lx r6=%08lx r7=%08lx r8=%08lx r9=%08lx "
5956 "r10=%08lx r11=%08lx r12=%08lx sp=%08lx lr=%08lx pc=%08lx cpsr=%08lx\n",
5959 trace(
"actual: r0=%08lx r1=%08lx r2=%08lx r3=%08lx r4=%08lx r5=%08lx r6=%08lx r7=%08lx r8=%08lx r9=%08lx "
5960 "r10=%08lx r11=%08lx r12=%08lx sp=%08lx lr=%08lx pc=%08lx cpsr=%08lx\n",
5965 "wrong flags %08lx\n",
context.ContextFlags );
5990 trace(
"expect: r0=%08lx r1=%08lx r2=%08lx r3=%08lx r4=%08lx r5=%08lx r6=%08lx r7=%08lx r8=%08lx r9=%08lx "
5991 "r10=%08lx r11=%08lx r12=%08lx sp=%08lx lr=%08lx pc=%08lx cpsr=%08lx\n",
5994 trace(
"actual: r0=%08lx r1=%08lx r2=%08lx r3=%08lx r4=%08lx r5=%08lx r6=%08lx r7=%08lx r8=%08lx r9=%08lx "
5995 "r10=%08lx r11=%08lx r12=%08lx sp=%08lx lr=%08lx pc=%08lx cpsr=%08lx\n",
6012 ok( (
char *)
context.Pc >= (
char *)pNtGetContextThread &&
6013 (
char *)
context.Pc <= (
char *)pNtGetContextThread + 0x10,
6014 "wrong Pc %08lx/%08lx\n",
context.Pc, (
DWORD)pNtGetContextThread );
6024 DWORD continuestatus;
6032 if(!pNtGetContextThread || !pNtSetContextThread || !pNtReadVirtualMemory || !pNtTerminateProcess)
6034 skip(
"NtGetContextThread, NtSetContextThread, NtReadVirtualMemory or NtTerminateProcess not found\n");
6038 if (with_WaitForDebugEventEx && !pWaitForDebugEventEx)
6040 skip(
"WaitForDebugEventEx not found, skipping unicode strings in OutputDebugStringW\n");
6052 continuestatus = cont_status;
6054 ok(
ret,
"reading debug event\n");
6057 ok(!
ret,
"ContinueDebugEvent unexpectedly succeeded\n");
6071 skip(
"child process loaded at different address, terminating it\n");
6082 sizeof(code_mem_address), &size_read);
6085 sizeof(stage), &size_read);
6092 trace(
"exception 0x%lx at %p firstchance=%ld pc=%08lx, r0=%08lx\n",
6099 ok(
FALSE,
"got way too many exceptions, probably caught in an infinite loop, terminating child\n");
6110 "wrong pc %p ntdll %p-%p\n", (
void *)
ctx.Pc,
ntdll,
6117 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 7,
"Pc at %lx instead of %p\n",
6118 ctx.Pc, (
char *)code_mem_address + 7);
6122 ctx.R0 = 0xf00f00f1;
6131 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 7,
"Pc at 0x%lx instead of %p\n",
6132 ctx.Pc, (
char *)code_mem_address + 7);
6134 ctx.R0 = 0xf00f00f1;
6145 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 7,
6146 "Pc at 0x%lx instead of %p\n",
ctx.Pc, (
char *)code_mem_address + 7);
6150 else ok((
char *)
ctx.Pc == (
char *)code_mem_address + 7,
6151 "Pc at 0x%lx instead of %p\n",
ctx.Pc, (
char *)code_mem_address + 7);
6159 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 0x1d,
6160 "expected Pc = %p, got 0x%lx\n", (
char *)code_mem_address + 0x1d,
ctx.Pc);
6167 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 3,
6168 "expected Pc = %p, got 0x%lx\n", (
char *)code_mem_address + 3,
ctx.Pc);
6187 ok(
FALSE,
"unexpected stage %x\n", stage);
6200 sizeof(stage), &size_read);
6204 ok(with_WaitForDebugEventEx &&
6206 "unexpected unicode debug string event\n");
6209 "unexpected ansi debug string event %u %s %lx\n",
6210 stage, with_WaitForDebugEventEx ?
"with" :
"without", cont_status);
6239 sizeof(stage), &size_read);
6244 ok(de.
u.
RipInfo.
dwError == 0x11223344,
"got unexpected rip error code %08lx, expected %08x\n",
6246 ok(de.
u.
RipInfo.
dwType == 0x55667788,
"got unexpected rip type %08lx, expected %08x\n",
6250 ok(
FALSE,
"unexpected stage %x\n", stage);
6266static void test_debug_service(
DWORD numexc)
6272static BOOL hook_called;
6274static void *code_ptr;
6276static WORD patched_code[] =
6297static void *
WINAPI hook_KiUserExceptionDispatcher(
void *
stack)
6302 trace(
"rec %p context %p pc %#lx sp %#lx flags %#lx\n",
6309 memcpy(code_ptr, saved_code,
sizeof(saved_code));
6314static void test_KiUserExceptionDispatcher(
void)
6316 WORD hook_trampoline[] =
6326 void *trampoline_ptr, *vectored_handler;
6331 *(
void **)&hook_trampoline[5] = hook_KiUserExceptionDispatcher;
6332 trampoline_ptr = (
char *)
code_mem + 1024;
6333 memcpy( trampoline_ptr, hook_trampoline,
sizeof(hook_trampoline));
6339 memcpy( saved_code, code_ptr,
sizeof(saved_code) );
6340 *(
void **)&patched_code[4] = (
char *)trampoline_ptr + 1;
6342 vectored_handler = AddVectoredExceptionHandler(
TRUE, dbg_except_continue_vectored_handler);
6344 memcpy( code_ptr, patched_code,
sizeof(patched_code) );
6348 hook_called =
FALSE;
6350 pRtlRaiseException(&
record);
6353 ok(!hook_called,
"Hook was called.\n");
6355 memcpy( code_ptr, patched_code,
sizeof(patched_code) );
6359 hook_called =
FALSE;
6362 pRtlRaiseException(&
record);
6365 ok(hook_called,
"Hook was not called.\n");
6368 RemoveVectoredExceptionHandler(vectored_handler);
6369 VirtualProtect(code_ptr,
sizeof(saved_code), old_protect, &old_protect);
6372static UINT alertable_supported;
6374static void *
WINAPI hook_KiUserApcDispatcher(
void *
stack)
6386 if (
args->alertable == 1) alertable_supported =
TRUE;
6389 trace(
"stack=%p func=%p args=%lx,%lx,%lx alertable=%lx context=%p pc=%lx sp=%lx (%lx)\n",
6396 ok(
args->args[1] == 0x5678,
"wrong arg2 %lx\n",
args->args[1] );
6397 ok(
args->args[2] == 0xdeadbeef,
"wrong arg3 %lx\n",
args->args[2] );
6403 memcpy( code_ptr, saved_code,
sizeof(saved_code));
6408static void test_KiUserApcDispatcher(
void)
6410 WORD hook_trampoline[] =
6422 *(
void **)&hook_trampoline[5] = hook_KiUserApcDispatcher;
6429 memcpy( saved_code, code_ptr,
sizeof(saved_code) );
6430 *(
void **)&patched_code[4] = (
char *)
code_mem + 1;
6431 memcpy( code_ptr, patched_code,
sizeof(patched_code) );
6434 hook_called =
FALSE;
6439 ok( hook_called,
"hook was not called\n" );
6441 memcpy( code_ptr, patched_code,
sizeof(patched_code) );
6445 if (alertable_supported)
6452 VirtualProtect( code_ptr,
sizeof(saved_code), old_protect, &old_protect );
6455static void WINAPI hook_KiUserCallbackDispatcher(
void *
sp)
6470 trace(
"stack=%p len=%lx id=%lx lr=%lx sp=%lx pc=%lx\n",
6475 ok( redzone >= 8 && redzone <= 16,
"wrong sp %p / %p (%Iu)\n",
6476 (
void *)
stack->sp,
stack->args_data, redzone );
6483 ok(
mod == win32u,
"pc %lx not in win32u %p\n",
stack->pc, win32u );
6488static void test_KiUserCallbackDispatcher(
void)
6498 memcpy( saved_code, code_ptr,
sizeof(saved_code));
6499 *(
void **)&patched_code[4] = hook_KiUserCallbackDispatcher;
6500 memcpy( code_ptr, patched_code,
sizeof(patched_code));
6503 DestroyWindow(
CreateWindowA(
"Static",
"test", 0, 0, 0, 0, 0, 0, 0, 0, 0 ));
6505 memcpy( code_ptr, saved_code,
sizeof(saved_code));
6507 VirtualProtect( code_ptr,
sizeof(saved_code), old_protect, &old_protect );
6512 DWORD function_length : 18;
6521static void run_exception_test(
void *
handler,
const void*
context,
6522 const void *
code,
unsigned int code_size,
6527 RUNTIME_FUNCTION runtime_func[2];
6530 DWORD oldaccess, oldaccess2;
6532 runtime_func[0].BeginAddress = 0;
6533 runtime_func[0].UnwindData = 0x1000;
6534 runtime_func[1].BeginAddress = func2_offset;
6535 runtime_func[1].UnwindData = 0x1010;
6537 unwind.function_length = func2_offset / 2;
6545 buf[1] = 0xfbfbffd4;
6548 unwind.function_length = (code_size - func2_offset) / 2;
6550 buf[5] = 0xfbfbffd4;
6553 buf[8] = 0xc004f8df;
6554 buf[9] = 0xbf004760;
6564 pRtlDeleteFunctionTable(runtime_func);
6569static BOOL got_nested_exception, got_prev_frame_exception;
6570static void *nested_exception_initial_frame;
6575 trace(
"nested_exception_handler pc %p, sp %p, code %#lx, flags %#lx, ExceptionAddress %p.\n",
6581 ok((
char *)
context->Sp == (
char *)frame - 8,
"Got unexpected frame %p / %p.\n", frame, (
void *)
context->Sp);
6585 nested_exception_initial_frame = frame;
6596 got_nested_exception =
TRUE;
6597 ok(frame == nested_exception_initial_frame,
"Got unexpected frame %p / %p.\n",
6598 frame, nested_exception_initial_frame);
6605 ok((
char *)frame == (
char *)nested_exception_initial_frame + 8,
"Got unexpected frame %p / %p.\n",
6606 frame, nested_exception_initial_frame);
6607 got_prev_frame_exception =
TRUE;
6611static const WORD nested_except_code[] =
6622static void test_nested_exception(
void)
6624 got_nested_exception = got_prev_frame_exception =
FALSE;
6625 run_exception_test(nested_exception_handler,
NULL, nested_except_code,
sizeof(nested_except_code),
6627 ok(got_nested_exception,
"Did not get nested exception.\n");
6628 ok(got_prev_frame_exception,
"Did not get nested exception in the previous frame.\n");
6631static unsigned int collided_unwind_exception_count;
6638 trace(
"collided_exception_handler pc %p, sp %p, code %#lx, flags %#lx, ExceptionAddress %p, frame %p.\n",
6641 switch(collided_unwind_exception_count++)
6646 nested_exception_initial_frame = frame;
6649 ok(0,
"shouldn't be reached\n");
6657 ok(0,
"shouldn't be reached\n");
6663 ok(frame == nested_exception_initial_frame,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
6669 ok((
char *)frame == (
char *)nested_exception_initial_frame + 8,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
6671 ok(0,
"shouldn't be reached\n");
6677 ok(frame == nested_exception_initial_frame,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
6683 ok((
char *)frame == (
char *)nested_exception_initial_frame + 8,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
6689static void test_collided_unwind(
void)
6691 got_nested_exception = got_prev_frame_exception =
FALSE;
6692 collided_unwind_exception_count = 0;
6693 run_exception_test(collided_exception_handler,
NULL, nested_except_code,
sizeof(nested_except_code),
6695 ok(collided_unwind_exception_count == 6,
"got %u.\n", collided_unwind_exception_count);
6699static int rtlraiseexception_unhandled_handler_called;
6700static int rtlraiseexception_teb_handler_called;
6701static int rtlraiseexception_handler_called;
6704 void *dispatcher,
BOOL unhandled_handler )
6708 trace(
"exception: %08lx flags:%lx addr:%p context: Pc:%p\n",
6712 "ExceptionAddress at %p instead of %p\n",
addr, (
char *)
code_mem + 7 );
6715 "wrong context flags %lx\n",
context->ContextFlags );
6719 ok(
context->R0 == 0xf00f00f0,
"context->X0 is %lx, should have been set to 0xf00f00f0 in vectored handler\n",
context->R0 );
6727 trace(
"exception: %08lx flags:%lx addr:%p context: Pc:%p\n",
6729 rtlraiseexception_unhandled_handler_called = 1;
6741 rtlraiseexception_teb_handler_called = 1;
6742 rtlraiseexception_handler_(rec, frame,
context, dispatcher,
FALSE);
6754 "wrong non volatile reg r%u %lx / %lx\n",
i + 4,
6756 for (
i = 0;
i < 8;
i++)
6758 "wrong non volatile reg d%u %I64x / %I64x\n",
i + 8,
6761 rtlraiseexception_handler_called = 1;
6762 rtlraiseexception_handler_(rec, frame,
context, dispatcher,
FALSE);
6772 trace(
"exception: %08lx flags:%lx addr:%p context: Pc:%p\n",
6775 "ExceptionAddress at %p instead of %p\n",
addr, (
char *)
code_mem + 7 );
6783static const DWORD call_one_arg_code[] =
6791static void run_rtlraiseexception_test(
DWORD exceptioncode)
6797 record.ExceptionCode = exceptioncode;
6798 record.ExceptionFlags = 0;
6801 record.NumberParameters = 0;
6803 frame.
Handler = rtlraiseexception_teb_handler;
6807 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, rtlraiseexception_vectored_handler);
6808 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
6809 if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(rtlraiseexception_unhandled_handler);
6811 rtlraiseexception_handler_called = 0;
6812 rtlraiseexception_teb_handler_called = 0;
6813 rtlraiseexception_unhandled_handler_called = 0;
6815 run_exception_test( rtlraiseexception_handler,
NULL, call_one_arg_code,
6816 sizeof(call_one_arg_code),
sizeof(call_one_arg_code),
6818 &
record, pRtlRaiseException);
6821 "address set to %p instead of %p\n",
record.ExceptionAddress, (
char *)
code_mem + 7 );
6824 ok( !rtlraiseexception_teb_handler_called,
"Frame TEB handler called\n" );
6825 ok( rtlraiseexception_handler_called,
"Frame handler called\n" );
6826 ok( rtlraiseexception_unhandled_handler_called,
"UnhandledExceptionFilter wasn't called\n" );
6828 pRtlRemoveVectoredExceptionHandler(vectored_handler);
6829 if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(
NULL);
6833static void test_rtlraiseexception(
void)
6835 run_rtlraiseexception_test(0x12345);
6841static LONG consolidate_dummy_called;
6844static const WORD call_rtlunwind[] =
6863 ok(
ctx->Pc == 0xdeadbeef,
"RtlRestoreContext wrong Pc, expected: 0xdeadbeef, got: %lx\n",
ctx->Pc);
6867 ok(
ctx->Pc != 0xdeadbeef,
"RtlUnwindEx wrong Pc, got: %lx\n",
ctx->Pc );
6869 for (
i = 0;
i < 8;
i++)
6870 ok( saved_regs[
i] == regs[
i],
"wrong reg R%u, expected: %lx, got: %lx\n",
6871 i + 4, saved_regs[
i], regs[
i] );
6874 for (
i = 0;
i < 8;
i++)
6876 "wrong reg D%u, expected: %I64x, got: %I64x\n",
6883static void test_restore_context(
void)
6890 if (!pRtlUnwindEx || !pRtlRestoreContext || !pRtlCaptureContext)
6892 skip(
"RtlUnwindEx/RtlCaptureContext/RtlRestoreContext not found\n");
6899 pRtlCaptureContext(&
ctx);
6902 pRtlRestoreContext(&
ctx,
NULL);
6903 ok(0,
"shouldn't be reached\n");
6921 pRtlRestoreContext(&
ctx, &rec);
6922 ok(0,
"shouldn't be reached\n");
6926 ok(
buf.R4 ==
ctx.R4 ,
"longjmp failed for R4, expected: %lx, got: %lx\n",
buf.R4,
ctx.R4 );
6927 ok(
buf.R5 ==
ctx.R5 ,
"longjmp failed for R5, expected: %lx, got: %lx\n",
buf.R5,
ctx.R5 );
6928 ok(
buf.R6 ==
ctx.R6 ,
"longjmp failed for R6, expected: %lx, got: %lx\n",
buf.R6,
ctx.R6 );
6929 ok(
buf.R7 ==
ctx.R7 ,
"longjmp failed for R7, expected: %lx, got: %lx\n",
buf.R7,
ctx.R7 );
6930 ok(
buf.R8 ==
ctx.R8 ,
"longjmp failed for R8, expected: %lx, got: %lx\n",
buf.R8,
ctx.R8 );
6931 ok(
buf.R9 ==
ctx.R9 ,
"longjmp failed for R9, expected: %lx, got: %lx\n",
buf.R9,
ctx.R9 );
6932 ok(
buf.R10 ==
ctx.R10,
"longjmp failed for R10, expected: %lx, got: %lx\n",
buf.R10,
ctx.R10 );
6933 ok(
buf.R11 ==
ctx.R11,
"longjmp failed for R11, expected: %lx, got: %lx\n",
buf.R11,
ctx.R11 );
6934 for (
i = 0;
i < 8;
i++)
6935 ok(
buf.D[
i] ==
ctx.D[
i + 8],
"longjmp failed for D%u, expected: %I64x, got: %I64x\n",
6937 pRtlRestoreContext(&
ctx, &rec);
6938 ok(0,
"shouldn't be reached\n");
6941 ok(
pass == 5,
"unexpected pass %ld\n",
pass);
6946 pRtlCaptureContext(&
ctx);
6957 pRtlUnwindEx((
void*)
buf.Sp, (
void*)0xdeadbeef, &rec,
NULL, &
ctx,
NULL);
6958 ok(0,
"shouldn't be reached\n");
6961 ok(
pass == 4,
"unexpected pass %ld\n",
pass);
6977 ctx.Pc = 0xdeadbeef;
6979 pRtlRestoreContext(&
ctx, &rec);
6980 ok(0,
"shouldn't be reached\n");
6983 ok(consolidate_dummy_called == 1,
"test_consolidate_dummy not called\n");
6985 ok(0,
"unexpected pass %ld\n",
pass);
6990 pRtlCaptureContext(&
ctx);
7005 ctx.Pc = 0xdeadbeef;
7009 func(
buf.Frame, 0xdeadbeef, &rec, 0, &
ctx,
NULL, pRtlUnwindEx, nonvol_regs );
7010 ok(0,
"shouldn't be reached\n");
7013 ok(consolidate_dummy_called == 2,
"test_consolidate_dummy not called\n");
7015 ok(0,
"unexpected pass %ld\n",
pass);
7018#elif defined(__aarch64__)
7020static void test_thread_context(
void)
7026 ULONG64 X0, X1,
X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16,
7027 X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, Fp, Lr,
Sp, Pc;
7028 ULONG Cpsr, Fpcr, Fpsr;
7032 static const DWORD call_func[] =
7070#define COMPARE(reg) \
7071 ok( context.reg == expect.reg, "wrong " #reg " %p/%p\n", (void *)(ULONG64)context.reg, (void *)(ULONG64)expect.reg )
7076 trace(
"expect: x0=%p x1=%p x2=%p x3=%p x4=%p x5=%p x6=%p x7=%p x8=%p x9=%p x10=%p x11=%p x12=%p x13=%p x14=%p x15=%p x16=%p x17=%p x18=%p x19=%p x20=%p x21=%p x22=%p x23=%p x24=%p x25=%p x26=%p x27=%p x28=%p fp=%p lr=%p sp=%p pc=%p cpsr=%08lx\n",
7086 trace(
"actual: x0=%p x1=%p x2=%p x3=%p x4=%p x5=%p x6=%p x7=%p x8=%p x9=%p x10=%p x11=%p x12=%p x13=%p x14=%p x15=%p x16=%p x17=%p x18=%p x19=%p x20=%p x21=%p x22=%p x23=%p x24=%p x25=%p x26=%p x27=%p x28=%p fp=%p lr=%p sp=%p pc=%p cpsr=%08lx\n",
7098 "wrong flags %08lx\n",
context.ContextFlags );
7142 trace(
"expect: x0=%p x1=%p x2=%p x3=%p x4=%p x5=%p x6=%p x7=%p x8=%p x9=%p x10=%p x11=%p x12=%p x13=%p x14=%p x15=%p x16=%p x17=%p x18=%p x19=%p x20=%p x21=%p x22=%p x23=%p x24=%p x25=%p x26=%p x27=%p x28=%p fp=%p lr=%p sp=%p pc=%p cpsr=%08lx\n",
7152 trace(
"actual: x0=%p x1=%p x2=%p x3=%p x4=%p x5=%p x6=%p x7=%p x8=%p x9=%p x10=%p x11=%p x12=%p x13=%p x14=%p x15=%p x16=%p x17=%p x18=%p x19=%p x20=%p x21=%p x22=%p x23=%p x24=%p x25=%p x26=%p x27=%p x28=%p fp=%p lr=%p sp=%p pc=%p cpsr=%08lx\n",
7178 ok( (
char *)
context.Pc >= (
char *)pNtGetContextThread &&
7179 (
char *)
context.Pc <= (
char *)pNtGetContextThread + 32,
7180 "wrong Pc %p/%p\n", (
void *)
context.Pc, pNtGetContextThread );
7190 DWORD continuestatus;
7198 if(!pNtGetContextThread || !pNtSetContextThread || !pNtReadVirtualMemory || !pNtTerminateProcess)
7200 skip(
"NtGetContextThread, NtSetContextThread, NtReadVirtualMemory or NtTerminateProcess not found\n");
7204 if (with_WaitForDebugEventEx && !pWaitForDebugEventEx)
7206 skip(
"WaitForDebugEventEx not found, skipping unicode strings in OutputDebugStringW\n");
7218 continuestatus = cont_status;
7220 ok(
ret,
"reading debug event\n");
7223 ok(!
ret,
"ContinueDebugEvent unexpectedly succeeded\n");
7237 skip(
"child process loaded at different address, terminating it\n");
7248 sizeof(code_mem_address), &size_read);
7251 sizeof(stage), &size_read);
7258 trace(
"exception 0x%lx at %p firstchance=%ld pc=%p, x0=%p\n",
7265 ok(
FALSE,
"got way too many exceptions, probably caught in an infinite loop, terminating child\n");
7276 "wrong pc %p ntdll %p-%p\n", (
void *)
ctx.Pc,
ntdll,
7283 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 0xc,
"Pc at %p instead of %p\n",
7284 (
char *)
ctx.Pc, (
char *)code_mem_address + 0xc);
7288 ctx.X0 = 0xf00f00f1;
7297 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 0xc,
"Pc at %p instead of %p\n",
7298 (
char *)
ctx.Pc, (
char *)code_mem_address + 0xc);
7300 ctx.X0 = 0xf00f00f1;
7311 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 0xc,
7312 "Pc at %p instead of %p\n", (
char *)
ctx.Pc, (
char *)code_mem_address + 0xc);
7316 else ok((
char *)
ctx.Pc == (
char *)code_mem_address + 0xc,
7317 "Pc at %p instead of %p\n", (
void *)
ctx.Pc, (
char *)code_mem_address + 0xc);
7325 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 0x1d,
7326 "expected Pc = %p, got %p\n", (
char *)code_mem_address + 0x1d, (
char *)
ctx.Pc);
7333 ok((
char *)
ctx.Pc == (
char *)code_mem_address + 4,
7334 "expected Pc = %p, got %p\n", (
char *)code_mem_address + 4, (
char *)
ctx.Pc);
7353 ok(
FALSE,
"unexpected stage %x\n", stage);
7366 sizeof(stage), &size_read);
7370 ok(with_WaitForDebugEventEx &&
7372 "unexpected unicode debug string event\n");
7375 "unexpected ansi debug string event %u %s %lx\n",
7376 stage, with_WaitForDebugEventEx ?
"with" :
"without", cont_status);
7396 "unexpected stage %x, got debug string event '%s'\n", stage,
buffer);
7406 sizeof(stage), &size_read);
7411 ok(de.
u.
RipInfo.
dwError == 0x11223344,
"got unexpected rip error code %08lx, expected %08x\n",
7413 ok(de.
u.
RipInfo.
dwType == 0x55667788,
"got unexpected rip type %08lx, expected %08x\n",
7417 ok(
FALSE,
"unexpected stage %x\n", stage);
7433static void test_debug_service(
DWORD numexc)
7438static void test_continue(
void)
7440 struct context_pair {
7448 static const DWORD call_func[] =
7532 if (!pRtlCaptureContext)
7534 win_skip(
"RtlCaptureContext is not available.\n");
7541#define COMPARE(reg) \
7542 ok( contexts.before.reg == contexts.after.reg, "wrong " #reg " %p/%p\n", (void *)(ULONG64)contexts.before.reg, (void *)(ULONG64)contexts.after.reg )
7543#define COMPARE_INDEXED(reg) \
7544 ok( contexts.before.reg == contexts.after.reg, "wrong " #reg " i: %u, %p/%p\n", i, (void *)(ULONG64)contexts.before.reg, (void *)(ULONG64)contexts.after.reg )
7548 for (
i = 1;
i < 29;
i++) COMPARE_INDEXED(
X[
i] );
7553 for (
i = 0;
i < 32;
i++)
7555 COMPARE_INDEXED(
V[
i].
Low );
7556 COMPARE_INDEXED(
V[
i].
High );
7568 win_skip(
"NtContinueEx not supported\n" );
7572 func_ptr( &contexts, &
args, pNtContinueEx, pRtlCaptureContext );
7574 for (
i = 1;
i < 29;
i++) COMPARE_INDEXED(
X[
i] );
7579 for (
i = 0;
i < 32;
i++)
7581 COMPARE_INDEXED(
V[
i].
Low );
7582 COMPARE_INDEXED(
V[
i].
High );
7586 func_ptr( &contexts, &
args, pNtContinueEx, pRtlCaptureContext );
7589 func_ptr( &contexts, &
args, pNtContinueEx, pRtlCaptureContext );
7595static BOOL hook_called;
7598static ULONG patched_code[] =
7619static void *
WINAPI hook_KiUserExceptionDispatcher(
void *
stack)
7632 trace(
"stack %p context->Pc %#Ix, context->Sp %#Ix, ContextFlags %#lx.\n",
7640 ok(
args->rec.ExceptionCode == 0x80000003,
"Got unexpected ExceptionCode %#lx.\n",
args->rec.ExceptionCode );
7642 ok(
args->context_ex.All.Offset == -
sizeof(
CONTEXT),
"wrong All.Offset %lx\n",
args->context_ex.All.Offset );
7644 ok(
args->context_ex.Legacy.Offset == -
sizeof(
CONTEXT),
"wrong Legacy.Offset %lx\n",
args->context_ex.All.Offset );
7645 ok(
args->context_ex.Legacy.Length ==
sizeof(
CONTEXT),
"wrong Legacy.Length %lx\n",
args->context_ex.All.Length );
7646 ok(
args->sp ==
args->context.Sp,
"wrong sp %Ix / %Ix\n",
args->sp,
args->context.Sp );
7647 ok(
args->pc ==
args->context.Pc,
"wrong pc %Ix / %Ix\n",
args->pc,
args->context.Pc );
7655static void test_KiUserExceptionDispatcher(
void)
7657 ULONG hook_trampoline[] =
7667 void *trampoline_ptr, *vectored_handler;
7671 *(
void **)&hook_trampoline[4] = hook_KiUserExceptionDispatcher;
7672 trampoline_ptr = (
char *)
code_mem + 1024;
7673 memcpy( trampoline_ptr, hook_trampoline,
sizeof(hook_trampoline));
7680 *(
void **)&patched_code[3] = trampoline_ptr;
7682 vectored_handler = AddVectoredExceptionHandler(
TRUE, dbg_except_continue_vectored_handler);
7688 hook_called =
FALSE;
7690 pRtlRaiseException(&
record);
7693 ok(!hook_called,
"Hook was called.\n");
7699 hook_called =
FALSE;
7702 pRtlRaiseException(&
record);
7705 ok(hook_called,
"Hook was not called.\n");
7708 RemoveVectoredExceptionHandler(vectored_handler);
7712static void *
WINAPI hook_KiUserApcDispatcher(
void *
stack)
7723 trace(
"stack=%p func=%p args=%Ix,%Ix,%Ix alertable=%Ix context=%p pc=%Ix sp=%Ix (%Ix)\n",
7730 ok(
args->args[1] == 0x5678,
"wrong arg2 %Ix\n",
args->args[1] );
7731 ok(
args->args[2] == 0xdeadbeef,
"wrong arg3 %Ix\n",
args->args[2] );
7742static void test_KiUserApcDispatcher(
void)
7744 ULONG hook_trampoline[] =
7755 *(
void **)&hook_trampoline[4] = hook_KiUserApcDispatcher;
7763 *(
void **)&patched_code[3] =
code_mem;
7767 hook_called =
FALSE;
7772 ok( hook_called,
"hook was not called\n" );
7785static void WINAPI hook_KiUserCallbackDispatcher(
void *
sp)
7801 trace(
"stack=%p len=%lx id=%lx unk=%Ix lr=%Ix sp=%Ix pc=%Ix\n",
7805 ok( redzone >= 16 && redzone <= 32,
"wrong sp %p / %p (%Iu)\n",
7806 (
void *)
stack->sp,
stack->args_data, redzone );
7813 ok(
mod == win32u,
"pc %Ix not in win32u %p\n",
stack->pc, win32u );
7818static void test_KiUserCallbackDispatcher(
void)
7828 *(
void **)&patched_code[3] = hook_KiUserCallbackDispatcher;
7832 DestroyWindow(
CreateWindowA(
"Static",
"test", 0, 0, 0, 0, 0, 0, 0, 0, 0 ));
7839static void run_exception_test(
void *
handler,
const void*
context,
7840 const void *
code,
unsigned int code_size,
7845 RUNTIME_FUNCTION runtime_func[2];
7846 IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA unwind;
7848 DWORD oldaccess, oldaccess2;
7850 runtime_func[0].BeginAddress = 0;
7851 runtime_func[0].UnwindData = 0x1000;
7852 runtime_func[1].BeginAddress = func2_offset;
7853 runtime_func[1].UnwindData = 0x1014;
7855 unwind.FunctionLength = func2_offset / 4;
7857 unwind.ExceptionDataPresent = 1;
7858 unwind.EpilogInHeader = 1;
7859 unwind.EpilogCount = 1;
7860 unwind.CodeWords = 1;
7861 buf[0] = unwind.HeaderData;
7862 buf[1] = 0xe3e481e1;
7866 unwind.FunctionLength = (code_size - func2_offset) / 4;
7867 buf[5] = unwind.HeaderData;
7868 buf[6] = 0xe3e481e1;
7872 buf[10] = 0x5800004f;
7873 buf[11] = 0xd61f01e0;
7883 pRtlDeleteFunctionTable(runtime_func);
7888static BOOL got_nested_exception, got_prev_frame_exception;
7889static void *nested_exception_initial_frame;
7894 trace(
"nested_exception_handler pc %p, sp %p, code %#lx, flags %#lx, ExceptionAddress %p.\n",
7900 ok((
char *)
context->Sp == (
char *)frame - 0x10,
"Got unexpected frame %p / %p.\n", frame, (
void *)
context->Sp);
7901 ok((
char *)
context->Fp == (
char *)frame - 0x10,
"Got unexpected frame %p / %p.\n", frame, (
void *)
context->Fp);
7905 nested_exception_initial_frame = frame;
7916 got_nested_exception =
TRUE;
7917 ok(frame == nested_exception_initial_frame,
"Got unexpected frame %p / %p.\n",
7918 frame, nested_exception_initial_frame);
7925 ok((
char *)frame == (
char *)nested_exception_initial_frame + 0x10,
"Got unexpected frame %p / %p.\n",
7926 frame, nested_exception_initial_frame);
7927 got_prev_frame_exception =
TRUE;
7931static const DWORD nested_except_code[] =
7947static void test_nested_exception(
void)
7949 got_nested_exception = got_prev_frame_exception =
FALSE;
7950 run_exception_test(nested_exception_handler,
NULL, nested_except_code,
sizeof(nested_except_code),
7952 ok(got_nested_exception,
"Did not get nested exception.\n");
7953 ok(got_prev_frame_exception,
"Did not get nested exception in the previous frame.\n");
7956static unsigned int collided_unwind_exception_count;
7963 trace(
"collided_exception_handler pc %p, sp %p, code %#lx, flags %#lx, ExceptionAddress %p, frame %p.\n",
7966 switch(collided_unwind_exception_count++)
7971 nested_exception_initial_frame = frame;
7974 ok(0,
"shouldn't be reached\n");
7982 ok(0,
"shouldn't be reached\n");
7988 ok(frame == nested_exception_initial_frame,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
7994 ok((
char *)frame == (
char *)nested_exception_initial_frame + 0x10,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
7996 ok(0,
"shouldn't be reached\n");
8002 ok(frame == nested_exception_initial_frame,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
8008 ok((
char *)frame == (
char *)nested_exception_initial_frame + 0x10,
"got %p, expected %p.\n", frame, nested_exception_initial_frame);
8014static void test_collided_unwind(
void)
8016 got_nested_exception = got_prev_frame_exception =
FALSE;
8017 collided_unwind_exception_count = 0;
8018 run_exception_test(collided_exception_handler,
NULL, nested_except_code,
sizeof(nested_except_code),
8020 ok(collided_unwind_exception_count == 6,
"got %u.\n", collided_unwind_exception_count);
8024static int rtlraiseexception_unhandled_handler_called;
8025static int rtlraiseexception_teb_handler_called;
8026static int rtlraiseexception_handler_called;
8029 void *dispatcher,
BOOL unhandled_handler )
8033 trace(
"exception: %08lx flags:%lx addr:%p context: Pc:%p\n",
8037 "ExceptionAddress at %p instead of %p\n",
addr, (
char *)
code_mem + 0x0c );
8040 "wrong context flags %lx\n",
context->ContextFlags );
8044 ok(
context->X0 == 0xf00f00f0,
"context->X0 is %Ix, should have been set to 0xf00f00f0 in vectored handler\n",
context->X0 );
8052 rtlraiseexception_unhandled_handler_called = 1;
8064 rtlraiseexception_teb_handler_called = 1;
8065 rtlraiseexception_handler_(rec, frame,
context, dispatcher,
FALSE);
8077 "wrong non volatile reg x%u %I64x / %I64x\n",
i + 19,
8081 "wrong non volatile reg d%u %g / %g\n",
i + 8,
8084 rtlraiseexception_handler_called = 1;
8085 rtlraiseexception_handler_(rec, frame,
context, dispatcher,
FALSE);
8096 "ExceptionAddress at %p instead of %p\n",
addr, (
char *)
code_mem + 0xc );
8105static const DWORD call_one_arg_code[] =
8115static void run_rtlraiseexception_test(
DWORD exceptioncode)
8121 record.ExceptionCode = exceptioncode;
8122 record.ExceptionFlags = 0;
8125 record.NumberParameters = 0;
8127 frame.
Handler = rtlraiseexception_teb_handler;
8131 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, rtlraiseexception_vectored_handler);
8132 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
8133 if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(rtlraiseexception_unhandled_handler);
8135 rtlraiseexception_handler_called = 0;
8136 rtlraiseexception_teb_handler_called = 0;
8137 rtlraiseexception_unhandled_handler_called = 0;
8139 run_exception_test( rtlraiseexception_handler,
NULL, call_one_arg_code,
8140 sizeof(call_one_arg_code),
sizeof(call_one_arg_code),
8142 &
record, pRtlRaiseException);
8145 "address set to %p instead of %p\n",
record.ExceptionAddress, (
char *)
code_mem + 0x0c );
8148 ok( !rtlraiseexception_teb_handler_called,
"Frame TEB handler called\n" );
8149 ok( rtlraiseexception_handler_called,
"Frame handler called\n" );
8150 ok( rtlraiseexception_unhandled_handler_called,
"UnhandledExceptionFilter wasn't called\n" );
8152 pRtlRemoveVectoredExceptionHandler(vectored_handler);
8154 if (pRtlSetUnhandledExceptionFilter) pRtlSetUnhandledExceptionFilter(
NULL);
8158static void test_rtlraiseexception(
void)
8160 run_rtlraiseexception_test(0x12345);
8165static DWORD brk_exception_handler_code;
8178static void test_brk(
void)
8193 call_brk[2] = 0xd43e0020;
8194 run_exception_test( brk_exception_handler,
NULL, call_brk,
8195 sizeof(call_brk),
sizeof(call_brk),
8204 call_brk[2] = 0xd43e0080;
8205 run_exception_test( brk_exception_handler,
NULL, call_brk,
8206 sizeof(call_brk),
sizeof(call_brk),
8213 call_brk[2] = 0xd43e00a0;
8214 run_exception_test( brk_exception_handler,
NULL, call_brk,
8215 sizeof(call_brk),
sizeof(call_brk),
8220 call_brk[2] = 0xd4200000;
8221 run_exception_test( brk_exception_handler,
NULL, call_brk,
8222 sizeof(call_brk),
sizeof(call_brk),
8227static LONG consolidate_dummy_called;
8230static const DWORD call_rtlunwind[] =
8255 ok(
ctx->Pc == 0xdeadbeef,
"RtlRestoreContext wrong Pc, expected: 0xdeadbeef, got: %Ix\n",
ctx->Pc);
8259 ok(
ctx->Pc != 0xdeadbeef,
"RtlUnwindEx wrong Pc, got: %Ix\n",
ctx->Pc );
8263 ok( saved_regs[
i] == regs->
GpNvRegs[
i],
"wrong reg X%u, expected: %Ix, got: %Ix\n",
8265 for (
i = 0;
i < 8;
i++)
8267 "wrong reg D%u, expected: %Ix, got: %Ix\n",
8274static void test_restore_context(
void)
8281 if (!pRtlUnwindEx || !pRtlRestoreContext || !pRtlCaptureContext)
8283 skip(
"RtlUnwindEx/RtlCaptureContext/RtlRestoreContext not found\n");
8290 pRtlCaptureContext(&
ctx);
8293 pRtlRestoreContext(&
ctx,
NULL);
8294 ok(0,
"shouldn't be reached\n");
8312 pRtlRestoreContext(&
ctx, &rec);
8313 ok(0,
"shouldn't be reached\n");
8317 ok(
buf.X19 ==
ctx.X19,
"longjmp failed for X19, expected: %Ix, got: %Ix\n",
buf.X19,
ctx.X19);
8318 ok(
buf.X20 ==
ctx.X20,
"longjmp failed for X20, expected: %Ix, got: %Ix\n",
buf.X20,
ctx.X20);
8319 ok(
buf.X21 ==
ctx.X21,
"longjmp failed for X21, expected: %Ix, got: %Ix\n",
buf.X21,
ctx.X21);
8320 ok(
buf.X22 ==
ctx.X22,
"longjmp failed for X22, expected: %Ix, got: %Ix\n",
buf.X22,
ctx.X22);
8321 ok(
buf.X23 ==
ctx.X23,
"longjmp failed for X23, expected: %Ix, got: %Ix\n",
buf.X23,
ctx.X23);
8322 ok(
buf.X24 ==
ctx.X24,
"longjmp failed for X24, expected: %Ix, got: %Ix\n",
buf.X24,
ctx.X24);
8323 ok(
buf.X25 ==
ctx.X25,
"longjmp failed for X25, expected: %Ix, got: %Ix\n",
buf.X25,
ctx.X25);
8324 ok(
buf.X26 ==
ctx.X26,
"longjmp failed for X26, expected: %Ix, got: %Ix\n",
buf.X26,
ctx.X26);
8325 ok(
buf.X27 ==
ctx.X27,
"longjmp failed for X27, expected: %Ix, got: %Ix\n",
buf.X27,
ctx.X27);
8326 ok(
buf.X28 ==
ctx.X28,
"longjmp failed for X28, expected: %Ix, got: %Ix\n",
buf.X28,
ctx.X28);
8327 ok(
buf.Fp ==
ctx.Fp,
"longjmp failed for Fp, expected: %Ix, got: %Ix\n",
buf.Fp,
ctx.Fp);
8328 for (
i = 0;
i < 8;
i++)
8329 ok(
buf.D[
i] ==
ctx.V[
i + 8].D[0],
"longjmp failed for D%u, expected: %g, got: %g\n",
8331 pRtlRestoreContext(&
ctx, &rec);
8332 ok(0,
"shouldn't be reached\n");
8335 ok(
pass == 5,
"unexpected pass %ld\n",
pass);
8340 pRtlCaptureContext(&
ctx);
8351 pRtlUnwindEx((
void*)
buf.Sp, (
void*)0xdeadbeef, &rec,
NULL, &
ctx,
NULL);
8352 ok(0,
"shouldn't be reached\n");
8355 ok(
pass == 4,
"unexpected pass %ld\n",
pass);
8371 ctx.Pc = 0xdeadbeef;
8373 pRtlRestoreContext(&
ctx, &rec);
8374 ok(0,
"shouldn't be reached\n");
8377 ok(consolidate_dummy_called == 1,
"test_consolidate_dummy not called\n");
8379 ok(0,
"unexpected pass %ld\n",
pass);
8384 pRtlCaptureContext(&
ctx);
8399 ctx.Pc = 0xdeadbeef;
8403 func(
buf.Frame, 0xdeadbeef, &rec, 0, &
ctx,
NULL, pRtlUnwindEx, nonvol_regs );
8404 ok(0,
"shouldn't be reached\n");
8407 ok(consolidate_dummy_called == 2,
"test_consolidate_dummy not called\n");
8409 ok(0,
"unexpected pass %ld\n",
pass);
8412static void test_mrs_currentel(
void)
8417 static const DWORD call_func[] =
8433#if defined(__i386__) || defined(__x86_64__)
8455static void test_debug_registers(
void)
8463 { 0x42424240, 0, 0x126bb070, 0x0badbad0, 0, 0xffff0115 },
8464 { 0x42424242, 0, 0x100f0fe7, 0x0abebabe, 0, 0x115 },
8512 ctx.Dr0 = 0xffffffff;
8513 ctx.Dr1 = 0xffffffff;
8514 ctx.Dr2 = 0xffffffff;
8515 ctx.Dr3 = 0xffffffff;
8516 ctx.Dr6 = 0xffffffff;
8517 ctx.Dr7 = 0x00000400;
8539#if defined(__x86_64__)
8541static void test_debug_registers_wow64(
void)
8543 char cmdline[] =
"C:\\windows\\syswow64\\msinfo32.exe";
8553 if ((pRtlWow64GetThreadContext ==
NULL) ||
8554 (pRtlWow64SetThreadContext ==
NULL))
8556 skip(
"RtlWow64Get/SetThreadContext not found\n");
8563 ok(bret,
"CreateProcessA failed\n");
8566 ok(bret &&
is_wow64,
"expected Wow64 process\n");
8573 ok(bret,
"GetThreadContext failed\n");
8575 ctx.Dr0 = 0x12340000;
8576 ctx.Dr1 = 0x12340001;
8577 ctx.Dr2 = 0x12340002;
8578 ctx.Dr3 = 0x12340003;
8581 ok(bret,
"SetThreadContext failed\n");
8587 ok(bret,
"GetThreadContext failed\n");
8592 ok(!
ctx.Dr0,
"expected 0, got %Ix\n",
ctx.Dr0);
8593 ok(!
ctx.Dr1,
"expected 0, got %Ix\n",
ctx.Dr1);
8594 ok(!
ctx.Dr2,
"expected 0, got %Ix\n",
ctx.Dr2);
8595 ok(!
ctx.Dr3,
"expected 0, got %Ix\n",
ctx.Dr3);
8596 ok(!
ctx.Dr7,
"expected 0, got %Ix\n",
ctx.Dr7);
8600 ok(
ctx.Dr0 == 0x12340000,
"expected 0x12340000, got %Ix\n",
ctx.Dr0);
8601 ok(
ctx.Dr1 == 0x12340001,
"expected 0x12340001, got %Ix\n",
ctx.Dr1);
8602 ok(
ctx.Dr2 == 0x12340002,
"expected 0x12340002, got %Ix\n",
ctx.Dr2);
8603 ok(
ctx.Dr3 == 0x12340003,
"expected 0x12340003, got %Ix\n",
ctx.Dr3);
8604 ok(
ctx.Dr7 == 0x155,
"expected 0x155, got %Ix\n",
ctx.Dr7);
8608 memset(&wow64_ctx, 0xcc,
sizeof(wow64_ctx));
8610 ret = pRtlWow64GetThreadContext(
pi.
hThread, &wow64_ctx);
8616 ok(!wow64_ctx.
Dr0,
"expected 0, got %lx\n", wow64_ctx.
Dr0);
8617 ok(!wow64_ctx.
Dr1,
"expected 0, got %lx\n", wow64_ctx.
Dr1);
8618 ok(!wow64_ctx.
Dr2,
"expected 0, got %lx\n", wow64_ctx.
Dr2);
8619 ok(!wow64_ctx.
Dr3,
"expected 0, got %lx\n", wow64_ctx.
Dr3);
8620 ok(!wow64_ctx.
Dr7,
"expected 0, got %lx\n", wow64_ctx.
Dr7);
8624 ok(wow64_ctx.
Dr0 == 0x12340000,
"expected 0x12340000, got %lx\n", wow64_ctx.
Dr0);
8625 ok(wow64_ctx.
Dr1 == 0x12340001,
"expected 0x12340001, got %lx\n", wow64_ctx.
Dr1);
8626 ok(wow64_ctx.
Dr2 == 0x12340002,
"expected 0x12340002, got %lx\n", wow64_ctx.
Dr2);
8627 ok(wow64_ctx.
Dr3 == 0x12340003,
"expected 0x12340003, got %lx\n", wow64_ctx.
Dr3);
8628 ok(wow64_ctx.
Dr7 == 0x155,
"expected 0x155, got %lx\n", wow64_ctx.
Dr7);
8633 wow64_ctx.
Dr0 = 0x56780000;
8634 wow64_ctx.
Dr1 = 0x56780001;
8635 wow64_ctx.
Dr2 = 0x56780002;
8636 wow64_ctx.
Dr3 = 0x56780003;
8637 wow64_ctx.
Dr7 = 0x101;
8638 ret = pRtlWow64SetThreadContext(
pi.
hThread, &wow64_ctx);
8641 memset(&wow64_ctx, 0xcc,
sizeof(wow64_ctx));
8643 ret = pRtlWow64GetThreadContext(
pi.
hThread, &wow64_ctx);
8647 ok(wow64_ctx.
Dr0 == 0x56780000,
"expected 0x56780000, got %lx\n", wow64_ctx.
Dr0);
8648 ok(wow64_ctx.
Dr1 == 0x56780001,
"expected 0x56780001, got %lx\n", wow64_ctx.
Dr1);
8649 ok(wow64_ctx.
Dr2 == 0x56780002,
"expected 0x56780002, got %lx\n", wow64_ctx.
Dr2);
8650 ok(wow64_ctx.
Dr3 == 0x56780003,
"expected 0x56780003, got %lx\n", wow64_ctx.
Dr3);
8651 ok(wow64_ctx.
Dr7 == 0x101,
"expected 0x101, got %lx\n", wow64_ctx.
Dr7);
8657 ok(bret,
"GetThreadContext failed\n");
8662 ok(!
ctx.Dr0,
"expected 0, got %Ix\n",
ctx.Dr0);
8663 ok(!
ctx.Dr1,
"expected 0, got %Ix\n",
ctx.Dr1);
8664 ok(!
ctx.Dr2,
"expected 0, got %Ix\n",
ctx.Dr2);
8665 ok(!
ctx.Dr3,
"expected 0, got %Ix\n",
ctx.Dr3);
8666 ok(!
ctx.Dr7,
"expected 0, got %Ix\n",
ctx.Dr7);
8670 ok(
ctx.Dr0 == 0x56780000,
"expected 0x56780000, got %Ix\n",
ctx.Dr0);
8671 ok(
ctx.Dr1 == 0x56780001,
"expected 0x56780001, got %Ix\n",
ctx.Dr1);
8672 ok(
ctx.Dr2 == 0x56780002,
"expected 0x56780002, got %Ix\n",
ctx.Dr2);
8673 ok(
ctx.Dr3 == 0x56780003,
"expected 0x56780003, got %Ix\n",
ctx.Dr3);
8674 ok(
ctx.Dr7 == 0x101,
"expected 0x101, got %Ix\n",
ctx.Dr7);
8686static DWORD debug_service_exceptions;
8701 "expected ExceptionInformation[0] = %lx, got %Ix\n",
8716 "expected ExceptionInformation[0] = %Ix, got %Ix\n",
8720 debug_service_exceptions++;
8729 0x8b, 0x44, 0x24, 0x0c,
8730 0xb9, 0x11, 0x11, 0x11, 0x11,
8731 0xba, 0x22, 0x22, 0x22, 0x22,
8732 0xbb, 0x33, 0x33, 0x33, 0x33,
8733 0xbf, 0x44, 0x44, 0x44, 0x44,
8739 0x90, 0x90, 0x90, 0x90,
8740 0x90, 0x90, 0x90, 0x90,
8755 0x48, 0xb9, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
8756 0x48, 0xba, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
8757 0x48, 0xbb, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
8758 0x48, 0xbf, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
8764 0x90, 0x90, 0x90, 0x90,
8765 0x90, 0x90, 0x90, 0x90,
8775static void test_debug_service(
DWORD numexc)
8778 DWORD expected_exc, expected_ret;
8779 void *vectored_handler;
8785 vectored_handler = pRtlAddVectoredExceptionHandler(
TRUE, &debug_service_handler);
8786 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
8788 expected_exc = numexc;
8789 expected_ret = (numexc != 0);
8792 debug_service_exceptions = 0;
8794 ok(debug_service_exceptions == expected_exc,
8795 "BREAKPOINT_BREAK generated %lu exceptions, expected %lu\n",
8796 debug_service_exceptions, expected_exc);
8797 ok(
ret == expected_ret,
8798 "BREAKPOINT_BREAK returned %lu, expected %lu\n",
ret, expected_ret);
8801 debug_service_exceptions = 0;
8803 ok(debug_service_exceptions == expected_exc,
8804 "BREAKPOINT_PROMPT generated %lu exceptions, expected %lu\n",
8805 debug_service_exceptions, expected_exc);
8806 ok(
ret == expected_ret,
8807 "BREAKPOINT_PROMPT returned %lu, expected %lu\n",
ret, expected_ret);
8810 debug_service_exceptions = 0;
8812 ok(debug_service_exceptions == expected_exc,
8813 "invalid debug service generated %lu exceptions, expected %lu\n",
8814 debug_service_exceptions, expected_exc);
8815 ok(
ret == expected_ret,
8816 "invalid debug service returned %lu, expected %lu\n",
ret, expected_ret);
8818 expected_exc = (
is_wow64 ? numexc : 0);
8819 expected_ret = (
is_wow64 && numexc);
8822 debug_service_exceptions = 0;
8824 ok(debug_service_exceptions == expected_exc,
8825 "BREAKPOINT_PRINT generated %lu exceptions, expected %lu\n",
8826 debug_service_exceptions, expected_exc);
8827 ok(
ret == expected_ret,
8828 "BREAKPOINT_PRINT returned %lu, expected %lu\n",
ret, expected_ret);
8831 debug_service_exceptions = 0;
8833 ok(debug_service_exceptions == expected_exc,
8834 "BREAKPOINT_LOAD_SYMBOLS generated %lu exceptions, expected %lu\n",
8835 debug_service_exceptions, expected_exc);
8836 ok(
ret == expected_ret,
8837 "BREAKPOINT_LOAD_SYMBOLS returned %lu, expected %lu\n",
ret, expected_ret);
8840 debug_service_exceptions = 0;
8842 ok(debug_service_exceptions == expected_exc,
8843 "BREAKPOINT_UNLOAD_SYMBOLS generated %lu exceptions, expected %lu\n",
8844 debug_service_exceptions, expected_exc);
8845 ok(
ret == expected_ret,
8846 "BREAKPOINT_UNLOAD_SYMBOLS returned %lu, expected %lu\n",
ret, expected_ret);
8849 debug_service_exceptions = 0;
8851 ok(debug_service_exceptions == expected_exc ||
broken(debug_service_exceptions == numexc),
8852 "BREAKPOINT_COMMAND_STRING generated %lu exceptions, expected %lu\n",
8853 debug_service_exceptions, expected_exc);
8855 "BREAKPOINT_COMMAND_STRING returned %lu, expected %lu\n",
ret, expected_ret);
8857 pRtlRemoveVectoredExceptionHandler(vectored_handler);
8874 "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[1]);
8882 "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[1]);
8885 "ExceptionInformation[3] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[3]);
8897 DWORD numexc_unicode_low,
DWORD numexc_unicode_high)
8899 PVOID vectored_handler;
8901 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
8903 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
8908 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
8919 "OutputDebugString%c generated %ld ansi exceptions, expected %ld\n",
8923 "OutputDebugString%c generated %lu unicode exceptions, expected %ld-%ld\n",
8926 pRtlRemoveVectoredExceptionHandler(vectored_handler);
8942 "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[1]);
8950 "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[1]);
8953 "ExceptionInformation[3] = '%s' instead of 'Hello World'\n", (
char *)rec->
ExceptionInformation[3]);
8967 PVOID vectored_handler;
8974 DWORD exceptions_order;
8985 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
8987 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
8992 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
9005 "OutputDebugString%c/%u generated exceptions %04lxs, expected %04lx\n",
9006 tests[
i].unicode ?
'W' :
'A',
i,
9010 pRtlRemoveVectoredExceptionHandler(vectored_handler);
9034 PVOID vectored_handler;
9036 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
9038 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
9043 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
9046 record.ExceptionFlags = 0;
9049 record.NumberParameters = 2;
9050 record.ExceptionInformation[0] = 0x11223344;
9051 record.ExceptionInformation[1] = 0x55667788;
9054 pRtlRaiseException(&
record);
9058 pRtlRemoveVectoredExceptionHandler(vectored_handler);
9067 DWORD continuestatus;
9089 "expected exactly one parameter, got %lu\n",
9093 "expected %u for code, got %Iu\n",
9113 ok(had_ff ||
broken(had_se) ,
"fast fail did not occur\n");
9126 unsigned int codes[] = {
9165#elif defined(__x86_64__)
9173#elif defined(__arm__)
9181#elif defined(__aarch64__)
9195#if defined(__i386__) || defined(__x86_64__)
9196static const BYTE breakpoint_code[] = { 0xcd, 0x03, 0xc3 };
9197#elif defined(__arm__)
9198static const DWORD breakpoint_code[] = { 0xdefe, 0x4770 };
9199#elif defined(__aarch64__)
9200static const DWORD breakpoint_code[] = { 0xd43e0000, 0xd65f03c0 };
9206 void *vectored_handler;
9208#if defined(__REACTOS__)
9211 skip(
"Skipping tests that crash\n");
9221 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
9228 pRtlRemoveVectoredExceptionHandler(vectored_handler);
9231#if defined(__i386__) || defined(__x86_64__)
9232static BYTE except_code_set_ymm0[] =
9238 0x00, 0x00, 0x00, 0x00,
9240 0x00, 0x00, 0x00, 0x00,
9243 0xc5, 0xfc, 0x10, 0x00,
9245 0xc5, 0xfc, 0x11, 0x00,
9249static void test_debuggee_xstate(
void)
9252 unsigned int address_offset,
i;
9253 unsigned int data[8];
9255 if (!pRtlGetEnabledExtendedFeatures || !pRtlGetEnabledExtendedFeatures(1 <<
XSTATE_AVX))
9262 memcpy(
code_mem, except_code_set_ymm0,
sizeof(except_code_set_ymm0));
9263 address_offset =
sizeof(
void *) == 8 ? 2 : 1;
9271 for (
i = 0;
i < 4; ++
i)
9273 "Got unexpected data %#x, test_stage %u, i %u.\n",
data[
i],
test_stage,
i);
9278 "Got unexpected data %#x, test_stage %u, i %u.\n",
data[
i],
test_stage,
i);
9281static BYTE except_code_segments[] =
9308static void test_debuggee_segments(
void)
9312 memcpy(
code_mem, except_code_segments,
sizeof(except_code_segments));
9339 PVOID vectored_handler;
9342 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler || !pRtlRaiseException)
9344 skip(
"RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler or RtlRaiseException not found\n");
9349 ok(vectored_handler != 0,
"RtlAddVectoredExceptionHandler failed\n");
9357 "CloseHandle expected %d, got %d for %p\n", expectret,
ret,
handle);
9359 "CloseHandle generated %ld exceptions, expected %ld for %p\n",
9366 "NtClose returned unexpected status %#lx, expected %#lx for %p\n",
status,
expect,
handle);
9368 "CloseHandle generated %ld exceptions, expected %ld for %p\n",
9371 pRtlRemoveVectoredExceptionHandler(vectored_handler);
9376 PVOID handler1, handler2;
9379 if (!pRtlAddVectoredContinueHandler || !pRtlRemoveVectoredContinueHandler)
9381 skip(
"RtlAddVectoredContinueHandler or RtlRemoveVectoredContinueHandler not found\n");
9385 handler1 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
9386 ok(handler1 != 0,
"RtlAddVectoredContinueHandler failed\n");
9388 handler2 = pRtlAddVectoredContinueHandler(
TRUE, (
void *)0xdeadbeef);
9389 ok(handler2 != 0,
"RtlAddVectoredContinueHandler failed\n");
9390 ok(handler1 != handler2,
"RtlAddVectoredContinueHandler returned same handler\n");
9392 if (pRtlRemoveVectoredExceptionHandler)
9394 ret = pRtlRemoveVectoredExceptionHandler(handler1);
9395 ok(!
ret,
"RtlRemoveVectoredExceptionHandler succeeded\n");
9398 ret = pRtlRemoveVectoredContinueHandler(handler1);
9399 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
9401 ret = pRtlRemoveVectoredContinueHandler(handler2);
9402 ok(
ret,
"RtlRemoveVectoredContinueHandler failed\n");
9404 ret = pRtlRemoveVectoredContinueHandler(handler1);
9405 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
9407 ret = pRtlRemoveVectoredContinueHandler((
void *)0x11223344);
9408 ok(!
ret,
"RtlRemoveVectoredContinueHandler succeeded\n");
9418 if (!pNtQueueApcThread)
9420 win_skip(
"NtQueueApcThread is not available.\n");
9463#elif defined(__x86_64__)
9465#elif defined(__arm__)
9467#elif defined(__aarch64__)
9477 ok(
apc_count == 1,
"Test user APC was not called.\n");
9483 ok(0,
"Should not get here, status %#lx.\n",
status);
9486 ok(
ret == 0xabacab,
"Got return value %#x.\n",
ret);
9487 ok(
pass == 3,
"Got unexpected pass %ld.\n",
pass);
9488 ok(
apc_count > 0,
"Test user APC was not called.\n");
9517 win_skip(
"ThreadSuspendCount is not supported.\n");
9528#define TEST_SUSPEND_COUNT(thread, count) test_suspend_count((thread), (count), __LINE__)
9560 ok(
len == 123,
"Unexpected info length %lu.\n",
len);
9565 ok(
len == 123,
"Unexpected info length %lu.\n",
len);
9570 ok(
count == 10,
"Unexpected suspend count %lu.\n",
count);
9578 ok(
count == 0,
"Unexpected suspended count %lu.\n",
count);
9583 ok(!
status,
"Failed to suspend a thread, status %#lx.\n",
status);
9588 ok(!
status,
"Failed to suspend a thread, status %#lx.\n",
status);
9589 ok(
count == 1,
"Unexpected suspended count %lu.\n",
count);
9594 ok(!
status,
"Failed to resume a thread, status %#lx.\n",
status);
9595 ok(
count == 2,
"Unexpected suspended count %lu.\n",
count);
9600 ok(!
status,
"Failed to resume a thread, status %#lx.\n",
status);
9608#undef TEST_SUSPEND_COUNT
9627 ok(
event !=
NULL,
"Failed to open event handle.\n");
9628 ok(event2 !=
NULL,
"Failed to open event handle.\n");
9631 ok(
thread !=
NULL,
"Failed to create auxiliary thread.\n");
9646 ok(!
status,
"Failed to suspend a thread, status %#lx.\n",
status);
9647 ok(
count == 125,
"Unexpected suspend count %lu.\n",
count);
9650 ok(!
status,
"Failed to resume a thread, status %#lx.\n",
status);
9670 ok(event2 !=
NULL,
"Failed to create event.\n");
9678 ok(
ret,
"Failed to create target process.\n");
9691 ok(!
status,
"Failed to resume a process, status %#lx.\n",
status);
9693 status = pNtSuspendProcess(0);
9697 ok(!
status,
"Failed to resume a process, status %#lx.\n",
status);
9704 ok(!
status,
"Failed to suspend a process, status %#lx.\n",
status);
9707 ok(!
status &&
ret == 1,
"Failed to suspend main thread, status %#lx.\n",
status);
9709 ok(!
status &&
ret == 2,
"Failed to resume main thread, status %#lx.\n",
status);
9716 ok(!
status,
"Failed to suspend a process, status %#lx.\n",
status);
9719 ok(!
status,
"Failed to resume a process, status %#lx.\n",
status);
9726 ok(!
status,
"Failed to resume a process, status %#lx.\n",
status);
9745 static const WCHAR imageW[] = {
'm',
's',
'x',
'm',
'l',
'3',
'.',
'd',
'l',
'l',0};
9752 ok(unload_trace !=
NULL,
"Failed to get unload events pointer.\n");
9754 if (pRtlGetUnloadEventTraceEx)
9759 ok(unload_trace_ex !=
NULL,
"Unexpected pointer %p.\n", unload_trace_ex);
9763 size =
sizeof(*unload_trace);
9766 ok(
hmod !=
NULL,
"Failed to load library.\n");
9771 while (
ptr->BaseAddress !=
NULL)
9780 ok(found,
"Unloaded module wasn't found.\n");
9782 if (unload_trace_ex)
9785 ptr = *unload_trace_ex;
9786 while (
ptr->BaseAddress !=
NULL)
9795 ok(found,
"Unloaded module wasn't found.\n");
9799#if defined(__i386__) || defined(__x86_64__)
9801static const unsigned int test_extended_context_data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
9802static const unsigned test_extended_context_spoil_data1[8] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
9803static const unsigned test_extended_context_spoil_data2[8] = {0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 0x85};
9805static BOOL test_extended_context_modified_state;
9806static BOOL xsaveopt_enabled, compaction_enabled;
9807static ULONG64 xstate_supported_features;
9812 const ULONG64 expected_compaction_mask = (0x8000000000000000 | xstate_supported_features) & ~(
ULONG64)3;
9814 unsigned int *context_ymm_data;
9815 DWORD expected_min_offset;
9819 "Got unexpected ContextFlags %#lx.\n",
context->ContextFlags);
9829 ok(!(
dispatch->ContextRecord->ContextFlags & 0x40),
"Got unexpected ContextRecord->ContextFlags %#lx.\n",
9830 dispatch->ContextRecord->ContextFlags);
9838 "Got unexpected All.Offset %ld.\n", xctx->
All.
Offset);
9841 "Got unexpected XState.Offset %ld.\n", xctx->
XState.
Offset);
9845 context_ymm_data = (
unsigned int *)&xs->
YmmContext;
9846 ok(!((
ULONG_PTR)xs % 64),
"Got unexpected xs %p.\n", xs);
9848 if (compaction_enabled)
9849 ok((xs->
CompactionMask & (expected_compaction_mask | 3)) == expected_compaction_mask,
9850 "Got compaction mask %#I64x, expected %#I64x.\n", xs->
CompactionMask, expected_compaction_mask);
9854 if (test_extended_context_modified_state)
9857 ok(!
memcmp(context_ymm_data, test_extended_context_data + 4,
sizeof(
M128A)),
9858 "Got unexpected context data.\n");
9862 ok((xs->
Mask & 7) == (xsaveopt_enabled ? 0 : 4),
"Got unexpected Mask %#I64x.\n", xs->
Mask);
9869 memcpy(context_ymm_data, test_extended_context_spoil_data1 + 4,
sizeof(
M128A));
9874 __asm__ volatile(
"vmovups (%0),%%ymm0" : :
"r"(test_extended_context_spoil_data2));
9885struct call_func_offsets
9887 unsigned int func_addr;
9888 unsigned int func_param1;
9889 unsigned int func_param2;
9890 unsigned int ymm0_save;
9893static BYTE call_func_code_set_ymm0[] =
9897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9900 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9906 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9908 0xc5, 0xfc, 0x10, 0x45, 0x00,
9909 0x48, 0x83, 0xec, 0x20,
9911 0x48, 0x83, 0xc4, 0x20,
9912 0xc5, 0xfc, 0x11, 0x45, 0x00,
9916static BYTE call_func_code_reset_ymm_state[] =
9920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9923 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9926 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9929 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9933 0x48, 0x83, 0xec, 0x20,
9935 0x48, 0x83, 0xc4, 0x20,
9936 0xc5, 0xfc, 0x11, 0x45, 0x00,
9940static const struct call_func_offsets call_func_offsets = {3, 13, 23, 33};
9942static BYTE call_func_code_set_ymm0[] =
9946 0x00, 0x00, 0x00, 0x00,
9949 0x00, 0x00, 0x00, 0x00,
9952 0x00, 0x00, 0x00, 0x00,
9955 0x00, 0x00, 0x00, 0x00,
9957 0x81, 0xfa, 0xef, 0xbe, 0xad, 0xde,
9962 0xc5, 0xfc, 0x10, 0x45, 0x00,
9964 0xc5, 0xfc, 0x11, 0x45, 0x00,
9968static BYTE call_func_code_reset_ymm_state[] =
9972 0x00, 0x00, 0x00, 0x00,
9975 0x00, 0x00, 0x00, 0x00,
9978 0x00, 0x00, 0x00, 0x00,
9981 0x00, 0x00, 0x00, 0x00,
9983 0x81, 0xfa, 0xef, 0xbe, 0xad, 0xde,
9991 0xc5, 0xfc, 0x11, 0x45, 0x00,
9995static const struct call_func_offsets call_func_offsets = {2, 7, 12, 17};
10001 static unsigned int data[8];
10004 memcpy(
code_mem, call_func_code_reset_ymm_state,
sizeof(call_func_code_reset_ymm_state));
10007 *(
void **)((
BYTE *)
code_mem + call_func_offsets.func_param2) = (
void *)0xdeadbeef;
10011 for (
i = 0;
i < 4; ++
i)
10012 ok(!
data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10014 ok(
data[
i] == 0x48484848,
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10017 memcpy(
code_mem, call_func_code_set_ymm0,
sizeof(call_func_code_set_ymm0));
10020 *(
void **)((
BYTE *)
code_mem + call_func_offsets.func_param2) = (
void *)0xdeadbeef;
10024 memcpy(
code_mem, call_func_code_reset_ymm_state,
sizeof(call_func_code_reset_ymm_state));
10027 *(
void **)((
BYTE *)
code_mem + call_func_offsets.func_param2) = (
void *)0xdeadbeef;
10033static void wait_for_thread_next_suspend(
HANDLE thread)
10051#define CONTEXT_NATIVE (CONTEXT_XSTATE & CONTEXT_CONTROL)
10053struct context_parameters
10056 ULONG supported_flags;
10057 ULONG broken_flags;
10058 ULONG context_length;
10059 ULONG legacy_length;
10060 ULONG context_ex_length;
10062 ULONG flags_offset;
10063 ULONG xsavearea_offset;
10064 ULONG vector_reg_count;
10067static void test_extended_context(
void)
10069 static BYTE except_code_reset_ymm_state[] =
10075 0x00, 0x00, 0x00, 0x00,
10077 0x00, 0x00, 0x00, 0x00,
10079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
10084 0xc5, 0xfc, 0x11, 0x00,
10088 static const struct context_parameters context_arch_old[] =
10116 static const struct context_parameters context_arch_new[] =
10143 const struct context_parameters *context_arch;
10145 const ULONG64 supported_features = 0xff;
10146 const ULONG64 supported_compaction_mask = supported_features | ((
ULONG64)1 << 63);
10147 ULONG expected_length, expected_length_xstate,
context_flags, expected_offset, max_xstate_length;
10148 ULONG64 enabled_features, expected_compaction;
10151 unsigned int i,
j, address_offset,
test;
10164 address_offset =
sizeof(
void *) == 8 ? 2 : 1;
10165 *(
void **)(except_code_set_ymm0 + address_offset) =
data;
10166 *(
void **)(except_code_reset_ymm_state + address_offset) =
data;
10168 if (!pRtlGetEnabledExtendedFeatures)
10170 win_skip(
"RtlGetEnabledExtendedFeatures is not available.\n");
10174 enabled_features = pRtlGetEnabledExtendedFeatures(~(
ULONG64)0);
10177 if (enabled_features)
10182 xsaveopt_enabled = regs[0] & 1;
10183 compaction_enabled = regs[0] & 2;
10186 xstate_supported_features = enabled_features & supported_features;
10190 ret = pRtlGetExtendedContextLength(0, &
length);
10194 ret = pRtlGetExtendedContextLength(context_arch_new[0].
flag, &
length);
10196 if (
length == context_arch_new[0].context_length + context_arch_new[0].context_ex_length
10197 + context_arch_new[0].
align)
10198 context_arch = context_arch_new;
10200 context_arch = context_arch_old;
10204 expected_length = context_arch[
test].context_length + context_arch[
test].context_ex_length
10205 + context_arch[
test].align;
10206 expected_length_xstate = context_arch[
test].context_length + context_arch[
test].context_ex_length
10211 ok(!
ret &&
length == expected_length,
"Got unexpected result ret %#lx, length %#lx.\n",
10214 for (
i = 0;
i < 32; ++
i)
10220 length = length2 = 0xdeadbeef;
10226 ||
broken((context_arch[
test].broken_flags & (1 <<
i))
10228 "Got unexpected result ret %#lx, length %#lx, flags 0x%08lx.\n",
10234 "Got unexpected result ret %#lx, length %#lx, flags 0x%08lx.\n",
ret,
length,
flags);
10242 "Got unexpected bret %#x, length2 %#lx, GetLastError() %lu, flags %#lx.\n",
10249 context = (
void *)0xdeadbeef;
10250 length2 = expected_length - 1;
10251 bret = pInitializeContext(context_buffer,
flags, &
context, &length2);
10253 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10254 ok(
context == (
void *)0xdeadbeef,
"Got unexpected context %p.\n",
context);
10257 memset(context_buffer, 0xcc,
sizeof(context_buffer));
10258 length2 = expected_length;
10259 bret = pInitializeContext(context_buffer,
flags, &
context, &length2);
10261 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10262 ok(length2 == expected_length,
"Got unexpected length %#lx.\n",
length);
10272 : context_arch[
test].legacy_length),
10293 length2 = 0xdeadbeef;
10296 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10297 length2 = expected_length;
10312 if (
flags & CONTEXT_NATIVE)
10313 ok(bret &&
mask == ((
flags & flags_fpx) == flags_fpx ? 0x3 : 0),
10317 "Got unexpected bret %#x, mask %s, GetLastError() %#lx, flags %#lx.\n",
10320 bret = pSetXStateFeaturesMask(
context, 0);
10321 ok(bret == !!(
flags & CONTEXT_NATIVE),
"Got unexpected bret %#x, flags %#lx.\n", bret,
flags);
10325 bret = pSetXStateFeaturesMask(
context, 1);
10326 ok(bret == !!(
flags & CONTEXT_NATIVE),
"Got unexpected bret %#x, flags %#lx.\n", bret,
flags);
10331 bret = pSetXStateFeaturesMask(
context, 2);
10332 ok(bret == !!(
flags & CONTEXT_NATIVE),
"Got unexpected bret %#x, flags %#lx.\n", bret,
flags);
10337 bret = pSetXStateFeaturesMask(
context, 4);
10338 ok(!bret,
"Got unexpected bret %#x.\n", bret);
10342 *(
DWORD *)(context_buffer + context_arch[
test].flags_offset) =
flags;
10344 for (
j = 0;
j < context_arch[
test].flags_offset; ++
j)
10346 if (context_buffer[
j] != 0xcc)
10348 ok(0,
"Buffer data changed at offset %#x.\n",
j);
10353 j < context_arch[
test].context_length; ++
j)
10355 if (context_buffer[
j] != 0xcc)
10357 ok(0,
"Buffer data changed at offset %#x.\n",
j);
10361 for (
j = context_arch[
test].context_length + context_arch[
test].context_ex_length;
10362 j <
sizeof(context_buffer); ++
j)
10364 if (context_buffer[
j] != 0xcc)
10366 ok(0,
"Buffer data changed at offset %#x.\n",
j);
10371 memset(context_buffer2, 0xcc,
sizeof(context_buffer2));
10372 ret2 = pRtlInitializeExtendedContext(context_buffer2,
flags, &
context_ex);
10373 ok(!ret2,
"Got unexpected ret2 %#lx, flags %#lx.\n", ret2,
flags);
10374 ok(!
memcmp(context_buffer2, context_buffer,
sizeof(context_buffer2)),
10375 "Context data do not match, flags %#lx.\n",
flags);
10377 memset(context_buffer2, 0xcc,
sizeof(context_buffer2));
10378 ret2 = pRtlInitializeExtendedContext(context_buffer2 + 2,
flags, &
context_ex);
10379 ok(!ret2,
"Got unexpected ret2 %#lx, flags %#lx.\n", ret2,
flags);
10384 sizeof(context_buffer2) -
align),
10385 "Context data do not match, flags %#lx.\n",
flags);
10388 memset(context_buffer2, 0xcc,
sizeof(context_buffer2));
10389 bret = pInitializeContext(context_buffer2 + 2,
flags, &
context, &length2);
10391 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10392 ok(length2 == expected_length,
"Got unexpected length %#lx.\n",
length);
10394 sizeof(context_buffer2) -
align),
10395 "Context data do not match, flags %#lx.\n",
flags);
10397 length2 = 0xdeadbeef;
10399 if (
flags & CONTEXT_NATIVE)
10402 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10404 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10405 length2 = 0xdeadbeef;
10407 if (
flags & CONTEXT_NATIVE)
10409 && length2 ==
sizeof(
M128A) * context_arch[
test].vector_reg_count,
10410 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10412 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10413 length2 = 0xdeadbeef;
10415 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10417 if (!pRtlInitializeExtendedContext2 || !pInitializeContext2)
10422 win_skip(
"InitializeContext2 is not available.\n");
10426 length2 = expected_length;
10427 memset(context_buffer2, 0xcc,
sizeof(context_buffer2));
10429 ok(!ret2,
"Got unexpected ret2 %#lx, flags %#lx.\n", ret2,
flags);
10431 sizeof(context_buffer2) -
align),
10432 "Context data do not match, flags %#lx.\n",
flags);
10434 memset(context_buffer2, 0xcc,
sizeof(context_buffer2));
10435 bret = pInitializeContext2(context_buffer2 + 2,
flags, &
context, &length2, 0);
10437 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10438 ok(length2 == expected_length,
"Got unexpected length %#lx.\n",
length);
10440 sizeof(context_buffer2) -
align),
10441 "Context data do not match, flags %#lx.\n",
flags);
10443 length2 = 0xdeadbeef;
10445 if (
flags & CONTEXT_NATIVE)
10448 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10450 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10453 flags = context_arch[
test].flag | 0x40;
10459 if (!enabled_features)
10462 "Got unexpected result ret %#lx, length %#lx.\n",
ret,
length);
10465 ret2 = pRtlInitializeExtendedContext(context_buffer,
flags, &
context_ex);
10469 length2 =
sizeof(context_buffer);
10470 bret = pInitializeContext(context_buffer,
flags, &
context, &length2);
10472 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10477 if (pInitializeContext2)
10480 length2 =
sizeof(context_buffer);
10483 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10492 "Got unexpected result ret %#lx, length %#lx, test %u.\n",
ret,
length,
test);
10494 if (!pRtlGetExtendedContextLength2)
10496 win_skip(
"RtlGetExtendedContextLength2 is not available.\n");
10503 "Got unexpected result ret %#lx, length %#lx, test %u.\n",
ret,
length,
test);
10508 "Got unexpected result ret %#lx, length %#lx, test %u.\n",
ret,
length,
test);
10514 "Got unexpected result ret %#lx, length %#lx, test %u.\n",
ret,
length,
test);
10520 "Got unexpected result ret %#lx, length %#lx, test %u.\n",
ret,
length,
test);
10525 "Got unexpected result ret %#lx, length %#lx, test %u.\n",
ret,
length,
test);
10532 "Got unexpected bret %#x, length2 %#lx, GetLastError() %lu, flags %#lx.\n",
10536 context = (
void *)0xdeadbeef;
10538 bret = pInitializeContext(context_buffer,
flags, &
context, &length2);
10540 "Got unexpected bret %#x, GetLastError() %lu, length2 %#lx, flags %#lx.\n",
10544 memset(context_buffer, 0xcc,
sizeof(context_buffer));
10546 bret = pInitializeContext(context_buffer,
flags, &
context, &length2);
10548 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10559 : context_arch[
test].legacy_length),
10564 - context_arch[
test].context_length;
10578 length2 = 0xdeadbeef;
10579 for (
i = 0;
i < 2; ++
i)
10582 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx.\n",
p, length2);
10586 ok(length2 ==
sizeof(
YMMCONTEXT),
"Got unexpected length %#lx.\n", length2);
10591 length2 = 0xdeadbeef;
10593 if (
flags & CONTEXT_NATIVE)
10596 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10598 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10600 length2 = 0xdeadbeef;
10602 if (
flags & CONTEXT_NATIVE)
10604 && length2 ==
sizeof(
M128A) * context_arch[
test].vector_reg_count,
10605 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10607 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10609 length2 = 0xdeadbeef;
10611 if (
flags & CONTEXT_NATIVE)
10613 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10615 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10619 if (
flags & CONTEXT_NATIVE)
10623 ok(!bret &&
mask == 0xdeadbeef,
10626 expected_compaction = compaction_enabled ? ((
ULONG64)1 << 63) | enabled_features : 0;
10634 xs->
Mask = 0xdeadbeef;
10644 xs->
Mask = 0xdeadbeef;
10655 xs->
Mask = 0xdeadbeef;
10657 bret = pSetXStateFeaturesMask(
context, xstate_supported_features);
10658 ok(bret == !!(
flags & CONTEXT_NATIVE),
"Got unexpected bret %#x.\n", bret);
10665 ok(xs->
CompactionMask == bret ? expected_compaction : 0xdeadbeef,
"Got unexpected CompactionMask %s.\n",
10670 if (
flags & CONTEXT_NATIVE)
10671 ok(bret &&
mask == xstate_supported_features,
10672 "Got unexpected bret %#x, mask %s, flags %#lx (enabled_features & supported_features %#I64x).\n", bret,
wine_dbgstr_longlong(
mask),
flags, xstate_supported_features);
10674 ok(!bret &&
mask == 0xdeadbeef,
10677 if (pRtlGetExtendedContextLength2)
10679 memset(context_buffer, 0xcc,
sizeof(context_buffer));
10680 pRtlGetExtendedContextLength2(
flags, &
length, 0);
10682 memset(context_buffer, 0xcc,
sizeof(context_buffer));
10684 bret = pInitializeContext2(context_buffer,
flags, &
context, &length2, 0);
10686 "Got unexpected bret %#x, GetLastError() %lu, flags %#lx.\n", bret,
GetLastError(),
flags);
10690 length2 = 0xdeadbeef;
10692 if (
flags & CONTEXT_NATIVE)
10695 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10697 ok(!
p && length2 == 0xdeadbeef,
"Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10699 length2 = 0xdeadbeef;
10703 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10705 length2 = 0xdeadbeef;
10708 "Got unexpected p %p, length %#lx, flags %#lx.\n",
p, length2,
flags);
10717 : context_arch[
test].legacy_length),
10722 - context_arch[
test].context_length;
10736 expected_compaction = compaction_enabled ? (
ULONG64)1 << 63 : 0;
10739 ok(xs->CompactionMask == expected_compaction,
10745 ok(xs->CompactionMask == expected_compaction,
"Got unexpected CompactionMask %s.\n",
wine_dbgstr_longlong(xs->CompactionMask));
10750 ret = pRtlGetExtendedContextLength(context_arch[0].
flag | context_arch[1].
flag, &
length);
10758 length =
sizeof(context_buffer);
10763 if (!(enabled_features & (1 <<
XSTATE_AVX)))
10765 skip(
"AVX is not supported.\n");
10770 length =
sizeof(context_buffer);
10771 memset(context_buffer, 0xcc,
sizeof(context_buffer));
10773 ok(bret,
"Got unexpected bret %#x.\n", bret);
10778 ok(max_xstate_length >=
sizeof(
XSTATE),
"XSTATE size: %#lx; min: %#Ix.\n", max_xstate_length,
sizeof(
XSTATE));
10780 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_addr) =
RtlCaptureContext;
10781 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_param1) =
context;
10782 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_param2) = (
void *)0xdeadbeef;
10783 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.ymm0_save) =
data;
10784 memcpy(
code_mem, call_func_code_set_ymm0,
sizeof(call_func_code_set_ymm0));
10790 for (
i = 0;
i < 8; ++
i)
10791 ok(
data[
i] == test_extended_context_data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10794 length =
sizeof(context_buffer);
10795 memset(context_buffer, 0xcc,
sizeof(context_buffer));
10798 ok(bret,
"Got unexpected bret %#x.\n", bret);
10799 memset(&xs->YmmContext, 0xcc,
sizeof(xs->YmmContext));
10806 ok(
context->ContextFlags == expected_flags,
"Got unexpected ContextFlags %#lx.\n",
10808 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_addr) =
GetThreadContext;
10809 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_param1) = (
void *)
GetCurrentThread();
10810 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_param2) =
context;
10811 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.ymm0_save) =
data;
10812 memcpy(
code_mem, call_func_code_set_ymm0,
sizeof(call_func_code_set_ymm0));
10813 xs->CompactionMask = 2;
10814 xs->Mask = compaction_enabled ? 2 : 0;
10818 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
10820 ok(
context->ContextFlags == expected_flags,
"Got unexpected ContextFlags %#lx.\n",
10822 expected_compaction = compaction_enabled ? (
ULONG64)1 << 63 : 0;
10824 ok(!xs->Mask ||
broken(xs->Mask == 4) ,
10826 ok(xs->CompactionMask == expected_compaction,
"Got unexpected CompactionMask %s.\n",
10829 for (
i = 4;
i < 8; ++
i)
10830 ok(
data[
i] == test_extended_context_data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10832 for (
i = 0;
i < 4; ++
i)
10833 ok(((
ULONG *)&xs->YmmContext)[
i] == (xs->Mask == 4 ? test_extended_context_data[
i + 4] : 0xcccccccc),
10834 "Got unexpected data %#lx, i %u.\n", ((
ULONG *)&xs->YmmContext)[
i],
i);
10836 expected_compaction = compaction_enabled ? ((
ULONG64)1 << 63) | 4 : 0;
10838 xs->CompactionMask = 4;
10839 xs->Mask = compaction_enabled ? 0 : 4;
10843 "Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
10844 ok(
context->ContextFlags == expected_flags,
"Got unexpected ContextFlags %#lx.\n",
10846 ok(xs->Mask == (compaction_enabled ? 0 : 4),
"Got unexpected Mask %#I64x.\n", xs->Mask);
10847 ok(xs->CompactionMask == 4,
"Got unexpected CompactionMask %s.\n",
10849 for (
i = 0;
i < 4; ++
i)
10850 ok(((
ULONG *)&xs->YmmContext)[
i] == 0xcccccccc
10851 ||
broken(((
ULONG *)&xs->YmmContext)[
i] == test_extended_context_data[
i + 4]) ,
10852 "Got unexpected data %#lx, i %u.\n", ((
ULONG *)&xs->YmmContext)[
i],
i);
10854 xs->CompactionMask = 4;
10855 xs->Mask = compaction_enabled ? 0 : 4;
10858 ok(
context->ContextFlags == expected_flags,
"Got unexpected ContextFlags %#lx.\n",
10861 "Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
10863 ok(xs->CompactionMask == expected_compaction,
"Got unexpected CompactionMask %s.\n",
10865 for (
i = 0;
i < 4; ++
i)
10866 ok(((
ULONG *)&xs->YmmContext)[
i] == 0xcccccccc
10867 ||
broken(((
ULONG *)&xs->YmmContext)[
i] == test_extended_context_data[
i + 4]) ,
10868 "Got unexpected data %#lx, i %u.\n", ((
ULONG *)&xs->YmmContext)[
i],
i);
10871 xs->CompactionMask = 4;
10872 xs->Mask = compaction_enabled ? 0 : 4;
10874 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
10876 ok(
context->ContextFlags == expected_flags,
"Got unexpected ContextFlags %#lx.\n",
10880 ok(xs->CompactionMask == expected_compaction,
"Got unexpected CompactionMask %s.\n",
10883 for (
i = 4;
i < 8; ++
i)
10884 ok(
data[
i] == test_extended_context_data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10886 for (
i = 0;
i < 4; ++
i)
10887 ok(((
ULONG *)&xs->YmmContext)[
i] == test_extended_context_data[
i + 4],
10888 "Got unexpected data %#lx, i %u.\n", ((
ULONG *)&xs->YmmContext)[
i],
i);
10891 length =
sizeof(context_buffer);
10892 memset(context_buffer, 0xcc,
sizeof(context_buffer));
10895 memset(&xs->YmmContext, 0xcc,
sizeof(xs->YmmContext));
10896 ok(bret,
"Got unexpected bret %#x.\n", bret);
10899 pSetXStateFeaturesMask(
context, 0);
10906 *(
void **)(call_func_code_reset_ymm_state + call_func_offsets.func_addr) =
GetThreadContext;
10907 *(
void **)(call_func_code_reset_ymm_state + call_func_offsets.func_param1) = (
void *)
GetCurrentThread();
10908 *(
void **)(call_func_code_reset_ymm_state + call_func_offsets.func_param2) =
context;
10909 *(
void **)(call_func_code_reset_ymm_state + call_func_offsets.ymm0_save) =
data;
10910 memcpy(
code_mem, call_func_code_reset_ymm_state,
sizeof(call_func_code_reset_ymm_state));
10913 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
10919 ok(
context->ContextFlags == expected_flags,
"Got unexpected ContextFlags %#lx.\n",
10922 expected_compaction = compaction_enabled ? ((
ULONG64)1 << 63) | (xstate_supported_features & ~(
UINT64)3) : 0;
10925 ok((xs->Mask & supported_features) == (xsaveopt_enabled ? 0 : 4),
"Got unexpected Mask %#I64x.\n", xs->Mask);
10926 ok((xs->CompactionMask & (supported_features | ((
ULONG64)1 << 63))) == expected_compaction,
10927 "Got unexpected CompactionMask %s (expected %#I64x).\n",
wine_dbgstr_longlong(xs->CompactionMask), expected_compaction);
10929 for (
i = 4;
i < 8; ++
i)
10930 ok(!
data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10932 for (
i = 0;
i < 4; ++
i)
10933 ok(((
ULONG *)&xs->YmmContext)[
i] == ((xs->Mask & 4) ? 0 : 0xcccccccc)
10934 ||
broken(((
ULONG *)&xs->YmmContext)[
i] == test_extended_context_data[
i + 4]),
10935 "Got unexpected data %#lx, i %u.\n", ((
ULONG *)&xs->YmmContext)[
i],
i);
10940 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_addr) =
SetThreadContext;
10941 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_param1) = (
void *)
GetCurrentThread();
10942 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.func_param2) =
context;
10943 *(
void **)(call_func_code_set_ymm0 + call_func_offsets.ymm0_save) =
data;
10944 memcpy(
code_mem, call_func_code_set_ymm0,
sizeof(call_func_code_set_ymm0));
10950 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
10952 for (
i = 4;
i < 8; ++
i)
10953 ok(
data[
i] == test_extended_context_data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10958 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
10959 for (
i = 4;
i < 8; ++
i)
10960 ok(!
data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10964 skip(
"avx512 is not available, skipping test.\n");
10970 test_extended_context_modified_state =
FALSE;
10971 run_exception_test(test_extended_context_handler,
NULL, except_code_reset_ymm_state,
10973 for (
i = 0;
i < 8; ++
i)
10976 ok(!
data[
i] ||
broken(
i >= 4 &&
sizeof(
void *) == 4 &&
data[
i] == test_extended_context_spoil_data2[
i]),
10977 "Got unexpected data %#x, i %u.\n",
data[
i],
i);
10981 test_extended_context_modified_state =
TRUE;
10982 run_exception_test(test_extended_context_handler,
NULL, except_code_set_ymm0,
10985 for (
i = 0;
i < 8; ++
i)
10986 ok(
data[
i] == test_extended_context_data[
i],
"Got unexpected data %#x, i %u.\n",
data[
i],
i);
10990 ok(!!
thread,
"Failed to create thread.\n");
10994 ok(bret,
"Got unexpected bret %#x.\n", bret);
10995 memset(&xs->YmmContext, 0xcc,
sizeof(xs->YmmContext));
10998 pSetXStateFeaturesMask(
context, 4);
11001 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11003 ok((xs->Mask & supported_features) == (xsaveopt_enabled ? 0 : 4),
"Got unexpected Mask %#I64x.\n", xs->Mask);
11004 ok((xs->CompactionMask & supported_compaction_mask) == expected_compaction,
11005 "Got unexpected CompactionMask %I64x, expected %I64x.\n", xs->CompactionMask,
11006 expected_compaction);
11008 for (
i = 0;
i < 16 * 4; ++
i)
11009 ok(((
ULONG *)&xs->YmmContext)[
i] == ((xs->Mask & 4) ? 0 : 0xcccccccc),
11010 "Got unexpected value %#lx, i %u.\n", ((
ULONG *)&xs->YmmContext)[
i],
i);
11012 pSetXStateFeaturesMask(
context, 4);
11013 memset(&xs->YmmContext, 0,
sizeof(xs->YmmContext));
11015 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11017 memset(&xs->YmmContext, 0xcc,
sizeof(xs->YmmContext));
11019 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11020 ok(!(xs->Mask & supported_features) ||
broken((xs->Mask & supported_features) == 4),
"Got unexpected Mask %s.\n",
11022 ok((xs->CompactionMask & supported_compaction_mask) == expected_compaction,
"Got unexpected CompactionMask %s.\n",
11024 for (
i = 0;
i < 16 * 4; ++
i)
11025 ok(((
ULONG *)&xs->YmmContext)[
i] == 0xcccccccc ||
broken(xs->Mask == 4 && !((
ULONG *)&xs->YmmContext)[
i]),
11026 "Got unexpected value %#lx, i %u.\n", ((
ULONG *)&xs->YmmContext)[
i],
i);
11028 pSetXStateFeaturesMask(
context, 4);
11029 memset(&xs->YmmContext, 0x28,
sizeof(xs->YmmContext));
11031 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11032 memset(&xs->YmmContext, 0xcc,
sizeof(xs->YmmContext));
11034 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11036 ok((xs->CompactionMask & supported_compaction_mask) == expected_compaction,
"Got unexpected CompactionMask %s.\n",
11038 for (
i = 0;
i < 16 * 4; ++
i)
11039 ok(((
ULONG *)&xs->YmmContext)[
i] == 0x28282828,
"Got unexpected value %#lx, i %u.\n",
11040 ((
ULONG *)&xs->YmmContext)[
i],
i);
11042 wait_for_thread_next_suspend(
thread);
11045 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11046 pSetXStateFeaturesMask(
context, 4);
11047 memset(&xs->YmmContext, 0x48,
sizeof(xs->YmmContext));
11049 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11051 wait_for_thread_next_suspend(
thread);
11053 memset(&xs->YmmContext, 0xcc,
sizeof(xs->YmmContext));
11055 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11058 for (
i = 0;
i < 4; ++
i)
11059 ok(((
ULONG *)&xs->YmmContext)[
i] == 0x68686868,
"Got unexpected value %#lx, i %u.\n",
11060 ((
ULONG *)&xs->YmmContext)[
i],
i);
11062 wait_for_thread_next_suspend(
thread);
11064 memset(&xs->YmmContext, 0xcc,
sizeof(xs->YmmContext));
11066 ok(bret,
"Got unexpected bret %#x, GetLastError() %lu.\n", bret,
GetLastError());
11067 todo_wine_if (!xsaveopt_enabled &&
sizeof(
void *) != 4)
11068 ok((xs->
Mask & supported_features) == (xsaveopt_enabled ? 0 : 4)
11069 || (
sizeof(
void *) == 4 && (xs->
Mask & supported_features) == 4),
11071 if ((xs->Mask & supported_features) == 4)
11073 for (i = 0; i < 8 * sizeof(void *); ++i)
11074 ok(((ULONG *)&xs->YmmContext)[i] == 0,
11075 "Got unexpected value %#lx, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
11076 for (; i < 16 * 4; ++i)
11077 ok(((ULONG *)&xs->YmmContext)[i] == 0x48484848,
11078 "Got unexpected value %#lx, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
11082 for (i = 0; i < 16 * 4; ++i)
11083 ok(((ULONG *)&xs->YmmContext)[i] == 0xcccccccc,
11084 "Got unexpected value %#lx, i %u.\n", ((ULONG *)&xs->YmmContext)[i], i);
11087 if (compaction_enabled && enabled_features & ((ULONG64)1 << XSTATE_AVX512_KMASK))
11089 ULONG64 saved_mask;
11092 saved_mask = xs->CompactionMask;
11093 xs->Mask = XSTATE_MASK_GSSE;
11094 xs->CompactionMask = 0x8000000000000000 | xs->Mask;
11095 *(ULONG *)&xs->YmmContext = 0x11111111;
11096 bret = SetThreadContext(thread, context);
11097 ok(bret, "Got unexpected bret %#x, GetLastError() %lu.\n", bret, GetLastError());
11099 xs->Mask = (ULONG64)1 << XSTATE_AVX512_KMASK;
11100 xs->CompactionMask = 0x8000000000000000 | xs->Mask;
11101 *(ULONG *)&xs->YmmContext = 0x22222222;
11102 bret = SetThreadContext(thread, context);
11103 ok(bret, "Got unexpected bret %#x, GetLastError() %lu.\n", bret, GetLastError());
11105 xs->CompactionMask = saved_mask;
11106 bret = GetThreadContext(thread, context);
11107 ok(bret, "Got unexpected bret %#x, GetLastError() %lu.\n", bret, GetLastError());
11109 todo_wine_if(xs->Mask == XSTATE_MASK_GSSE)
11110 ok((xs->Mask & (XSTATE_MASK_GSSE | ((ULONG64)1 << XSTATE_AVX512_KMASK)))
11111 == (XSTATE_MASK_GSSE | ((ULONG64)1 << XSTATE_AVX512_KMASK)), "got Mask %#I64x.\n", xs->Mask);
11112 d = pLocateXStateFeature(context, XSTATE_AVX, NULL);
11113 ok(!!d, "Got NULL.\n");
11114 ok(*d == 0x11111111, "got %#lx.\n", *d);
11116 d = pLocateXStateFeature(context, XSTATE_AVX512_KMASK, NULL);
11117 ok(!!d, "Got NULL.\n");
11118 todo_wine ok(*d == 0x22222222, "got %#lx.\n", *d);
11122 skip("avx512 is not available, skipping test.\n");
11125 bret = ResumeThread(thread);
11126 ok(bret, "Got unexpected bret %#x, GetLastError() %lu.\n", bret, GetLastError());
11128 WaitForSingleObject(thread, INFINITE);
11129 CloseHandle(thread);
11132struct modified_range
11138#define check_changes_in_range(a, b, c, d) check_changes_in_range_(__FILE__, __LINE__, a, b, c, d)
11139static void check_changes_in_range_(const char *file, unsigned int line, const BYTE *p,
11140 const struct modified_range *range, ULONG flags, unsigned int length)
11142 ULONG range_flag, flag;
11143 unsigned int once = 0;
11147 for (i = 0; i < length; i++)
11149 if (i == range->start)
11151 range_flag = range->flag;
11155 if ((flag = range_flag) == ~0)
11158 if (flag & 0x80000000)
11160 if (flag & flags && p[i] == 0xcc)
11163 ok(broken(1), "Matched broken result at %#x, flags %#lx.\n", i, flags);
11169 if (flag & flags && p[i] != 0xcc)
11171 ok_(file, line)(0, "Got unexpected byte %#x at %#x, flags %#lx.\n", p[i], i, flags);
11174 else if (!(flag & flags) && p[i] != 0xdd)
11176 ok_(file, line)(0, "Got unexpected byte %#x at %#x, flags %#lx.\n", p[i], i, flags);
11180 ok_(file, line)(1, "Range matches.\n");
11183static void test_copy_context(void)
11185 static struct modified_range ranges_amd64[] =
11187 {0x30, ~0}, {0x38, 0x1}, {0x3a, 0x4}, {0x42, 0x1}, {0x48, 0x10}, {0x78, 0x2}, {0x98, 0x1},
11188 {0xa0, 0x2}, {0xf8, 0x1}, {0x100, 0x8}, {0x2a0, 0x80000008}, {0x4b0, 0x10}, {0x4d0, ~0},
11189 {0x4e8, 0}, {0x500, ~0}, {0x640, 0}, {0x1000, 0},
11191 static struct modified_range ranges_x86[] =
11193 {0x0, ~0}, {0x4, 0x10}, {0x1c, 0x8}, {0x8c, 0x4}, {0x9c, 0x2}, {0xb4, 0x1}, {0xcc, 0x20}, {0x1ec, 0x80000020},
11194 {0x2cc, ~0}, {0x440, 0}, {0x1000, 0},
11196 static const struct modified_range single_range[] =
11198 {0x0, 0x1}, {0x1000, 0},
11201 static const ULONG tests[] =
11204 CONTEXT_AMD64_CONTROL,
11205 CONTEXT_AMD64_INTEGER,
11206 CONTEXT_AMD64_SEGMENTS,
11207 CONTEXT_AMD64_FLOATING_POINT,
11208 CONTEXT_AMD64_DEBUG_REGISTERS,
11209 CONTEXT_AMD64_FULL,
11210 CONTEXT_AMD64_XSTATE,
11213 CONTEXT_I386_CONTROL,
11214 CONTEXT_I386_INTEGER,
11215 CONTEXT_I386_SEGMENTS,
11216 CONTEXT_I386_FLOATING_POINT,
11217 CONTEXT_I386_DEBUG_REGISTERS,
11218 CONTEXT_I386_EXTENDED_REGISTERS,
11219 CONTEXT_I386_XSTATE,
11222 static const ULONG arch_flags[] = {CONTEXT_AMD64, CONTEXT_i386};
11224 DECLSPEC_ALIGN(64) BYTE src_context_buffer[4096];
11225 DECLSPEC_ALIGN(64) BYTE dst_context_buffer[4096];
11226 ULONG64 enabled_features, expected_compaction;
11227 unsigned int context_length, flags_offset, i;
11228 CONTEXT_EX *src_ex, *dst_ex;
11229 XSTATE *dst_xs, *src_xs;
11230 BOOL compaction, bret;
11231 CONTEXT *src, *dst;
11236 if (!pRtlCopyExtendedContext)
11238 win_skip("RtlCopyExtendedContext is not available.\n");
11242 if (!pRtlGetEnabledExtendedFeatures)
11244 win_skip("RtlGetEnabledExtendedFeatures is not available.\n");
11248 enabled_features = pRtlGetEnabledExtendedFeatures(~(ULONG64)0);
11250 memset(dst_context_buffer, 0xdd, sizeof(dst_context_buffer));
11251 memset(src_context_buffer, 0xcc, sizeof(src_context_buffer));
11253 status = pRtlInitializeExtendedContext(src_context_buffer, CONTEXT_ALL | CONTEXT_XSTATE, &src_ex);
11256 src = pRtlLocateLegacyContext(src_ex, NULL);
11257 dst = (CONTEXT *)dst_context_buffer;
11258 dst->ContextFlags = CONTEXT_ALL;
11259 status = pRtlCopyContext(dst, dst->ContextFlags, src);
11260 ok(!status, "Got status %#lx.\n", status);
11261 check_changes_in_range((BYTE *)dst, CONTEXT_ALL & CONTEXT_AMD64 ? &ranges_amd64[0] : &ranges_x86[0],
11262 CONTEXT_ALL, sizeof(CONTEXT));
11266 ok(status == STATUS_NOT_SUPPORTED, "Got status %#lx.\n", status);
11267 skip("Extended context is not supported.\n");
11270 for (i = 0; i < ARRAY_SIZE(tests); ++i)
11273 flags_offset = (flags & CONTEXT_AMD64) ? offsetof(AMD64_CONTEXT,ContextFlags)
11274 : offsetof(I386_CONTEXT,ContextFlags);
11276 memset(dst_context_buffer, 0xdd, sizeof(dst_context_buffer));
11277 memset(src_context_buffer, 0xcc, sizeof(src_context_buffer));
11279 status = pRtlInitializeExtendedContext(src_context_buffer, flags, &src_ex);
11280 if (enabled_features || !(flags & 0x40))
11282 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11286 ok(status == STATUS_NOT_SUPPORTED, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11289 status = pRtlInitializeExtendedContext(dst_context_buffer, flags, &dst_ex);
11290 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11292 src = pRtlLocateLegacyContext(src_ex, NULL);
11293 dst = pRtlLocateLegacyContext(dst_ex, NULL);
11295 *(DWORD *)((BYTE *)dst + flags_offset) = 0;
11296 *(DWORD *)((BYTE *)src + flags_offset) = 0;
11298 context_length = dst_ex->All.Length;
11302 src_xs = (XSTATE *)((BYTE *)src_ex + src_ex->XState.Offset);
11303 memset(src_xs, 0xcc, src_ex->XState.Length);
11304 src_xs->Mask = enabled_features & ~(ULONG64)4;
11305 src_xs->CompactionMask = ~(ULONG64)0;
11306 if (flags & CONTEXT_AMD64)
11307 ranges_amd64[ARRAY_SIZE(ranges_amd64) - 2].start = 0x640 + src_ex->XState.Length - sizeof(XSTATE);
11309 ranges_x86[ARRAY_SIZE(ranges_x86) - 2].start = 0x440 + src_ex->XState.Length - sizeof(XSTATE);
11312 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11313 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11315 check_changes_in_range((BYTE *)dst, flags & CONTEXT_AMD64 ? &ranges_amd64[0] : &ranges_x86[0],
11316 flags, context_length);
11318 ok(*(DWORD *)((BYTE *)dst + flags_offset) == flags, "Got unexpected ContextFlags %#lx, flags %#lx.\n",
11319 *(DWORD *)((BYTE *)dst + flags_offset), flags);
11321 memset(dst_context_buffer, 0xdd, sizeof(dst_context_buffer));
11322 status = pRtlInitializeExtendedContext(dst_context_buffer, flags, &dst_ex);
11323 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11324 *(DWORD *)((BYTE *)src + flags_offset) = 0;
11325 *(DWORD *)((BYTE *)dst + flags_offset) = 0;
11326 SetLastError(0xdeadbeef);
11327 status = pRtlCopyContext(dst, flags | 0x40, src);
11328 ok(status == (enabled_features ? STATUS_INVALID_PARAMETER : STATUS_NOT_SUPPORTED)
11329 || broken(status == STATUS_INVALID_PARAMETER),
11330 "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11331 ok(*(DWORD *)((BYTE *)dst + flags_offset) == 0, "Got unexpected ContextFlags %#lx, flags %#lx.\n",
11332 *(DWORD *)((BYTE *)dst + flags_offset), flags);
11333 check_changes_in_range((BYTE *)dst, flags & CONTEXT_AMD64 ? &ranges_amd64[0] : &ranges_x86[0],
11334 0, context_length);
11336 *(DWORD *)((BYTE *)dst + flags_offset) = flags & (CONTEXT_AMD64 | CONTEXT_i386);
11337 *(DWORD *)((BYTE *)src + flags_offset) = flags;
11338 status = pRtlCopyContext(dst, flags, src);
11340 ok((status == STATUS_BUFFER_OVERFLOW)
11341 || broken(!(flags & CONTEXT_NATIVE) && status == STATUS_INVALID_PARAMETER),
11342 "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11344 ok(!status || broken(!(flags & CONTEXT_NATIVE) && status == STATUS_INVALID_PARAMETER),
11345 "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11348 ok(*(DWORD *)((BYTE *)dst + flags_offset) == flags, "Got unexpected ContextFlags %#lx, flags %#lx.\n",
11349 *(DWORD *)((BYTE *)dst + flags_offset), flags);
11350 check_changes_in_range((BYTE *)dst, flags & CONTEXT_AMD64 ? &ranges_amd64[0] : &ranges_x86[0],
11351 flags, context_length);
11355 ok(*(DWORD *)((BYTE *)dst + flags_offset) == (flags & 0x110000),
11356 "Got unexpected ContextFlags %#lx, flags %#lx.\n",
11357 *(DWORD *)((BYTE *)dst + flags_offset), flags);
11358 check_changes_in_range((BYTE *)dst, flags & CONTEXT_AMD64 ? &ranges_amd64[0] : &ranges_x86[0],
11359 0, context_length);
11363 for (i = 0; i < ARRAY_SIZE(arch_flags); ++i)
11365 flags = arch_flags[i] | 0x42;
11366 flags_offset = (flags & CONTEXT_AMD64) ? offsetof(AMD64_CONTEXT,ContextFlags)
11367 : offsetof(I386_CONTEXT,ContextFlags);
11368 context_length = (flags & CONTEXT_AMD64) ? sizeof(AMD64_CONTEXT) : sizeof(I386_CONTEXT);
11370 memset(dst_context_buffer, 0xdd, sizeof(dst_context_buffer));
11371 memset(src_context_buffer, 0xcc, sizeof(src_context_buffer));
11372 length = sizeof(src_context_buffer);
11373 bret = pInitializeContext(src_context_buffer, flags, &src, &length);
11374 ok(bret, "Got unexpected bret %#x, flags %#lx.\n", bret, flags);
11376 length = sizeof(dst_context_buffer);
11377 bret = pInitializeContext(dst_context_buffer, flags, &dst, &length);
11378 ok(bret, "Got unexpected bret %#x, flags %#lx.\n", bret, flags);
11380 dst_ex = (CONTEXT_EX *)((BYTE *)dst + context_length);
11381 src_ex = (CONTEXT_EX *)((BYTE *)src + context_length);
11383 dst_xs = (XSTATE *)((BYTE *)dst_ex + dst_ex->XState.Offset);
11384 src_xs = (XSTATE *)((BYTE *)src_ex + src_ex->XState.Offset);
11386 *(DWORD *)((BYTE *)dst + flags_offset) = 0;
11387 *(DWORD *)((BYTE *)src + flags_offset) = 0;
11389 compaction = !!(src_xs->CompactionMask & ((ULONG64)1 << 63));
11390 expected_compaction = (compaction ? ((ULONG64)1 << (ULONG64)63) | enabled_features : 0);
11392 memset(&src_xs->YmmContext, 0xcc, sizeof(src_xs->YmmContext));
11393 src_xs->CompactionMask = ~(ULONG64)0;
11396 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11397 dst_xs->CompactionMask = 0xdddddddddddddddd;
11398 dst_xs->Mask = 0xdddddddddddddddd;
11399 dst_ex->XState.Length = 0;
11400 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11401 ok(status == (enabled_features ? STATUS_BUFFER_OVERFLOW : STATUS_NOT_SUPPORTED),
11402 "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11404 if (!enabled_features)
11407 ok(*(DWORD *)((BYTE *)dst + flags_offset) == flags, "Got unexpected ContextFlags %#lx, flags %#lx.\n",
11408 *(DWORD *)((BYTE *)dst + flags_offset), flags);
11410 src_xs->Mask = ~(ULONG64)0;
11412 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11413 dst_xs->CompactionMask = 0xdddddddddddddddd;
11414 dst_xs->Mask = 0xdddddddddddddddd;
11415 dst_ex->XState.Length = 0;
11416 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11417 ok(status == STATUS_BUFFER_OVERFLOW, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11418 ok(*(DWORD *)((BYTE *)dst + flags_offset) == flags, "Got unexpected ContextFlags %#lx, flags %#lx.\n",
11419 *(DWORD *)((BYTE *)dst + flags_offset), flags);
11421 ok(dst_xs->Mask == 0xdddddddddddddddd, "Got unexpected Mask %s.\n",
11422 wine_dbgstr_longlong(dst_xs->Mask));
11423 ok(dst_xs->CompactionMask == 0xdddddddddddddddd, "Got unexpected CompactionMask %s.\n",
11424 wine_dbgstr_longlong(dst_xs->CompactionMask));
11425 check_changes_in_range((BYTE *)&dst_xs->YmmContext, single_range, 0, sizeof(dst_xs->YmmContext));
11428 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11429 dst_xs->CompactionMask = 0xdddddddddddddddd;
11430 dst_xs->Mask = 0xdddddddddddddddd;
11431 dst_ex->XState.Length = offsetof(XSTATE, YmmContext);
11432 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11433 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11434 ok(*(DWORD *)((BYTE *)dst + flags_offset) == flags, "Got unexpected ContextFlags %#lx, flags %#lx.\n",
11435 *(DWORD *)((BYTE *)dst + flags_offset), flags);
11436 ok(dst_xs->Mask == 0, "Got unexpected Mask %s.\n",
11437 wine_dbgstr_longlong(dst_xs->Mask));
11438 ok(dst_xs->CompactionMask == expected_compaction,
11439 "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(dst_xs->CompactionMask));
11440 check_changes_in_range((BYTE *)&dst_xs->YmmContext, single_range, 0, sizeof(dst_xs->YmmContext));
11442 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11443 dst_xs->CompactionMask = 0xdddddddddddddddd;
11444 dst_xs->Mask = 0xdddddddddddddddd;
11445 dst_ex->XState.Length = sizeof(XSTATE);
11446 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11447 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11448 ok(dst_xs->Mask == 0, "Got unexpected Mask %s.\n",
11449 wine_dbgstr_longlong(dst_xs->Mask));
11450 ok(dst_xs->CompactionMask == expected_compaction,
11451 "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(dst_xs->CompactionMask));
11452 check_changes_in_range((BYTE *)&dst_xs->YmmContext, single_range, 0, sizeof(dst_xs->YmmContext));
11455 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11456 dst_xs->CompactionMask = 0xdddddddddddddddd;
11457 dst_xs->Mask = 0xdddddddddddddddd;
11458 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11459 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11460 ok(dst_xs->Mask == 4, "Got unexpected Mask %s.\n",
11461 wine_dbgstr_longlong(dst_xs->Mask));
11462 ok(dst_xs->CompactionMask == expected_compaction,
11463 "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(dst_xs->CompactionMask));
11464 check_changes_in_range((BYTE *)&dst_xs->YmmContext, single_range, 1, sizeof(dst_xs->YmmContext));
11467 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11468 dst_xs->CompactionMask = 0xdddddddddddddddd;
11469 dst_xs->Mask = 0xdddddddddddddddd;
11470 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11471 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11472 ok(dst_xs->Mask == 0, "Got unexpected Mask %s.\n",
11473 wine_dbgstr_longlong(dst_xs->Mask));
11474 ok(dst_xs->CompactionMask == expected_compaction,
11475 "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(dst_xs->CompactionMask));
11476 check_changes_in_range((BYTE *)&dst_xs->YmmContext, single_range, 0, sizeof(dst_xs->YmmContext));
11479 *(DWORD *)((BYTE *)src + flags_offset) = arch_flags[i];
11482 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11483 dst_xs->CompactionMask = 0xdddddddddddddddd;
11484 dst_xs->Mask = 0xdddddddddddddddd;
11485 status = pRtlCopyExtendedContext(dst_ex, flags, src_ex);
11486 ok(!status, "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11487 ok(dst_xs->Mask == 4, "Got unexpected Mask %s.\n",
11488 wine_dbgstr_longlong(dst_xs->Mask));
11489 ok(dst_xs->CompactionMask == expected_compaction,
11490 "Got unexpected CompactionMask %s.\n", wine_dbgstr_longlong(dst_xs->CompactionMask));
11491 check_changes_in_range((BYTE *)&dst_xs->YmmContext, single_range, 1, sizeof(dst_xs->YmmContext));
11494 memset(&dst_xs->YmmContext, 0xdd, sizeof(dst_xs->YmmContext));
11495 dst_xs->CompactionMask = 0xdddddddddddddddd;
11496 dst_xs->Mask = 0xdddddddddddddddd;
11497 status = pRtlCopyContext(dst, flags, src);
11498 ok(!status || broken(!(flags & CONTEXT_NATIVE) && status == STATUS_INVALID_PARAMETER),
11499 "Got unexpected status %#lx, flags %#lx.\n", status, flags);
11500 ok(dst_xs->Mask == 0xdddddddddddddddd || broken(dst_xs->Mask == 4), "Got unexpected Mask %s, flags %#lx.\n",
11501 wine_dbgstr_longlong(dst_xs->Mask), flags);
11502 ok(dst_xs->CompactionMask == 0xdddddddddddddddd || broken(dst_xs->CompactionMask == expected_compaction),
11503 "Got unexpected CompactionMask %s, flags %#lx.\n", wine_dbgstr_longlong(dst_xs->CompactionMask), flags);
11504 check_changes_in_range((BYTE *)&dst_xs->YmmContext, single_range,
11505 dst_xs->Mask == 4, sizeof(dst_xs->YmmContext));
11509#if defined(__i386__)
11510# define IP_REG(ctx) ctx.Eip
11512# define IP_REG(ctx) ctx.Rip
11515static volatile int exit_ip_test;
11516static DWORD WINAPI ip_test_thread_proc( void *param )
11519 while (!exit_ip_test);
11520 return ERROR_SUCCESS;
11523static void test_set_live_context(void)
11525 UINT_PTR old_ip, target;
11526 HANDLE thread, event;
11532 /* jmp to self at offset 0 and 4 */
11533 static const char target_code[] = {0xeb, 0xfe, 0x90, 0x90, 0xeb, 0xfe};
11535 target_ptr = VirtualAlloc( NULL, 65536, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
11536 memcpy( target_ptr, target_code, sizeof(target_code) );
11537 target = (UINT_PTR)target_ptr;
11539 event = CreateEventW( NULL, TRUE, FALSE, NULL );
11540 thread = CreateThread( NULL, 65536, ip_test_thread_proc, event, 0, NULL );
11541 ok( thread != NULL, "Failed to create thread: %lx\n", GetLastError() );
11542 res = WaitForSingleObject( event, 1000 );
11543 ok( !res, "wait returned: %ld\n", res );
11544 CloseHandle( event );
11546 memset( &ctx, 0, sizeof(ctx) );
11547 ctx.ContextFlags = CONTEXT_ALL;
11548 res = GetThreadContext( thread, &ctx );
11549 ok( res, "Failed to get thread context: %lx\n", GetLastError() );
11550 old_ip = IP_REG(ctx);
11552 IP_REG(ctx) = target;
11553 res = SetThreadContext( thread, &ctx );
11554 ok( res, "Failed to set thread context: %lx\n", GetLastError() );
11556 for (i = 0; i < 10; i++)
11558 IP_REG(ctx) = target;
11559 res = SetThreadContext( thread, &ctx );
11560 ok( res, "Failed to set thread context: %lx\n", GetLastError() );
11562 ctx.ContextFlags = CONTEXT_ALL;
11563 res = GetThreadContext( thread, &ctx );
11564 ok( res, "Failed to get thread context: %lx\n", GetLastError() );
11565 ok( IP_REG(ctx) == target, "IP = %p, expected %p\n", (void *)IP_REG(ctx), target_ptr );
11567 IP_REG(ctx) = target + 4;
11568 res = SetThreadContext( thread, &ctx );
11569 ok( res, "Failed to set thread context: %lx\n", GetLastError()) ;
11571 ctx.ContextFlags = CONTEXT_ALL;
11572 res = GetThreadContext( thread, &ctx );
11573 ok( res, "Failed to get thread context: %lx\n", GetLastError() );
11574 ok( IP_REG(ctx) == target + 4, "IP = %p, expected %p\n", (void *)IP_REG(ctx), target_ptr + 4 );
11578 ctx.ContextFlags = CONTEXT_ALL;
11579 IP_REG(ctx) = old_ip;
11580 res = SetThreadContext( thread, &ctx );
11581 ok( res, "Failed to restore thread context: %lx\n", GetLastError() );
11583 res = WaitForSingleObject( thread, 1000 );
11584 ok( !res, "wait returned: %ld\n", res );
11586 VirtualFree( target_ptr, 0, MEM_RELEASE );
11590static void test_backtrace(void)
11592 void *buffer[1024];
11593 WCHAR name[MAX_PATH];
11595 ULONG hash, hash_expect;
11596 int i, count = RtlCaptureStackBackTrace( 0, 1024, buffer, &hash );
11598 ok( count > 0, "got %u entries\n", count );
11599 for (i = hash_expect = 0; i < count; i++) hash_expect += (ULONG_PTR)buffer[i];
11600 ok( hash == hash_expect, "hash mismatch %lx / %lx\n", hash, hash_expect );
11601 pRtlPcToFileHeader( buffer[0], &module );
11602 if (is_arm64ec && module == hntdll) /* Windows arm64ec has an extra frame for the entry thunk */
11604 ok( count > 1, "wrong count %u\n", count );
11605 pRtlPcToFileHeader( buffer[1], &module );
11607 GetModuleFileNameW( module, name, ARRAY_SIZE(name) );
11608 ok( module == GetModuleHandleA(0), "wrong module %p %s / %p for %p\n",
11609 module, debugstr_w(name), GetModuleHandleA(0), buffer[0]);
11611 if (pRtlGetCallersAddress)
11613 void *caller, *parent;
11615 caller = parent = (void *)0xdeadbeef;
11616 pRtlGetCallersAddress( &caller, &parent );
11617 ok( caller == (count > 1 ? buffer[1] : NULL) || broken(is_arm64ec), /* caller is entry thunk */
11618 "wrong caller %p / %p\n", caller, buffer[1] );
11619 ok( parent == (count > 2 ? buffer[2] : NULL), "wrong parent %p / %p\n", parent, buffer[2] );
11621 else win_skip( "RtlGetCallersAddress not supported\n" );
11623 if (count && !buffer[count - 1]) count--; /* win11 32-bit */
11624 if (count <= 1) return;
11625 pRtlPcToFileHeader( buffer[count - 1], &module );
11626 GetModuleFileNameW( module, name, ARRAY_SIZE(name) );
11627 ok( module == hntdll, "wrong module %p %s for frame %u %p\n",
11628 module, debugstr_w(name), count - 1, buffer[count - 1] );
11631struct context_exception_request_thread_param
11633 LONG volatile sync;
11636static volatile int *p_context_exception_request_value;
11637struct context_exception_request_thread_param *context_exception_request_param;
11639static LONG CALLBACK test_context_exception_request_handler( EXCEPTION_POINTERS *info )
11641 PEXCEPTION_RECORD rec = info->ExceptionRecord;
11642 CONTEXT *c = info->ContextRecord;
11645 ok( !(c->ContextFlags & (CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE
11646 | CONTEXT_EXCEPTION_ACTIVE)), "got %#lx.\n", c->ContextFlags );
11648 ok( rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION, "got %#lx.\n", rec->ExceptionCode );
11649 VirtualProtect( (void *)p_context_exception_request_value, sizeof(*p_context_exception_request_value),
11650 PAGE_READWRITE, &old_prot );
11652 WriteRelease( &context_exception_request_param->sync, 5 );
11653 while (ReadAcquire( &context_exception_request_param->sync ) != 6)
11656 return EXCEPTION_CONTINUE_EXECUTION;
11660static const BYTE call_func64_code[] =
11662 0x58, /* pop %eax */
11663 0x0e, /* push %cs */
11664 0x50, /* push %eax */
11665 0x6a, 0x33, /* push $0x33 */
11666 0xe8, 0x00, 0x00, 0x00, 0x00, /* call 1f */
11667 0x83, 0x04, 0x24, 0x05, /* 1: addl $0x5,(%esp) */
11669 /* in 64-bit mode: */
11670 0x4c, 0x87, 0xf4, /* xchg %r14,%rsp */
11671 0x55, /* push %rbp */
11672 0x48, 0x89, 0xe5, /* mov %rsp,%rbp */
11673 0x56, /* push %rsi */
11674 0x57, /* push %rdi */
11675 0x41, 0x8b, 0x4e, 0x10, /* mov 0x10(%r14),%ecx */
11676 0x41, 0x8b, 0x76, 0x14, /* mov 0x14(%r14),%esi */
11677 0x67, 0x8d, 0x04, 0xcd, 0, 0, 0, 0, /* lea 0x0(,%ecx,8),%eax */
11678 0x83, 0xf8, 0x20, /* cmp $0x20,%eax */
11679 0x7d, 0x05, /* jge 1f */
11680 0xb8, 0x20, 0x00, 0x00, 0x00, /* mov $0x20,%eax */
11681 0x48, 0x29, 0xc4, /* 1: sub %rax,%rsp */
11682 0x48, 0x83, 0xe4, 0xf0, /* and $~15,%rsp */
11683 0x48, 0x89, 0xe7, /* mov %rsp,%rdi */
11684 0xf3, 0x48, 0xa5, /* rep movsq */
11685 0x48, 0x8b, 0x0c, 0x24, /* mov (%rsp),%rcx */
11686 0x48, 0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%rsp),%rdx */
11687 0x4c, 0x8b, 0x44, 0x24, 0x10, /* mov 0x10(%rsp),%r8 */
11688 0x4c, 0x8b, 0x4c, 0x24, 0x18, /* mov 0x18(%rsp),%r9 */
11689 0x41, 0xff, 0x56, 0x08, /* callq *0x8(%r14) */
11690 0x48, 0x8d, 0x65, 0xf0, /* lea -0x10(%rbp),%rsp */
11691 0x5f, /* pop %rdi */
11692 0x5e, /* pop %rsi */
11693 0x5d, /* pop %rbp */
11694 0x4c, 0x87, 0xf4, /* xchg %r14,%rsp */
11698static NTSTATUS call_func64( ULONG64 func64, int nb_args, ULONG64 *args, void *code_mem )
11700 NTSTATUS (WINAPI *func)( ULONG64 func64, int nb_args, ULONG64 *args ) = code_mem;
11702 memcpy( code_mem, call_func64_code, sizeof(call_func64_code) );
11703 return func( func64, nb_args, args );
11707static DWORD WINAPI test_context_exception_request_thread( void *arg )
11710 static BYTE wait_sync_x64_code[] =
11712 0x89, 0x11, /* mov %edx,(%rcx) */
11713 0x83, 0xc2, 0x01, /* add $0x1,%edx */
11714 0x0f, 0x1f, 0x00, /* 1: nopl (%rax) */
11715 0x8b, 0x01, /* mov (%rcx),%eax */
11716 0x39, 0xd0, /* cmp %edx,%eax */
11717 0x75, 0xfa, /* jne 1b */
11722 struct context_exception_request_thread_param *p = arg;
11723 void *vectored_handler;
11725 context_exception_request_param = p;
11726 vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, test_context_exception_request_handler );
11727 ok( !!vectored_handler, "failed.\n" );
11729 WriteRelease( &p->sync, 1 );
11730 while (ReadAcquire( &p->sync ) != 2)
11733 WaitForSingleObject( p->event, INFINITE );
11736 memcpy( (char *)code_mem + 1024, wait_sync_x64_code, sizeof(wait_sync_x64_code) );
11737 args[0] = (ULONG_PTR)&p->sync;
11739 if (is_wow64 && !old_wow64) call_func64( (ULONG64)(ULONG_PTR)code_mem + 1024, ARRAY_SIZE(args), args, code_mem );
11742 p_context_exception_request_value = VirtualAlloc( NULL, sizeof(*p_context_exception_request_value),
11743 MEM_RESERVE | MEM_COMMIT, PAGE_READONLY );
11744 ok( !!p_context_exception_request_value, "got NULL.\n" );
11745 *p_context_exception_request_value = 1;
11746 ok( *p_context_exception_request_value == 1, "got %d.\n", *p_context_exception_request_value );
11747 VirtualFree( (void *)p_context_exception_request_value, 0, MEM_RELEASE );
11748 pRtlRemoveVectoredExceptionHandler( vectored_handler );
11752 if (is_wow64 && !old_wow64) call_func64( (ULONG64)(ULONG_PTR)code_mem + 1024, ARRAY_SIZE(args), args, code_mem );
11758static void test_context_exception_request(void)
11760 struct context_exception_request_thread_param p;
11761 DWORD expected_flags;
11766 if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
11768 skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found.\n" );
11772 c.ContextFlags = CONTEXT_CONTROL;
11773 ret = GetThreadContext( GetCurrentThread(), &c );
11774 ok( ret, "got error %lu.\n", GetLastError() );
11775 ok( c.ContextFlags == CONTEXT_CONTROL, "got %#lx.\n", c.ContextFlags );
11777 expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE;
11779 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11780 ret = GetThreadContext( GetCurrentThread(), &c );
11781 ok( ret, "got error %lu.\n", GetLastError() );
11782 ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == 0x10001 ) /* Win7 WoW64 */,
11783 "got %#lx.\n", c.ContextFlags );
11784 if (c.ContextFlags == 0x10001)
11786 win_skip( "Old WoW64 behaviour, skipping tests.\n" );
11790 ret = DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &thread, 0, TRUE, DUPLICATE_SAME_ACCESS );
11791 ok( ret, "got error %lu.\n", GetLastError() );
11792 c.ContextFlags = expected_flags | CONTEXT_EXCEPTION_REQUEST;
11794 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11795 ret = GetThreadContext( thread, &c );
11796 ok( ret, "got error %lu.\n", GetLastError() );
11797 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11798 CloseHandle( thread );
11800 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE
11801 | CONTEXT_EXCEPTION_ACTIVE;
11802 ret = GetThreadContext( GetCurrentThread(), &c );
11803 ok( ret, "got error %lu.\n", GetLastError() );
11804 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11806 p.event = CreateEventW( NULL, FALSE, FALSE, NULL );
11807 thread = CreateThread( NULL, 0, test_context_exception_request_thread, &p, CREATE_SUSPENDED, NULL );
11808 ok( !!thread, "got error %lu.\n", GetLastError() );
11810 expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE;
11812 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11813 ret = GetThreadContext( thread, &c );
11814 ok( ret, "got error %lu.\n", GetLastError() );
11815 ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == (CONTEXT_CONTROL
11816 | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING)) /* Win7 64 */, "got %#lx.\n", c.ContextFlags );
11819 ResumeThread(thread);
11821 while (ReadAcquire( &p.sync ) != 1)
11823 /* thread is in user code. */
11824 SuspendThread( thread );
11826 c.ContextFlags = CONTEXT_CONTROL;
11827 ret = GetThreadContext( thread, &c );
11828 ok( ret, "got error %lu.\n", GetLastError() );
11829 ok( c.ContextFlags == CONTEXT_CONTROL, "got %#lx.\n", c.ContextFlags );
11831 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE;
11832 ret = SetThreadContext( thread, &c );
11833 ok( ret, "got error %lu.\n", GetLastError() );
11835 expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING;
11837 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11838 ret = GetThreadContext( thread, &c );
11839 ok( ret, "got error %lu.\n", GetLastError() );
11840 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11842 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE
11843 | CONTEXT_EXCEPTION_ACTIVE;
11844 ret = GetThreadContext( thread, &c );
11845 ok( ret, "got error %lu.\n", GetLastError() );
11846 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11848 ResumeThread(thread);
11849 WriteRelease( &p.sync, 2 );
11850 /* Try to make sure the thread entered WaitForSingleObject(). */
11853 expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE;
11855 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11856 ret = GetThreadContext( thread, &c );
11857 ok( ret, "got error %lu.\n", GetLastError() );
11858 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11860 c.ContextFlags = CONTEXT_CONTROL;
11861 ret = SetThreadContext( thread, &c );
11862 ok( ret, "got error %lu.\n", GetLastError() );
11864 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE
11865 | CONTEXT_EXCEPTION_ACTIVE;
11866 ret = GetThreadContext( thread, &c );
11867 ok( ret, "got error %lu.\n", GetLastError() );
11868 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11870 SetEvent( p.event );
11872 if (is_wow64 && !old_wow64)
11874 while (ReadAcquire( &p.sync ) != 3)
11876 /* thread is in x64 code. */
11878 expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE;
11880 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11881 ret = GetThreadContext( thread, &c );
11882 ok( ret, "got error %lu.\n", GetLastError() );
11883 ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags );
11885 WriteRelease( &p.sync, 4 );
11888 while (ReadAcquire( &p.sync ) != 5)
11891#if defined(__REACTOS__) && defined(__i386__) && !defined(__GNUC__)
11894 win_skip("Skipping on WOW64 with MSVC builds, because it makes the test crash\n");
11895 CloseHandle( thread );
11896 CloseHandle( p.event );
11901 expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING; // 0xC0010001
11903 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11904 ret = GetThreadContext( thread, &c );
11905 ok( ret, "got error %lu.\n", GetLastError() );
11907 if (GetNTVersion() < _WIN32_WINNT_VISTA)
11908 ok( c.ContextFlags == (expected_flags & ~CONTEXT_EXCEPTION_REPORTING), "got %#lx.\n", c.ContextFlags );
11911 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11913 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE
11914 | CONTEXT_EXCEPTION_ACTIVE;
11915 ret = GetThreadContext( thread, &c );
11916 ok( ret, "got error %lu.\n", GetLastError() );
11918 if (GetNTVersion() < _WIN32_WINNT_VISTA)
11919 ok( c.ContextFlags == (expected_flags | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE), "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags );
11922 ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
11924 WriteRelease( &p.sync, 6 );
11926 if (is_wow64 && !old_wow64)
11928 while (ReadAcquire( &p.sync ) != 7)
11930 /* thread is in x64 code. */
11932 expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE;
11934 c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST;
11935 ret = GetThreadContext( thread, &c );
11936 ok( ret, "got error %lu.\n", GetLastError() );
11937 ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags );
11939 WriteRelease( &p.sync, 8 );
11942 WaitForSingleObject( thread, INFINITE );
11943 CloseHandle( thread );
11944 CloseHandle( p.event );
11947START_TEST(exception)
11949 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
11950 hntdll = GetModuleHandleA("ntdll.dll");
11952 my_argc = winetest_get_mainargs( &my_argv );
11954 if (my_argc >= 3 && !strcmp(my_argv[2], "suspend_process"))
11956 suspend_process_proc();
11960 code_mem = VirtualAlloc(NULL, 65536, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
11962 trace("VirtualAlloc failed\n");
11966#define X(f) p##f = (void*)GetProcAddress(hntdll, #f)
11967 X(NtGetContextThread);
11968 X(NtSetContextThread);
11969 X(NtQueueApcThread);
11971 X(NtReadVirtualMemory);
11974 X(RtlRaiseException);
11975 X(RtlCaptureContext);
11976 X(NtTerminateProcess);
11977 X(RtlAddVectoredExceptionHandler);
11978 X(RtlRemoveVectoredExceptionHandler);
11979 X(RtlAddVectoredContinueHandler);
11980 X(RtlRemoveVectoredContinueHandler);
11981 X(RtlSetUnhandledExceptionFilter);
11982 X(NtQueryInformationThread);
11983 X(NtSetInformationProcess);
11984 X(NtSuspendProcess);
11985 X(NtRaiseException);
11986 X(NtResumeProcess);
11987 X(RtlGetUnloadEventTrace);
11988 X(RtlGetUnloadEventTraceEx);
11989 X(RtlGetEnabledExtendedFeatures);
11990 X(RtlGetExtendedContextLength);
11991 X(RtlGetExtendedContextLength2);
11992 X(RtlInitializeExtendedContext);
11993 X(RtlInitializeExtendedContext2);
11994 X(RtlLocateExtendedFeature);
11995 X(RtlLocateLegacyContext);
11996 X(RtlSetExtendedFeaturesMask);
11997 X(RtlGetExtendedFeaturesMask);
11998 X(RtlPcToFileHeader);
11999 X(RtlGetCallersAddress);
12001 X(RtlCopyExtendedContext);
12002 X(KiUserApcDispatcher);
12003 X(KiUserCallbackDispatcher);
12004 X(KiUserExceptionDispatcher);
12006 X(RtlRestoreContext);
12008 X(RtlAddFunctionTable);
12009 X(RtlDeleteFunctionTable);
12010 X(RtlGetNativeSystemInformation);
12014 if (pRtlGetNativeSystemInformation)
12016 SYSTEM_CPU_INFORMATION info;
12018 if (!pRtlGetNativeSystemInformation( SystemCpuInformation, &info, sizeof(info), &len ))
12019 is_arm64ec = (info.ProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64);
12024#define X(f) p##f = (void*)GetProcAddress(hkernel32, #f)
12026 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
12029 TEB64 *teb64 = ULongToPtr( NtCurrentTeb()->GdiBatchCount );
12033 PEB64 *peb64 = ULongToPtr(teb64->Peb);
12034 old_wow64 = !peb64->LdrData;
12038 X(InitializeContext);
12039 X(InitializeContext2);
12040 X(LocateXStateFeature);
12041 X(SetXStateFeaturesMask);
12042 X(GetXStateFeaturesMask);
12043 X(WaitForDebugEventEx);
12046 if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
12047 have_vectored_api = TRUE;
12049 skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
12051 my_argc = winetest_get_mainargs( &my_argv );
12056 if (strcmp(my_argv[2], "fastfail") == 0)
12058 __fastfail(strtoul(my_argv[3], NULL, 0));
12062 sscanf( my_argv[3], "%p", &addr );
12064 if (addr != &test_stage)
12066 skip( "child process not mapped at same address (%p/%p)\n", &test_stage, addr);
12070 /* child must be run under a debugger */
12071 if (!NtCurrentTeb()->Peb->BeingDebugged)
12073 ok(FALSE, "child process not being debugged?\n");
12077 if (pRtlRaiseException)
12079 test_stage = STAGE_RTLRAISE_NOT_HANDLED;
12080 run_rtlraiseexception_test(0x12345);
12081 run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
12082 run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
12083 test_stage = STAGE_RTLRAISE_HANDLE_LAST_CHANCE;
12084 run_rtlraiseexception_test(0x12345);
12085 run_rtlraiseexception_test(EXCEPTION_BREAKPOINT);
12086 run_rtlraiseexception_test(EXCEPTION_INVALID_HANDLE);
12088 else skip( "RtlRaiseException not found\n" );
12090 test_stage = STAGE_OUTPUTDEBUGSTRINGA_CONTINUE;
12092 test_outputdebugstring(FALSE, 0, FALSE, 0, 0);
12093 test_stage = STAGE_OUTPUTDEBUGSTRINGA_NOT_HANDLED;
12094 test_outputdebugstring(FALSE, 2, TRUE, 0, 0); /* is 2 a Windows bug? */
12095 test_stage = STAGE_OUTPUTDEBUGSTRINGW_CONTINUE;
12096 /* depending on value passed DebugContinue we can get the unicode exception or not */
12097 test_outputdebugstring(TRUE, 0, FALSE, 0, 1);
12098 test_stage = STAGE_OUTPUTDEBUGSTRINGW_NOT_HANDLED;
12099 /* depending on value passed DebugContinue we can get the unicode exception or not */
12100 test_outputdebugstring(TRUE, 2, TRUE, 0, 1); /* is 2 a Windows bug? */
12101 test_stage = STAGE_RIPEVENT_CONTINUE;
12103 test_stage = STAGE_RIPEVENT_NOT_HANDLED;
12105 test_stage = STAGE_SERVICE_CONTINUE;
12106 test_debug_service(0);
12107 test_stage = STAGE_SERVICE_NOT_HANDLED;
12108 test_debug_service(1);
12109 test_stage = STAGE_BREAKPOINT_CONTINUE;
12110 test_breakpoint(0);
12111 test_stage = STAGE_BREAKPOINT_NOT_HANDLED;
12112 test_breakpoint(1);
12113 test_stage = STAGE_EXCEPTION_INVHANDLE_CONTINUE;
12114 test_closehandle(0, (HANDLE)0xdeadbeef);
12115 test_closehandle(0, (HANDLE)0x7fffffff);
12116 test_stage = STAGE_EXCEPTION_INVHANDLE_NOT_HANDLED;
12117 test_closehandle(1, (HANDLE)0xdeadbeef);
12118 test_closehandle(1, (HANDLE)~(ULONG_PTR)6);
12119 test_stage = STAGE_NO_EXCEPTION_INVHANDLE_NOT_HANDLED; /* special cases */
12120 test_closehandle(0, 0);
12121 test_closehandle(0, INVALID_HANDLE_VALUE);
12122 test_closehandle(0, GetCurrentProcess());
12123 test_closehandle(0, GetCurrentThread());
12124 test_closehandle(0, (HANDLE)~(ULONG_PTR)2);
12125 test_closehandle(0, GetCurrentProcessToken());
12126 test_closehandle(0, GetCurrentThreadToken());
12127 test_closehandle(0, GetCurrentThreadEffectiveToken());
12128#if defined(__i386__) || defined(__x86_64__)
12129 test_stage = STAGE_XSTATE;
12130 test_debuggee_xstate();
12131 test_stage = STAGE_XSTATE_LEGACY_SSE;
12132 test_debuggee_xstate();
12133 test_stage = STAGE_SEGMENTS;
12134 test_debuggee_segments();
12137 /* rest of tests only run in parent */
12145 test_debug_registers();
12146 test_debug_service(1);
12147 test_simd_exceptions();
12148 test_fpu_exceptions();
12149 test_dpe_exceptions();
12151 test_extended_context();
12152 test_copy_context();
12153 test_set_live_context();
12154 test_hwbpt_in_syscall();
12155 test_instrumentation_callback();
12157#elif defined(__x86_64__)
12159#define X(f) p##f = (void*)GetProcAddress(hntdll, #f)
12160 X(__C_specific_handler);
12161 X(RtlWow64GetThreadContext);
12162 X(RtlWow64SetThreadContext);
12163 X(RtlWow64GetCpuAreaInfo);
12167 test_debug_registers();
12168 test_debug_registers_wow64();
12169 test_debug_service(1);
12170 test_simd_exceptions();
12172 test___C_specific_handler();
12173 test_restore_context();
12175 test_dpe_exceptions();
12176 test_wow64_context();
12177 test_nested_exception();
12178 test_collided_unwind();
12179 test_extended_context();
12180 test_copy_context();
12181 test_set_live_context();
12182 test_unwind_from_apc();
12183 test_syscall_clobbered_regs();
12184 test_raiseexception_regs();
12185 test_hwbpt_in_syscall();
12186 test_instrumentation_callback();
12187 test_direct_syscalls();
12189#elif defined(__aarch64__)
12193 test_nested_exception();
12194 test_collided_unwind();
12195 test_restore_context();
12196 test_mrs_currentel();
12198#elif defined(__arm__)
12200 test_nested_exception();
12201 test_collided_unwind();
12202 test_restore_context();
12206 test_KiUserExceptionDispatcher();
12207 test_KiUserApcDispatcher();
12208 test_KiUserCallbackDispatcher();
12209 test_rtlraiseexception();
12210 test_debugger(DBG_EXCEPTION_HANDLED, FALSE);
12211 test_debugger(DBG_CONTINUE, FALSE);
12212 test_debugger(DBG_EXCEPTION_HANDLED, TRUE);
12213 test_debugger(DBG_CONTINUE, TRUE);
12214 test_thread_context();
12215 test_outputdebugstring(FALSE, 1, FALSE, 0, 0);
12216 if (pWaitForDebugEventEx)
12218 test_outputdebugstring(TRUE, 1, FALSE, 1, 1);
12219 test_outputdebugstring_newmodel();
12222 skip("Unsupported new unicode debug string model\n");
12226 test_breakpoint(1);
12227 test_closehandle(0, (HANDLE)0xdeadbeef);
12228 /* Call of Duty WWII writes to BeingDebugged then closes an invalid handle,
12229 * crashing the game if an exception is raised. */
12230 NtCurrentTeb()->Peb->BeingDebugged = 0x98;
12231 test_closehandle(0, (HANDLE)0xdeadbeef);
12232 NtCurrentTeb()->Peb->BeingDebugged = 0;
12235 test_user_callback();
12236 test_vectored_continue_handler();
12237 test_suspend_thread();
12238 test_suspend_process();
12239 test_unload_trace();
12241 test_context_exception_request();
12242 VirtualFree(code_mem, 0, MEM_RELEASE);
#define STATUS_PRIVILEGE_NOT_HELD
std::map< E_MODULE, HMODULE > mod
COMPILER_DEPENDENT_UINT64 UINT64
static void startup(void)
NTSTATUS NTAPI NtCallbackReturn(_In_ PVOID Result, _In_ ULONG ResultLength, _In_ NTSTATUS CallbackStatus)
#define InterlockedIncrement
void dispatch(HANDLE hStopEvent)
union _UNWIND_CODE UNWIND_CODE
struct _UNWIND_INFO UNWIND_INFO
#define STATUS_ILLEGAL_INSTRUCTION
#define STATUS_INVALID_HANDLE
#define STATUS_NOT_SUPPORTED
#define ERROR_INSUFFICIENT_BUFFER
size_t const element_size
static WCHAR unknown[MAX_STRING_RESOURCE_LEN]
#define ReadProcessMemory(a, b, c, d, e)
@ ExceptionContinueSearch
@ ExceptionContinueExecution
#define ERROR_INVALID_PARAMETER
#define EXCEPTION_MAXIMUM_PARAMETERS
struct _EXCEPTION_RECORD EXCEPTION_RECORD
#define GetProcAddress(x, y)
#define INVALID_HANDLE_VALUE
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
#define GetCurrentProcess()
enum _EXCEPTION_DISPOSITION EXCEPTION_DISPOSITION
#define WOW64_CONTEXT_ALL
#define ERROR_NOT_SUPPORTED
#define ERROR_INVALID_HANDLE
static const WCHAR version[]
BOOL WINAPI ContinueDebugEvent(IN DWORD dwProcessId, IN DWORD dwThreadId, IN DWORD dwContinueStatus)
BOOL WINAPI WaitForDebugEvent(IN LPDEBUG_EVENT lpDebugEvent, IN DWORD dwMilliseconds)
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI DECLSPEC_HOTPATCH SetUnhandledExceptionFilter(IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
BOOL WINAPI FlushInstructionCache(IN HANDLE hProcess, IN LPCVOID lpBaseAddress, IN SIZE_T nSize)
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
DWORD WINAPI ResumeThread(IN HANDLE hThread)
BOOL WINAPI SetThreadContext(IN HANDLE hThread, IN CONST CONTEXT *lpContext)
DWORD WINAPI SuspendThread(IN HANDLE hThread)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
BOOL WINAPI TlsFree(IN DWORD Index)
BOOL WINAPI GetThreadContext(IN HANDLE hThread, OUT LPCONTEXT lpContext)
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
DWORD WINAPI DECLSPEC_HOTPATCH TlsAlloc(void)
UINT(* handler)(MSIPACKAGE *)
void CDECL unexpected(void)
int CDECL fflush(FILE *file)
#define DECLSPEC_ALIGN(x)
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
_ACRTIMP char *__cdecl strstr(const char *, const char *)
_ACRTIMP int __cdecl strcmp(const char *, const char *)
_ACRTIMP int __cdecl strncmp(const char *, const char *, size_t)
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
int align(int length, int align)
enum _SYSTEM_INFORMATION_CLASS SYSTEM_INFORMATION_CLASS
#define STATUS_ACCESS_VIOLATION
static char * path_name(DOS_FILE *file)
for(i=0;i< ARRAY_SIZE(offsets);i++)
GLint GLint GLint GLint GLint x
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble r
GLuint GLuint GLuint GLuint arg1
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
GLenum const GLfloat * params
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLuint GLsizei GLsizei * length
GLenum const GLvoid * addr
GLuint GLint GLboolean GLint GLenum access
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
void WINAPI SHIM_OBJ_NAME() OutputDebugStringW(LPCWSTR lpOutputString)
#define EXCEPTION_EXECUTE_HANDLER
#define EXCEPTION_CONTINUE_SEARCH
#define EXCEPTION_CONTINUE_EXECUTION
__INTRIN_INLINE void __cpuidex(int CPUInfo[4], int InfoType, int ECXValue)
const char * winetest_platform
#define todo_wine_if(is_todo)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
#define EXCEPTION_SINGLE_STEP
#define EXCEPTION_FLT_STACK_CHECK
#define CREATE_PROCESS_DEBUG_EVENT
#define EXCEPTION_INT_DIVIDE_BY_ZERO
#define EXIT_PROCESS_DEBUG_EVENT
#define EXCEPTION_INVALID_HANDLE
#define OUTPUT_DEBUG_STRING_EVENT
#define EXCEPTION_DEBUG_EVENT
#define EXCEPTION_ILLEGAL_INSTRUCTION
#define EXCEPTION_ACCESS_VIOLATION
#define EXCEPTION_BREAKPOINT
#define EXCEPTION_FLT_INVALID_OPERATION
#define EXCEPTION_FLT_DIVIDE_BY_ZERO
#define memcpy(s1, s2, n)
static struct test_info tests[]
static NTSTATUS *static PWSTR CURDIR *static HMODULE hmod
static const BYTE call_debug_service_code[]
static void test_debugger(const char *argv0)
static PROCESS_INFORMATION pi
static const DWORD padding[]
static DWORD outputdebugstring_exceptions_unicode
static ULONG context_flags
static const char * suspend_process_event2_name
static void CALLBACK apc_func(ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3)
static DWORD outputdebugstring_exceptions_ansi
static void * pKiUserCallbackDispatcher
static void test_suspend_process(void)
static void test_unload_trace(void)
static BOOL have_vectored_api
static void suspend_process_proc(void)
struct _RTL_UNLOAD_EVENT_TRACE * PRTL_UNLOAD_EVENT_TRACE
static void test_outputdebugstring(BOOL unicode, DWORD numexc_ansi, BOOL todo_ansi, DWORD numexc_unicode_low, DWORD numexc_unicode_high)
static ULONG CONTEXT_EX ** context_ex
static void *WINAPI * pRtlLocateLegacyContext(CONTEXT_EX *context_ex, ULONG *length)
static void **static CONTEXT * context
static void test_closehandle(DWORD numexc, HANDLE handle)
static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
static RTL_UNLOAD_EVENT_TRACE *WINAPI * pRtlGetUnloadEventTrace(void)
static const void void SIZE_T *static LONG exit_code
static DWORD CONTEXT * src
static const char * suspend_process_event_name
static void *WINAPI * pRtlLocateExtendedFeature(CONTEXT_EX *context_ex, ULONG feature_id, ULONG *length)
static DWORD outputdebugstring_newmodel_return
static ULONG64 feature_mask
static LONG CALLBACK ripevent_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
static ULONG ** element_count
static void *WINAPI * pLocateXStateFeature(CONTEXT *context, DWORD feature_id, DWORD *length)
static EXCEPTION_RECORD *static void ULONG *static void * pKiUserApcDispatcher
static DWORD WINAPI suspend_thread_test(void *arg)
static void test_ripevent(DWORD numexc)
static CONTEXT *static CONTEXT *static PNTAPCFUNC func
static void *WINAPI * pRtlPcToFileHeader(PVOID pc, PVOID *address)
static ULONG ULONG64 compaction_mask
static BOOL is_magic_handle(HANDLE handle)
static DWORD outputdebugstring_exceptions_newmodel_order
static void test_fastfail(void)
static DWORD ripevent_exceptions
static ULONG void ** event_trace
static const void void SIZE_T
static void test_vectored_continue_handler(void)
static VOID EXCEPTION_RECORD VOID CONTEXT UNWIND_HISTORY_TABLE *static DWORD64
static LONG CALLBACK invalid_handle_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
static void test_suspend_count(HANDLE hthread, ULONG expected_count, int line)
static DWORD breakpoint_exceptions
static void subtest_fastfail(unsigned int code)
static void test_suspend_thread(void)
static CONTEXT *static CONTEXT *static PNTAPCFUNC ULONG_PTR ULONG_PTR ULONG_PTR arg3
static void test_user_callback(void)
static DWORD WINAPI dummy_thread_proc(void *arg)
static DWORD invalid_handle_exceptions
static void **static CONTEXT BOOL first_chance
static void test_outputdebugstring_newmodel(void)
static enum debugger_stages test_stage
@ STAGE_SERVICE_NOT_HANDLED
@ STAGE_OUTPUTDEBUGSTRINGA_CONTINUE
@ STAGE_OUTPUTDEBUGSTRINGW_CONTINUE
@ STAGE_EXCEPTION_INVHANDLE_NOT_HANDLED
@ STAGE_RTLRAISE_NOT_HANDLED
@ STAGE_NO_EXCEPTION_INVHANDLE_NOT_HANDLED
@ STAGE_BREAKPOINT_CONTINUE
@ STAGE_RTLRAISE_HANDLE_LAST_CHANCE
@ STAGE_EXCEPTION_INVHANDLE_CONTINUE
@ STAGE_BREAKPOINT_NOT_HANDLED
@ STAGE_XSTATE_LEGACY_SSE
@ STAGE_RIPEVENT_CONTINUE
@ STAGE_RIPEVENT_NOT_HANDLED
@ STAGE_OUTPUTDEBUGSTRINGA_NOT_HANDLED
@ STAGE_OUTPUTDEBUGSTRINGW_NOT_HANDLED
static CONTEXT *static CONTEXT *static PNTAPCFUNC ULONG_PTR ULONG_PTR arg2
struct _RTL_UNLOAD_EVENT_TRACE RTL_UNLOAD_EVENT_TRACE
static LONG CALLBACK outputdebugstring_new_model_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
#define TEST_SUSPEND_COUNT(thread, count)
static CONTEXT *static CONTEXT *static PNTAPCFUNC ULONG_PTR arg1
static void test_user_apc(void)
static void * pKiUserExceptionDispatcher
static LONG CALLBACK breakpoint_handler(EXCEPTION_POINTERS *ExceptionInfo)
static void test_breakpoint(DWORD numexc)
#define RTL_UNLOAD_EVENT_TRACE_NUMBER
unsigned __int3264 UINT_PTR
#define MEM_EXECUTE_OPTION_DISABLE
#define MEM_EXECUTE_OPTION_PERMANENT
#define MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION
#define MEM_EXECUTE_OPTION_ENABLE
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
LONG(NTAPI * PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionPointers)
#define CONTEXT_DEBUG_REGISTERS
#define PAGE_EXECUTE_READ
#define CONTEXT_FLOATING_POINT
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)
#define PAGE_EXECUTE_READWRITE
NTSTATUS NTAPI NtContinue(_In_ PCONTEXT Context, _In_ BOOLEAN TestAlert)
NTSTATUS NTAPI NtSetContextThread(IN HANDLE ThreadHandle, IN PCONTEXT ThreadContext)
NTSTATUS NTAPI NtSetInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _In_reads_bytes_(ProcessInformationLength) PVOID ProcessInformation, _In_ ULONG ProcessInformationLength)
NTSTATUS NTAPI NtSetInformationThread(_In_ HANDLE ThreadHandle, _In_ THREADINFOCLASS ThreadInformationClass, _In_reads_bytes_(ThreadInformationLength) PVOID ThreadInformation, _In_ ULONG ThreadInformationLength)
NTSTATUS NTAPI NtQueryInformationProcess(_In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_writes_bytes_to_opt_(ProcessInformationLength, *ReturnLength) PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength)
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
NTSTATUS NTAPI NtSuspendThread(IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL)
#define DBG_PRINTEXCEPTION_WIDE_C
#define STATUS_ASSERTION_FAILURE
#define STATUS_NO_CALLBACK_ACTIVE
#define STATUS_SINGLE_STEP
#define STATUS_UNWIND_CONSOLIDATE
#define STATUS_PRIVILEGED_INSTRUCTION
#define STATUS_BREAKPOINT
#define STATUS_FLOAT_MULTIPLE_TRAPS
#define DBG_PRINTEXCEPTION_C
#define DBG_EXCEPTION_NOT_HANDLED
#define STATUS_STACK_BUFFER_OVERRUN
#define STATUS_INVALID_INFO_CLASS
#define STATUS_PARTIAL_COPY
#define STATUS_SUSPEND_COUNT_EXCEEDED
#define IMAGE_FILE_MACHINE_I386
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tpush %rbx\n" "\t.seh_pushreg %rbx\n" "\tpush %rdi\n" "\t.seh_pushreg %rdi\n" "\tpush %rsi\n" "\t.seh_pushreg %rsi\n" "\tpush %r12\n" "\t.seh_pushreg %r12\n" "\tpush %r13\n" "\t.seh_pushreg %r13\n" "\tpush %r14\n" "\t.seh_pushreg %r14\n" "\tpush %r15\n" "\t.seh_pushreg %r15\n" "\tsub $40, %rsp\n" "\t.seh_stackalloc 40\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $40, %rsp\n" "\tpop %r15\n" "\tpop %r14\n" "\tpop %r13\n" "\tpop %r12\n" "\tpop %rsi\n" "\tpop %rdi\n" "\tpop %rbx\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
#define offsetof(TYPE, MEMBER)
int winetest_get_mainargs(char ***pargv)
#define wait_child_process
XSAVE_FORMAT XMM_SAVE_AREA32
#define EXCEPTION_EXECUTE_FAULT
#define EXCEPTION_READ_FAULT
#define CONTEXT_EXTENDED_REGISTERS
#define R1(v, w, x, y, z, i)
#define R2(v, w, x, y, z, i)
#define R0(v, w, x, y, z, i)
#define R3(v, w, x, y, z, i)
#define R4(v, w, x, y, z, i)
#define _WIN32_WINNT_WIN8
#define _WIN32_WINNT_WIN7
union _DEBUG_EVENT::@3289 u
OUTPUT_DEBUG_STRING_INFO DebugString
EXCEPTION_DEBUG_INFO Exception
CREATE_PROCESS_DEBUG_INFO CreateProcessInfo
PVOID NonVolatileRegisters
EXCEPTION_RECORD ExceptionRecord
PEXCEPTION_RECORD ExceptionRecord
struct _EXCEPTION_RECORD * ExceptionRecord
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]
PEXCEPTION_ROUTINE Handler
struct _EXCEPTION_REGISTRATION_RECORD * Prev
UNWIND_CODE UnwindCode[1]
WOW64_FLOATING_SAVE_AREA FloatSave
BYTE ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION]
DWORD WINAPI SleepEx(IN DWORD dwMilliseconds, IN BOOL bAlertable)
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
HANDLE WINAPI DECLSPEC_HOTPATCH OpenEventA(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN LPCSTR lpName)
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
__inline int before(__u32 seq1, __u32 seq2)
__inline int after(__u32 seq1, __u32 seq2)
#define STATUS_ACCESS_DENIED
#define STATUS_INVALID_PARAMETER
#define STATUS_INFO_LENGTH_MISMATCH
double FpNvRegs[NONVOL_FP_NUMREG_ARM64]
DWORD64 GpNvRegs[NONVOL_INT_NUMREG_ARM64]
BOOL NTAPI VirtualProtect(IN LPVOID lpAddress, IN SIZE_T dwSize, IN DWORD flNewProtect, OUT PDWORD lpflOldProtect)
DWORD WINAPI GetLastError(void)
HANDLE WINAPI GetCurrentThread(void)
#define EVENT_MODIFY_STATE
DWORD WINAPI GetCurrentProcessId(void)
#define WOW64_TLS_CPURESERVED
NTSTATUS(WINAPI * KERNEL_CALLBACK_PROC)(void *, ULONG)
NTSYSAPI void WINAPI DbgBreakPoint(void)
@ ProcessInstrumentationCallback
void(CALLBACK * PNTAPCFUNC)(ULONG_PTR, ULONG_PTR, ULONG_PTR)
#define KCONTINUE_FLAG_TEST_ALERT
LONG(CALLBACK * PRTL_EXCEPTION_FILTER)(PEXCEPTION_POINTERS)
#define CONTEXT_EXCEPTION_ACTIVE
#define CONTEXT_SERVICE_ACTIVE
#define CONTEXT_EXCEPTION_REQUEST
#define CONTEXT_EXCEPTION_REPORTING
#define CONTEXT_UNWOUND_TO_CALL
#define NONVOL_INT_NUMREG_ARM64
#define NONVOL_FP_NUMREG_ARM64
#define EXCEPTION_SOFTWARE_ORIGINATE
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
BOOL WINAPI DestroyWindow(_In_ HWND)
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define XSTATE_AVX512_KMASK
#define XSTATE_LEGACY_SSE
#define FAST_FAIL_GS_COOKIE_INIT
#define FAST_FAIL_INVALID_FAST_FAIL_CODE
#define FAST_FAIL_INCORRECT_STACK
#define FAST_FAIL_LEGACY_GS_VIOLATION
#define FAST_FAIL_VTGUARD_CHECK_FAILURE
#define FAST_FAIL_STACK_COOKIE_CHECK_FAILURE
#define FAST_FAIL_FATAL_APP_EXIT
#define FAST_FAIL_INVALID_ARG
#define FAST_FAIL_CORRUPT_LIST_ENTRY
#define EXCEPTION_NESTED_CALL
#define EXCEPTION_UNWINDING
#define EXCEPTION_TARGET_UNWIND
#define EXCEPTION_COLLIDED_UNWIND