-- v3: ntdll: Store exception reporting flags for debug events. ntdll: Store exception reporting flags on suspend. ntdll: Store exception reporting flags in server context. ntdll: Set exception reporting flags in NtGetContextThread(). ntdll/tests: Add tests for CONTEXT_EXCEPTION_REQUEST.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/exception.c | 321 ++++++++++++++++++++++++++++++++-- dlls/ntdll/tests/ntdll_test.h | 2 + dlls/ntdll/tests/wow64.c | 14 +- include/winnt.h | 5 + 4 files changed, 322 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 771f32bb514..0087628034b 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -18,22 +18,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include <stdarg.h> +#include "ntdll_test.h" + #include <stdio.h> #include <setjmp.h>
-#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "winnt.h" -#include "winreg.h" #include "winuser.h" -#include "winternl.h" #include "rtlsupportapi.h" #include "ddk/wdm.h" #include "excpt.h" -#include "wine/test.h" #include "intrin.h"
static void *code_mem; @@ -236,6 +229,19 @@ static void test_debugger_xstate(HANDLE thread, CONTEXT *ctx, enum debugger_stag status = pNtSetContextThread(thread, xctx); ok(!status, "NtSetContextThread failed with 0x%lx\n", status); } + +#define check_context_exception_request( a, b ) check_context_exception_request_( a, b, __LINE__ ) +static void check_context_exception_request_( DWORD flags, BOOL hardware_exception, unsigned int line ) +{ + static const DWORD exception_reporting_flags = CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING + | CONTEXT_EXCEPTION_ACTIVE | CONTEXT_SERVICE_ACTIVE; + DWORD expected_flags = CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING; + + if (!(flags & CONTEXT_EXCEPTION_REPORTING)) return; + expected_flags |= hardware_exception ? CONTEXT_EXCEPTION_ACTIVE : CONTEXT_SERVICE_ACTIVE; + ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n", + flags, expected_flags ); +} #endif
#ifdef __i386__ @@ -1103,13 +1109,16 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) sizeof(stage), &size_read); ok(!status,"NtReadVirtualMemory failed with 0x%lx\n", status);
- ctx.ContextFlags = CONTEXT_FULL | CONTEXT_EXTENDED_REGISTERS; + ctx.ContextFlags = CONTEXT_FULL | CONTEXT_EXTENDED_REGISTERS | CONTEXT_EXCEPTION_REQUEST; status = pNtGetContextThread(pi.hThread, &ctx); ok(!status, "NtGetContextThread failed with 0x%lx\n", status); + todo_wine ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING + || broken( !(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) ) /* Win7 WoW64 */, + "got %#lx.\n", ctx.ContextFlags);
- trace("exception 0x%lx at %p firstchance=%ld Eip=0x%lx, Eax=0x%lx\n", + trace("exception 0x%lx at %p firstchance=%ld Eip=0x%lx, Eax=0x%lx ctx.ContextFlags %#lx\n", de.u.Exception.ExceptionRecord.ExceptionCode, - de.u.Exception.ExceptionRecord.ExceptionAddress, de.u.Exception.dwFirstChance, ctx.Eip, ctx.Eax); + de.u.Exception.ExceptionRecord.ExceptionAddress, de.u.Exception.dwFirstChance, ctx.Eip, ctx.Eax, ctx.ContextFlags);
if (counter > 100) { @@ -1126,6 +1135,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) (char *)ctx.Eip < (char *)ntdll + nt->OptionalHeader.SizeOfImage, "wrong eip %p ntdll %p-%p\n", (void *)ctx.Eip, ntdll, (char *)ntdll + nt->OptionalHeader.SizeOfImage ); + check_context_exception_request( ctx.ContextFlags, TRUE ); } else { @@ -1139,6 +1149,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ctx.Eax = 0xf00f00f1; /* let the debuggee handle the exception */ continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, !is_wow64 ); } else if (stage == STAGE_RTLRAISE_HANDLE_LAST_CHANCE) { @@ -1175,6 +1186,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ctx.Eip, (char *)code_mem_address + 0xb); /* here we handle exception */ } + check_context_exception_request( ctx.ContextFlags, !is_wow64 ); } else if (stage == STAGE_SERVICE_CONTINUE || stage == STAGE_SERVICE_NOT_HANDLED) { @@ -1184,6 +1196,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) "expected Eip = %p, got 0x%lx\n", (char *)code_mem_address + 0x1d, ctx.Eip);
if (stage == STAGE_SERVICE_NOT_HANDLED) continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, TRUE ); } else if (stage == STAGE_BREAKPOINT_CONTINUE || stage == STAGE_BREAKPOINT_NOT_HANDLED) { @@ -1193,6 +1206,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) "expected Eip = %p, got 0x%lx\n", (char *)code_mem_address + 2, ctx.Eip);
if (stage == STAGE_BREAKPOINT_NOT_HANDLED) continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, TRUE ); } else if (stage == STAGE_EXCEPTION_INVHANDLE_CONTINUE || stage == STAGE_EXCEPTION_INVHANDLE_NOT_HANDLED) { @@ -1203,14 +1217,17 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) "unexpected number of parameters %ld, expected 0\n", de.u.Exception.ExceptionRecord.NumberParameters);
if (stage == STAGE_EXCEPTION_INVHANDLE_NOT_HANDLED) continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, !is_wow64 ); } else if (stage == STAGE_NO_EXCEPTION_INVHANDLE_NOT_HANDLED) { ok(FALSE || broken(TRUE) /* < Win10 */, "should not throw exception\n"); continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, !is_wow64 ); } else if (stage == STAGE_XSTATE || stage == STAGE_XSTATE_LEGACY_SSE) { + check_context_exception_request( ctx.ContextFlags, TRUE ); test_debugger_xstate(pi.hThread, &ctx, stage); } else if (stage == STAGE_SEGMENTS) @@ -1231,6 +1248,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ok( !ctx.SegEs, "wrong es %04lx / %04lx\n", ctx.SegEs, ctx.SegSs ); ok( !ctx.SegGs, "wrong gs %04lx / %04lx\n", ctx.SegGs, ctx.SegSs ); } + check_context_exception_request( ctx.ContextFlags, TRUE ); } else ok(FALSE, "unexpected stage %u\n", stage); @@ -3564,9 +3582,10 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) sizeof(stage), &size_read); ok(!status,"NtReadVirtualMemory failed with 0x%lx\n", status);
- ctx.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS; + ctx.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS | CONTEXT_EXCEPTION_REQUEST; status = pNtGetContextThread(pi.hThread, &ctx); ok(!status, "NtGetContextThread failed with 0x%lx\n", status); + todo_wine ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING, "got %#lx.\n", ctx.ContextFlags);
trace("exception 0x%lx at %p firstchance=%ld Rip=%p, Rax=%p\n", de.u.Exception.ExceptionRecord.ExceptionCode, @@ -3587,6 +3606,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) (char *)ctx.Rip < (char *)hntdll + nt->OptionalHeader.SizeOfImage, "wrong rip %p ntdll %p-%p\n", (void *)ctx.Rip, hntdll, (char *)hntdll + nt->OptionalHeader.SizeOfImage ); + check_context_exception_request( ctx.ContextFlags, TRUE ); } else { @@ -3605,6 +3625,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ctx.Rax = 0xf00f00f1; /* let the debuggee handle the exception */ continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, FALSE ); } else if (stage == STAGE_RTLRAISE_HANDLE_LAST_CHANCE) { @@ -3643,6 +3664,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ctx.Rip, (char *)code_mem_address + 0x0c); /* here we handle exception */ } + check_context_exception_request( ctx.ContextFlags, FALSE ); } else if (stage == STAGE_SERVICE_CONTINUE || stage == STAGE_SERVICE_NOT_HANDLED) { @@ -3651,6 +3673,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ok((char *)ctx.Rip == (char *)code_mem_address + 0x30, "expected Rip = %p, got %p\n", (char *)code_mem_address + 0x30, (char *)ctx.Rip); if (stage == STAGE_SERVICE_NOT_HANDLED) continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, TRUE ); } else if (stage == STAGE_BREAKPOINT_CONTINUE || stage == STAGE_BREAKPOINT_NOT_HANDLED) { @@ -3659,6 +3682,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ok((char *)ctx.Rip == (char *)code_mem_address + 2, "expected Rip = %p, got %p\n", (char *)code_mem_address + 2, (char *)ctx.Rip); if (stage == STAGE_BREAKPOINT_NOT_HANDLED) continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, TRUE ); } else if (stage == STAGE_EXCEPTION_INVHANDLE_CONTINUE || stage == STAGE_EXCEPTION_INVHANDLE_NOT_HANDLED) { @@ -3669,14 +3693,17 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) "unexpected number of parameters %ld, expected 0\n", de.u.Exception.ExceptionRecord.NumberParameters);
if (stage == STAGE_EXCEPTION_INVHANDLE_NOT_HANDLED) continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, FALSE ); } else if (stage == STAGE_NO_EXCEPTION_INVHANDLE_NOT_HANDLED) { ok(FALSE || broken(TRUE) /* < Win10 */, "should not throw exception\n"); continuestatus = DBG_EXCEPTION_NOT_HANDLED; + check_context_exception_request( ctx.ContextFlags, FALSE ); } else if (stage == STAGE_XSTATE || stage == STAGE_XSTATE_LEGACY_SSE) { + check_context_exception_request( ctx.ContextFlags, TRUE ); test_debugger_xstate(pi.hThread, &ctx, stage); } else if (stage == STAGE_SEGMENTS) @@ -3705,6 +3732,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ok( ctx.SegEs == ctx.SegSs, "wrong es %04x / %04x\n", ctx.SegEs, ctx.SegSs ); todo_wine ok( ctx.SegFs != ctx.SegSs, "wrong fs %04x / %04x\n", ctx.SegFs, ctx.SegSs ); ok( ctx.SegGs == ctx.SegSs, "wrong gs %04x / %04x\n", ctx.SegGs, ctx.SegSs ); + check_context_exception_request( ctx.ContextFlags, TRUE ); } else ok(FALSE, "unexpected stage %u\n", stage); @@ -4316,9 +4344,21 @@ static void test_wow64_context(void) ret = pRtlWow64GetThreadContext( pi.hThread, &ctx ); ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); ok( ctx.ContextFlags == WOW64_CONTEXT_ALL, "got context flags %#lx\n", ctx.ContextFlags ); + + ctx.ContextFlags = WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST; + ret = pRtlWow64GetThreadContext( pi.hThread, &ctx ); + ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); + todo_wine ok( (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) || broken( ctx.ContextFlags == WOW64_CONTEXT_ALL ) /*Win 7*/, + "got context flags %#lx\n", ctx.ContextFlags ); + if (context.SegCs == cs32) { trace( "in 32-bit mode %04x\n", context.SegCs ); + if (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) + ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING) + || ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING + | CONTEXT_EXCEPTION_ACTIVE), + "got %#lx.\n", ctx.ContextFlags ); ok( ctx.Eip == context.Rip, "cs32: eip %08lx / %p\n", ctx.Eip, (void *)context.Rip ); ok( ctx.Ebp == context.Rbp, "cs32: ebp %08lx / %p\n", ctx.Ebp, (void *)context.Rbp ); ok( ctx.Esp == context.Rsp, "cs32: esp %08lx / %p\n", ctx.Esp, (void *)context.Rsp ); @@ -4395,6 +4435,12 @@ static void test_wow64_context(void) else { trace( "in 64-bit mode %04x\n", context.SegCs ); + if (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) + ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST + | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE) + || ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST + | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE), + "got %#lx.\n", ctx.ContextFlags ); ok( ctx.Eip != context.Rip, "cs64: eip %08lx / %p\n", ctx.Eip, (void *)context.Rip); ok( ctx.SegCs == cs32, "cs64: wrong cs %04lx / %04x\n", ctx.SegCs, cs32 ); if (!is_arm64ec) @@ -10941,6 +10987,254 @@ static void test_backtrace(void) module, debugstr_w(name), count - 1, buffer[count - 1] ); }
+struct context_exception_request_thread_param +{ + LONG volatile sync; + HANDLE event; +}; +static volatile int *p_context_exception_request_value; +struct context_exception_request_thread_param *context_exception_request_param; + +static LONG CALLBACK test_context_exception_request_handler( EXCEPTION_POINTERS *info ) +{ + PEXCEPTION_RECORD rec = info->ExceptionRecord; + CONTEXT *c = info->ContextRecord; + DWORD old_prot; + + ok( !(c->ContextFlags & (CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE + | CONTEXT_EXCEPTION_ACTIVE)), "got %#lx.\n", c->ContextFlags ); + + ok( rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION, "got %#lx.\n", rec->ExceptionCode ); + VirtualProtect( (void *)p_context_exception_request_value, sizeof(*p_context_exception_request_value), + PAGE_READWRITE, &old_prot ); + + WriteRelease( &context_exception_request_param->sync, 5 ); + while (ReadAcquire( &context_exception_request_param->sync ) != 6) + ; + + return EXCEPTION_CONTINUE_EXECUTION; +} + +static DWORD WINAPI test_context_exception_request_thread( void *arg ) +{ +#ifndef _WIN64 + static BYTE wait_sync_x64_code[] = + { + 0x89, 0x11, /* mov %edx,(%rcx) */ + 0x83, 0xc2, 0x01, /* add $0x1,%edx */ + 0x0f, 0x1f, 0x00, /* 1: nopl (%rax) */ + 0x8b, 0x01, /* mov (%rcx),%eax */ + 0x39, 0xd0, /* cmp %edx,%eax */ + 0x75, 0xfa, /* jne 1b */ + 0xc3, /* ret */ + }; + ULONG64 args[2]; +#endif + struct context_exception_request_thread_param *p = arg; + void *vectored_handler; + + context_exception_request_param = p; + vectored_handler = pRtlAddVectoredExceptionHandler( TRUE, test_context_exception_request_handler ); + ok( !!vectored_handler, "failed.\n" ); + + WriteRelease( &p->sync, 1 ); + while (ReadAcquire( &p->sync ) != 2) + ; + + WaitForSingleObject( p->event, INFINITE ); + +#ifndef _WIN64 + memcpy( (char *)code_mem + 1024, wait_sync_x64_code, sizeof(wait_sync_x64_code) ); + args[0] = (ULONG_PTR)&p->sync; + args[1] = 3; + if (is_wow64 && !old_wow64) call_func64( (ULONG64)(ULONG_PTR)code_mem + 1024, ARRAY_SIZE(args), args, code_mem ); +#endif + + p_context_exception_request_value = VirtualAlloc( NULL, sizeof(*p_context_exception_request_value), + MEM_RESERVE | MEM_COMMIT, PAGE_READONLY ); + ok( !!p_context_exception_request_value, "got NULL.\n" ); + *p_context_exception_request_value = 1; + ok( *p_context_exception_request_value == 1, "got %d.\n", *p_context_exception_request_value ); + VirtualFree( (void *)p_context_exception_request_value, 0, MEM_RELEASE ); + pRtlRemoveVectoredExceptionHandler( vectored_handler ); + +#ifndef _WIN64 + args[1] = 7; + if (is_wow64 && !old_wow64) call_func64( (ULONG64)(ULONG_PTR)code_mem + 1024, ARRAY_SIZE(args), args, code_mem ); +#endif + + return 0; +} + +static void test_context_exception_request(void) +{ + struct context_exception_request_thread_param p; + DWORD expected_flags; + HANDLE thread; + CONTEXT c; + BOOL ret; + + if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler) + { + skip( "RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found.\n" ); + return; + } + + c.ContextFlags = CONTEXT_CONTROL; + ret = GetThreadContext( GetCurrentThread(), &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + ok( c.ContextFlags == CONTEXT_CONTROL, "got %#lx.\n", c.ContextFlags ); + + expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( GetCurrentThread(), &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == 0x10001 ) /* Win7 WoW64 */, + "got %#lx.\n", c.ContextFlags ); + if (c.ContextFlags == 0x10001) + { + win_skip( "Old WoW64 behaviour, skipping tests.\n" ); + return; + } + + ret = DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &thread, 0, TRUE, DUPLICATE_SAME_ACCESS ); + ok( ret, "got error %lu.\n", GetLastError() ); + c.ContextFlags = expected_flags | CONTEXT_EXCEPTION_REQUEST; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + CloseHandle( thread ); + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE + | CONTEXT_EXCEPTION_ACTIVE; + ret = GetThreadContext( GetCurrentThread(), &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + + p.event = CreateEventW( NULL, FALSE, FALSE, NULL ); + thread = CreateThread( NULL, 0, test_context_exception_request_thread, &p, CREATE_SUSPENDED, NULL ); + ok( !!thread, "got error %lu.\n", GetLastError() ); + + expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == (CONTEXT_CONTROL + | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING)) /* Win7 64 */, "got %#lx.\n", c.ContextFlags ); + + p.sync = 0; + ResumeThread(thread); + + while (ReadAcquire( &p.sync ) != 1) + SwitchToThread(); + /* thread is in user code. */ + SuspendThread( thread ); + + c.ContextFlags = CONTEXT_CONTROL; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + ok( c.ContextFlags == CONTEXT_CONTROL, "got %#lx.\n", c.ContextFlags ); + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE; + ret = SetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + + expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE + | CONTEXT_EXCEPTION_ACTIVE; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + + ResumeThread(thread); + WriteRelease( &p.sync, 2 ); + /* Try to make sure the thread entered WaitForSingleObject(). */ + Sleep(30); + + expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + + c.ContextFlags = CONTEXT_CONTROL; + ret = SetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE + | CONTEXT_EXCEPTION_ACTIVE; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + + SetEvent( p.event ); + + if (is_wow64 && !old_wow64) + { + while (ReadAcquire( &p.sync ) != 3) + SwitchToThread(); + /* thread is in x64 code. */ + + expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags ); + + WriteRelease( &p.sync, 4 ); + } + + while (ReadAcquire( &p.sync ) != 5) + SwitchToThread(); + + expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE + | CONTEXT_EXCEPTION_ACTIVE; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + + WriteRelease( &p.sync, 6 ); + + if (is_wow64 && !old_wow64) + { + while (ReadAcquire( &p.sync ) != 7) + SwitchToThread(); + /* thread is in x64 code. */ + + expected_flags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE; + + c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; + ret = GetThreadContext( thread, &c ); + ok( ret, "got error %lu.\n", GetLastError() ); + todo_wine ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags ); + + WriteRelease( &p.sync, 8 ); + } + + WaitForSingleObject( thread, INFINITE ); + CloseHandle( thread ); + CloseHandle( p.event ); +} + START_TEST(exception) { HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); @@ -11218,5 +11512,6 @@ START_TEST(exception) test_suspend_process(); test_unload_trace(); test_backtrace(); + test_context_exception_request(); VirtualFree(code_mem, 0, MEM_RELEASE); } diff --git a/dlls/ntdll/tests/ntdll_test.h b/dlls/ntdll/tests/ntdll_test.h index 67278358b29..ed824583870 100644 --- a/dlls/ntdll/tests/ntdll_test.h +++ b/dlls/ntdll/tests/ntdll_test.h @@ -30,3 +30,5 @@
#include "wine/test.h" #include "wine/heap.h" + +extern NTSTATUS call_func64( ULONG64 func64, int nb_args, ULONG64 *args, void *code_mem ); diff --git a/dlls/ntdll/tests/wow64.c b/dlls/ntdll/tests/wow64.c index e0dd7bab13b..28d7ec2406a 100644 --- a/dlls/ntdll/tests/wow64.c +++ b/dlls/ntdll/tests/wow64.c @@ -1569,7 +1569,7 @@ static const BYTE call_func64_code[] = 0xcb, /* lret */ };
-static NTSTATUS call_func64( ULONG64 func64, int nb_args, ULONG64 *args ) +NTSTATUS call_func64( ULONG64 func64, int nb_args, ULONG64 *args, void *code_mem ) { NTSTATUS (WINAPI *func)( ULONG64 func64, int nb_args, ULONG64 *args ) = code_mem;
@@ -2070,7 +2070,7 @@ static void test_iosb(void) iosb64.Information = 0xdeadbeef;
args[0] = (LONG_PTR)server; - status = call_func64( func, ARRAY_SIZE(args), args ); + status = call_func64( func, ARRAY_SIZE(args), args, code_mem ); ok( status == STATUS_PENDING, "NtFsControlFile returned %lx\n", status ); ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status ); ok( iosb64.Pointer == PtrToUlong(&iosb32), "status changed to %lx\n", iosb64.Status ); @@ -2095,7 +2095,7 @@ static void test_iosb(void) args[8] = (ULONG_PTR)&id; args[9] = sizeof(id);
- status = call_func64( func, ARRAY_SIZE(args), args ); + status = call_func64( func, ARRAY_SIZE(args), args, code_mem ); ok( status == STATUS_PENDING || status == STATUS_SUCCESS, "NtFsControlFile returned %lx\n", status ); todo_wine { @@ -2125,7 +2125,7 @@ static void test_iosb(void) id = 0xdeadbeef;
args[0] = (LONG_PTR)server; - status = call_func64( func, ARRAY_SIZE(args), args ); + status = call_func64( func, ARRAY_SIZE(args), args, code_mem ); ok( status == STATUS_SUCCESS, "NtFsControlFile returned %lx\n", status ); ok( iosb32.Status == 0x55555555, "status changed to %lx\n", iosb32.Status ); ok( iosb32.Information == 0x55555555, "info changed to %Ix\n", iosb32.Information ); @@ -2148,7 +2148,7 @@ static NTSTATUS invoke_syscall( const char *name, ULONG args32[] ) else win_skip( "syscall thunk %s not recognized\n", name );
- return call_func64( func, ARRAY_SIZE(args64), args64 ); + return call_func64( func, ARRAY_SIZE(args64), args64, code_mem ); }
static void test_syscalls(void) @@ -2254,14 +2254,14 @@ static void test_cpu_area(void) ULONG64 context, context_ex; ULONG64 args[] = { (ULONG_PTR)&machine, (ULONG_PTR)&context, (ULONG_PTR)&context_ex };
- status = call_func64( ptr, ARRAY_SIZE(args), args ); + status = call_func64( ptr, ARRAY_SIZE(args), args, code_mem ); ok( !status, "RtlWow64GetCpuAreaInfo failed %lx\n", status ); ok( machine == IMAGE_FILE_MACHINE_I386, "wrong machine %x\n", machine ); ok( context == teb64->TlsSlots[WOW64_TLS_CPURESERVED] + 4, "wrong context %s / %s\n", wine_dbgstr_longlong(context), wine_dbgstr_longlong(teb64->TlsSlots[WOW64_TLS_CPURESERVED]) ); ok( !context_ex, "got context_ex %s\n", wine_dbgstr_longlong(context_ex) ); args[0] = args[1] = args[2] = 0; - status = call_func64( ptr, ARRAY_SIZE(args), args ); + status = call_func64( ptr, ARRAY_SIZE(args), args, code_mem ); ok( !status, "RtlWow64GetCpuAreaInfo failed %lx\n", status ); } else win_skip( "RtlWow64GetCpuAreaInfo not supported\n" ); diff --git a/include/winnt.h b/include/winnt.h index e7c322fd127..1bf38616b87 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -1536,6 +1536,11 @@ typedef struct _CONTEXT_EX #endif } CONTEXT_EX, *PCONTEXT_EX;
+#define CONTEXT_EXCEPTION_ACTIVE 0x08000000 +#define CONTEXT_SERVICE_ACTIVE 0x10000000 +#define CONTEXT_EXCEPTION_REQUEST 0x40000000 +#define CONTEXT_EXCEPTION_REPORTING 0x80000000 + #define CONTEXT_ARM 0x0200000 #define CONTEXT_ARM_CONTROL (CONTEXT_ARM | 0x00000001) #define CONTEXT_ARM_INTEGER (CONTEXT_ARM | 0x00000002)
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/exception.c | 8 ++++---- dlls/ntdll/unix/signal_arm.c | 1 + dlls/ntdll/unix/signal_arm64.c | 3 +++ dlls/ntdll/unix/signal_i386.c | 1 + dlls/ntdll/unix/signal_x86_64.c | 2 ++ dlls/ntdll/unix/unix_private.h | 11 +++++++++++ 6 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 0087628034b..7ccc76263cd 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -11090,8 +11090,8 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( GetCurrentThread(), &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == 0x10001 ) /* Win7 WoW64 */, - "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == 0x10001 ) /* Win7 WoW64 */, + "got %#lx.\n", c.ContextFlags ); if (c.ContextFlags == 0x10001) { win_skip( "Old WoW64 behaviour, skipping tests.\n" ); @@ -11105,14 +11105,14 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); CloseHandle( thread );
c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE; ret = GetThreadContext( GetCurrentThread(), &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
p.event = CreateEventW( NULL, FALSE, FALSE, NULL ); thread = CreateThread( NULL, 0, test_context_exception_request_thread, &p, CREATE_SUSPENDED, NULL ); diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index d4711e27319..44e79d0abdf 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -513,6 +513,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) memcpy( context->D, frame->d, sizeof(frame->d) ); context->ContextFlags |= CONTEXT_FLOATING_POINT; } + set_context_exception_reporting_flags( &context->ContextFlags, CONTEXT_SERVICE_ACTIVE ); return STATUS_SUCCESS; }
diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index fcebbab76cf..11340d88672 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -433,6 +433,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) context->ContextFlags |= CONTEXT_FLOATING_POINT; } if (needed_flags & CONTEXT_DEBUG_REGISTERS) FIXME( "debug registers not supported\n" ); + set_context_exception_reporting_flags( &context->ContextFlags, CONTEXT_SERVICE_ACTIVE ); return STATUS_SUCCESS; }
@@ -640,6 +641,7 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size ) context->Dr7 = wow_frame->Dr7; } /* FIXME: CONTEXT_I386_XSTATE */ + set_context_exception_reporting_flags( &context->ContextFlags, CONTEXT_SERVICE_ACTIVE ); break; }
@@ -679,6 +681,7 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size ) memcpy( context->D, wow_frame->D, sizeof(wow_frame->D) ); context->ContextFlags |= CONTEXT_FLOATING_POINT; } + set_context_exception_reporting_flags( &context->ContextFlags, CONTEXT_SERVICE_ACTIVE ); break; }
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 61f42806f5d..6e2752745d3 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1153,6 +1153,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) x86_thread_data()->dr6 = context->Dr6; x86_thread_data()->dr7 = context->Dr7; } + set_context_exception_reporting_flags( &context->ContextFlags, CONTEXT_SERVICE_ACTIVE ); }
if (context->ContextFlags & (CONTEXT_INTEGER & ~CONTEXT_i386)) diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 4fc2727595d..41e5f9531d5 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1186,6 +1186,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context ) amd64_thread_data()->dr6 = context->Dr6; amd64_thread_data()->dr7 = context->Dr7; } + set_context_exception_reporting_flags( &context->ContextFlags, CONTEXT_SERVICE_ACTIVE ); return STATUS_SUCCESS; }
@@ -1390,6 +1391,7 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size ) frame->restore_flags |= CONTEXT_XSTATE; } } + set_context_exception_reporting_flags( &context->ContextFlags, CONTEXT_SERVICE_ACTIVE ); return STATUS_SUCCESS; }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index b249570d421..ec11f9d4795 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -215,6 +215,17 @@ extern int server_pipe( int fd[2] ); extern void fpux_to_fpu( I386_FLOATING_SAVE_AREA *fpu, const XSAVE_FORMAT *fpux ); extern void fpu_to_fpux( XSAVE_FORMAT *fpux, const I386_FLOATING_SAVE_AREA *fpu );
+static inline void set_context_exception_reporting_flags( DWORD *context_flags, DWORD reporting_flag ) +{ + if (!(*context_flags & CONTEXT_EXCEPTION_REQUEST)) + { + *context_flags &= ~(CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE); + return; + } + *context_flags = (*context_flags & ~(CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE)) + | CONTEXT_EXCEPTION_REPORTING | reporting_flag; +} + extern BOOL xstate_compaction_enabled; extern UINT64 xstate_supported_features_mask; extern UINT64 xstate_features_size;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/exception.c | 18 ++++++------- dlls/ntdll/unix/server.c | 4 +++ dlls/ntdll/unix/thread.c | 50 +++++++++++++++++++++++++++++++++--- server/protocol.def | 13 ++++++++++ server/thread.c | 5 ++-- server/trace.c | 13 ++++++++++ tools/make_requests | 2 +- 7 files changed, 89 insertions(+), 16 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 7ccc76263cd..fb0e324d879 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -239,7 +239,7 @@ static void check_context_exception_request_( DWORD flags, BOOL hardware_excepti
if (!(flags & CONTEXT_EXCEPTION_REPORTING)) return; expected_flags |= hardware_exception ? CONTEXT_EXCEPTION_ACTIVE : CONTEXT_SERVICE_ACTIVE; - ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n", + todo_wine ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n", flags, expected_flags ); } #endif @@ -1112,7 +1112,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ctx.ContextFlags = CONTEXT_FULL | CONTEXT_EXTENDED_REGISTERS | CONTEXT_EXCEPTION_REQUEST; status = pNtGetContextThread(pi.hThread, &ctx); ok(!status, "NtGetContextThread failed with 0x%lx\n", status); - todo_wine ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING + ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING || broken( !(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) ) /* Win7 WoW64 */, "got %#lx.\n", ctx.ContextFlags);
@@ -3585,7 +3585,7 @@ static void test_debugger(DWORD cont_status, BOOL with_WaitForDebugEventEx) ctx.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS | CONTEXT_EXCEPTION_REQUEST; status = pNtGetContextThread(pi.hThread, &ctx); ok(!status, "NtGetContextThread failed with 0x%lx\n", status); - todo_wine ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING, "got %#lx.\n", ctx.ContextFlags); + ok(ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING, "got %#lx.\n", ctx.ContextFlags);
trace("exception 0x%lx at %p firstchance=%ld Rip=%p, Rax=%p\n", de.u.Exception.ExceptionRecord.ExceptionCode, @@ -4348,7 +4348,7 @@ static void test_wow64_context(void) ctx.ContextFlags = WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST; ret = pRtlWow64GetThreadContext( pi.hThread, &ctx ); ok(ret == STATUS_SUCCESS, "got %#lx\n", ret); - todo_wine ok( (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) || broken( ctx.ContextFlags == WOW64_CONTEXT_ALL ) /*Win 7*/, + ok( (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) || broken( ctx.ContextFlags == WOW64_CONTEXT_ALL ) /*Win 7*/, "got context flags %#lx\n", ctx.ContextFlags );
if (context.SegCs == cs32) @@ -4436,7 +4436,7 @@ static void test_wow64_context(void) { trace( "in 64-bit mode %04x\n", context.SegCs ); if (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) - ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST + todo_wine ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE) || ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE), @@ -11148,13 +11148,13 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
ResumeThread(thread); WriteRelease( &p.sync, 2 ); @@ -11204,13 +11204,13 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
WriteRelease( &p.sync, 6 );
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 438c16518bd..f3ffd99c3fc 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -751,7 +751,11 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT
if (ret == STATUS_USER_APC) *user_apc = reply_data.call.user; if (reply_size > sizeof(reply_data.call)) + { memcpy( context, reply_data.context, reply_size - sizeof(reply_data.call) ); + context[0].flags &= ~SERVER_CTX_EXEC_SPACE; + context[1].flags &= ~SERVER_CTX_EXEC_SPACE; + } return ret; }
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 7ae5c022fb2..21b581ddc7c 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -166,7 +166,7 @@ void fpu_to_fpux( XMM_SAVE_AREA32 *fpux, const I386_FLOATING_SAVE_AREA *fpu ) */ static unsigned int get_server_context_flags( const void *context, USHORT machine ) { - unsigned int flags, ret = 0; + unsigned int flags = 0, ret = 0;
switch (machine) { @@ -204,6 +204,7 @@ static unsigned int get_server_context_flags( const void *context, USHORT machin if (flags & CONTEXT_ARM64_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; break; } + if (flags & CONTEXT_EXCEPTION_REQUEST) ret |= SERVER_CTX_EXEC_SPACE; return ret; }
@@ -218,11 +219,11 @@ static unsigned int get_native_context_flags( USHORT native_machine, USHORT wow_ switch (MAKELONG( native_machine, wow_machine )) { case MAKELONG( IMAGE_FILE_MACHINE_AMD64, IMAGE_FILE_MACHINE_I386 ): - return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT | SERVER_CTX_YMM_REGISTERS; + return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT | SERVER_CTX_YMM_REGISTERS | SERVER_CTX_EXEC_SPACE; case MAKELONG( IMAGE_FILE_MACHINE_ARM64, IMAGE_FILE_MACHINE_ARMNT ): - return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT; + return SERVER_CTX_DEBUG_REGISTERS | SERVER_CTX_FLOATING_POINT | SERVER_CTX_EXEC_SPACE; default: - return 0; + return SERVER_CTX_EXEC_SPACE; } }
@@ -242,6 +243,21 @@ static void xstate_to_server( context_t *to, const CONTEXT_EX *xctx ) }
+/*********************************************************************** + * exception_request_flags_to_server + * + * Copy exception reporting flags to the server format. + */ +static void exception_request_flags_to_server( context_t *to, DWORD context_flags ) +{ + if (!(context_flags & CONTEXT_EXCEPTION_REPORTING)) return; + to->flags |= SERVER_CTX_EXEC_SPACE; + if (context_flags & CONTEXT_SERVICE_ACTIVE) to->exec_space.space.space = EXEC_SPACE_SYSCALL; + else if (context_flags & CONTEXT_EXCEPTION_ACTIVE) to->exec_space.space.space = EXEC_SPACE_EXCEPTION; + else to->exec_space.space.space = EXEC_SPACE_USERMODE; +} + + /*********************************************************************** * context_to_server * @@ -319,6 +335,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void } if (flags & CONTEXT_I386_XSTATE) xstate_to_server( to, (const CONTEXT_EX *)(from + 1) ); + exception_request_flags_to_server( to, flags ); return STATUS_SUCCESS; }
@@ -377,6 +394,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void } if (flags & CONTEXT_I386_XSTATE) xstate_to_server( to, (const CONTEXT_EX *)(from + 1) ); + exception_request_flags_to_server( to, flags ); return STATUS_SUCCESS; }
@@ -438,6 +456,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void } if (flags & CONTEXT_AMD64_XSTATE) xstate_to_server( to, (const CONTEXT_EX *)(from + 1) ); + exception_request_flags_to_server( to, flags ); return STATUS_SUCCESS; }
@@ -503,6 +522,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void } if (flags & CONTEXT_AMD64_XSTATE) xstate_to_server( to, (const CONTEXT_EX *)(from + 1) ); + exception_request_flags_to_server( to, flags ); return STATUS_SUCCESS; }
@@ -550,6 +570,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->debug.arm_regs.wvr[i] = from->Wvr[i]; for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->debug.arm_regs.wcr[i] = from->Wcr[i]; } + exception_request_flags_to_server( to, flags ); return STATUS_SUCCESS; }
@@ -591,6 +612,7 @@ static NTSTATUS context_to_server( context_t *to, USHORT to_machine, const void for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->debug.arm64_regs.wcr[i] = from->Wcr[i]; for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->debug.arm64_regs.wvr[i] = from->Wvr[i]; } + exception_request_flags_to_server( to, flags ); return STATUS_SUCCESS; }
@@ -632,6 +654,20 @@ static void xstate_from_server( CONTEXT_EX *xctx, const context_t *from ) }
+/*********************************************************************** + * exception_request_flags_from_server + * + * Copy exception reporting flags from the server format. + */ +static void exception_request_flags_from_server( DWORD *context_flags, const context_t *from ) +{ + if (!(*context_flags & CONTEXT_EXCEPTION_REQUEST) || !(from->flags & SERVER_CTX_EXEC_SPACE)) return; + *context_flags = (*context_flags & ~(CONTEXT_SERVICE_ACTIVE | CONTEXT_EXCEPTION_ACTIVE)) | CONTEXT_EXCEPTION_REPORTING; + if (from->exec_space.space.space == EXEC_SPACE_SYSCALL) *context_flags |= CONTEXT_SERVICE_ACTIVE; + else if (from->exec_space.space.space == EXEC_SPACE_EXCEPTION) *context_flags |= CONTEXT_EXCEPTION_ACTIVE; +} + + /*********************************************************************** * context_from_server * @@ -706,6 +742,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma } if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_I386_XSTATE)) xstate_from_server( (CONTEXT_EX *)(to + 1), from ); + exception_request_flags_from_server( &to->ContextFlags, from ); return STATUS_SUCCESS; }
@@ -767,6 +804,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma } if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_I386_XSTATE)) xstate_from_server( (CONTEXT_EX *)(to + 1), from ); + exception_request_flags_from_server( &to->ContextFlags, from ); return STATUS_SUCCESS; }
@@ -829,6 +867,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma } if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_AMD64_XSTATE)) xstate_from_server( (CONTEXT_EX *)(to + 1), from ); + exception_request_flags_from_server( &to->ContextFlags, from ); return STATUS_SUCCESS; }
@@ -898,6 +937,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma } if ((from->flags & SERVER_CTX_YMM_REGISTERS) && (to_flags & CONTEXT_AMD64_XSTATE)) xstate_from_server( (CONTEXT_EX *)(to + 1), from ); + exception_request_flags_from_server( &to->ContextFlags, from ); return STATUS_SUCCESS; }
@@ -945,6 +985,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->Wvr[i] = from->debug.arm_regs.wvr[i]; for (i = 0; i < ARM_MAX_WATCHPOINTS; i++) to->Wcr[i] = from->debug.arm_regs.wcr[i]; } + exception_request_flags_from_server( &to->ContextFlags, from ); return STATUS_SUCCESS; }
@@ -986,6 +1027,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->Wcr[i] = from->debug.arm64_regs.wcr[i]; for (i = 0; i < ARM64_MAX_WATCHPOINTS; i++) to->Wvr[i] = from->debug.arm64_regs.wvr[i]; } + exception_request_flags_from_server( &to->ContextFlags, from ); return STATUS_SUCCESS; }
diff --git a/server/protocol.def b/server/protocol.def index 55dda2d7636..69b8db3ebef 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -126,6 +126,14 @@ typedef union } unload_dll; } debug_event_t;
+ +enum context_exec_space +{ + EXEC_SPACE_USERMODE, + EXEC_SPACE_SYSCALL, + EXEC_SPACE_EXCEPTION, +}; + /* context data */ typedef struct { @@ -172,6 +180,10 @@ typedef struct unsigned char i386_regs[512]; } ext; /* selected by SERVER_CTX_EXTENDED_REGISTERS */ union + { + struct { enum context_exec_space space; int __pad; } space; + } exec_space; /* selected by SERVER_CTX_EXEC_SPACE */ + union { struct { struct { unsigned __int64 low, high; } ymm_high[16]; } regs; } ymm; /* selected by SERVER_CTX_YMM_REGISTERS */ @@ -184,6 +196,7 @@ typedef struct #define SERVER_CTX_DEBUG_REGISTERS 0x10 #define SERVER_CTX_EXTENDED_REGISTERS 0x20 #define SERVER_CTX_YMM_REGISTERS 0x40 +#define SERVER_CTX_EXEC_SPACE 0x80
/* structure used in sending an fd from client to server */ struct send_fd diff --git a/server/thread.c b/server/thread.c index 56f57cefd8f..55bd63d3030 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1303,6 +1303,7 @@ static void copy_context( context_t *to, const context_t *from, unsigned int fla if (flags & SERVER_CTX_DEBUG_REGISTERS) to->debug = from->debug; if (flags & SERVER_CTX_EXTENDED_REGISTERS) to->ext = from->ext; if (flags & SERVER_CTX_YMM_REGISTERS) to->ymm = from->ymm; + if (flags & SERVER_CTX_EXEC_SPACE) to->exec_space = from->exec_space; }
/* gets the current impersonation token */ @@ -1941,14 +1942,14 @@ DECL_HANDLER(set_thread_context) /* If context is in a pending state, we don't know if we will use WoW or native * context, so store both and discard irrevelant one in select request. */ const int is_pending = thread->context->status == STATUS_PENDING; - unsigned int native_flags = contexts[CTX_NATIVE].flags; + unsigned int native_flags = contexts[CTX_NATIVE].flags & ~SERVER_CTX_EXEC_SPACE;
if (ctx_count == 2 && (is_pending || thread->context->regs[CTX_WOW].machine)) { context_t *ctx = &thread->context->regs[CTX_WOW];
/* some regs are always set from the native context */ - flags = contexts[CTX_WOW].flags & ~req->native_flags; + flags = contexts[CTX_WOW].flags & ~(req->native_flags | SERVER_CTX_EXEC_SPACE); if (is_pending) ctx->machine = contexts[CTX_WOW].machine; else native_flags &= req->native_flags;
diff --git a/server/trace.c b/server/trace.c index efb4bb03c4a..b254a96f7a4 100644 --- a/server/trace.c +++ b/server/trace.c @@ -822,6 +822,19 @@ static void dump_varargs_context( const char *prefix, data_size_t size ) fprintf( stderr, "%s{machine=%04x", prefix, ctx.machine ); break; } + if (ctx.flags & SERVER_CTX_EXEC_SPACE) + { + const char *space; + + switch (ctx.exec_space.space.space) + { + case EXEC_SPACE_USERMODE: space = "user"; break; + case EXEC_SPACE_SYSCALL: space = "syscall"; break; + case EXEC_SPACE_EXCEPTION: space = "exception"; break; + default: space = "invalid"; break; + } + fprintf( stderr, ",exec_space=%s", space ); + } fputc( '}', stderr ); remove_data( size ); } diff --git a/tools/make_requests b/tools/make_requests index e3eaaf45b6f..419b1264ea4 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -54,7 +54,7 @@ my %formats = "hw_input_t" => [ 40, 8, "&dump_hw_input" ], # varargs-only structures "apc_call_t" => [ 64, 8 ], - "context_t" => [ 1720, 8 ], + "context_t" => [ 1728, 8 ], "cursor_pos_t" => [ 24, 8 ], "debug_event_t" => [ 160, 8 ], "message_data_t" => [ 48, 8 ],
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/exception.c | 10 +++++----- dlls/ntdll/unix/signal_arm.c | 9 +++++++-- dlls/ntdll/unix/signal_arm64.c | 9 +++++++-- dlls/ntdll/unix/signal_i386.c | 9 +++++++-- dlls/ntdll/unix/signal_x86_64.c | 6 ++++-- 5 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index fb0e324d879..f9ad22f4044 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -4436,7 +4436,7 @@ static void test_wow64_context(void) { trace( "in 64-bit mode %04x\n", context.SegCs ); if (ctx.ContextFlags & CONTEXT_EXCEPTION_REPORTING) - todo_wine ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST + ok( ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_SERVICE_ACTIVE) || ctx.ContextFlags == (WOW64_CONTEXT_ALL | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE), @@ -11123,8 +11123,8 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == (CONTEXT_CONTROL - | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING)) /* Win7 64 */, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags || broken( c.ContextFlags == (CONTEXT_CONTROL + | CONTEXT_EXCEPTION_REQUEST | CONTEXT_EXCEPTION_REPORTING)) /* Win7 64 */, "got %#lx.\n", c.ContextFlags );
p.sync = 0; ResumeThread(thread); @@ -11166,7 +11166,7 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
c.ContextFlags = CONTEXT_CONTROL; ret = SetThreadContext( thread, &c ); @@ -11176,7 +11176,7 @@ static void test_context_exception_request(void) | CONTEXT_EXCEPTION_ACTIVE; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags ); + ok( c.ContextFlags == expected_flags, "got %#lx.\n", c.ContextFlags );
SetEvent( p.event );
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 44e79d0abdf..9c67309a4c7 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -1021,7 +1021,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
if (is_inside_syscall( sigcontext )) { - context.ContextFlags = CONTEXT_FULL; + context.ContextFlags = CONTEXT_FULL | CONTEXT_EXCEPTION_REQUEST; NtGetContextThread( GetCurrentThread(), &context ); wait_suspend( &context ); NtSetContextThread( GetCurrentThread(), &context ); @@ -1029,6 +1029,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) else { save_context( &context, sigcontext ); + context.ContextFlags |= CONTEXT_EXCEPTION_REPORTING; wait_suspend( &context ); restore_context( &context, sigcontext ); } @@ -1135,7 +1136,11 @@ void call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB if (context.Pc & 1) context.Cpsr |= 0x20; /* thumb mode */ if ((ctx = get_cpu_area( IMAGE_FILE_MACHINE_ARMNT ))) *ctx = context;
- if (suspend) wait_suspend( &context ); + if (suspend) + { + context.ContextFlags |= CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE; + wait_suspend( &context ); + }
ctx = (CONTEXT *)((ULONG_PTR)context.Sp & ~15) - 1; *ctx = context; diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 11340d88672..afb5964758e 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -1225,7 +1225,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
if (is_inside_syscall( sigcontext )) { - context.ContextFlags = CONTEXT_FULL; + context.ContextFlags = CONTEXT_FULL | CONTEXT_EXCEPTION_REQUEST; NtGetContextThread( GetCurrentThread(), &context ); wait_suspend( &context ); NtSetContextThread( GetCurrentThread(), &context ); @@ -1233,6 +1233,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) else { save_context( &context, sigcontext ); + context.ContextFlags |= CONTEXT_EXCEPTION_REPORTING; wait_suspend( &context ); restore_context( &context, sigcontext ); } @@ -1418,7 +1419,11 @@ void call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB if (arm_context->Pc & 1) arm_context->Cpsr |= 0x20; /* thumb mode */ }
- if (suspend) wait_suspend( &context ); + if (suspend) + { + context.ContextFlags |= CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE; + wait_suspend( &context ); + }
ctx = (CONTEXT *)((ULONG_PTR)context.Sp & ~15) - 1; *ctx = context; diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 6e2752745d3..9588d480a42 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -2130,7 +2130,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ERR_(seh)( "kernel stack overflow.\n" ); return; } - context->c.ContextFlags = CONTEXT_FULL; + context->c.ContextFlags = CONTEXT_FULL | CONTEXT_EXCEPTION_REQUEST; NtGetContextThread( GetCurrentThread(), &context->c ); if (xstate_extended_features()) { @@ -2153,6 +2153,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) struct xcontext context;
save_context( &context, ucontext ); + context.c.ContextFlags |= CONTEXT_EXCEPTION_REPORTING; wait_suspend( &context.c ); restore_context( &context, ucontext ); } @@ -2514,7 +2515,11 @@ void call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB ((XSAVE_FORMAT *)context.ExtendedRegisters)->MxCsr = 0x1f80; if ((ctx = get_cpu_area( IMAGE_FILE_MACHINE_I386 ))) *ctx = context;
- if (suspend) wait_suspend( &context ); + if (suspend) + { + context.ContextFlags |= CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE; + wait_suspend( &context ); + }
ctx = (CONTEXT *)((ULONG_PTR)context.Esp & ~3) - 1; *ctx = context; diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 41e5f9531d5..d439848a113 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2172,7 +2172,7 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ERR_(seh)( "kernel stack overflow.\n" ); return; } - context->c.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS; + context->c.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS | CONTEXT_EXCEPTION_REQUEST; NtGetContextThread( GetCurrentThread(), &context->c ); if (xstate_extended_features()) { @@ -2195,6 +2195,8 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) struct xcontext context;
save_context( &context, ucontext ); + context.c.ContextFlags |= CONTEXT_EXCEPTION_REPORTING; + if (is_wow64() && context.c.SegCs == cs64_sel) context.c.ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; wait_suspend( &context.c ); restore_context( &context, ucontext ); } @@ -2536,7 +2538,7 @@ void call_init_thunk( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB # error Please define setting %gs for your architecture #endif
- context.ContextFlags = CONTEXT_ALL; + context.ContextFlags = CONTEXT_ALL | CONTEXT_EXCEPTION_REPORTING | CONTEXT_EXCEPTION_ACTIVE; context.Rcx = (ULONG_PTR)entry; context.Rdx = (ULONG_PTR)arg; context.Rsp = (ULONG_PTR)teb->Tib.StackBase - 0x28;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/tests/exception.c | 6 +++--- dlls/ntdll/unix/signal_arm.c | 2 +- dlls/ntdll/unix/signal_arm64.c | 2 +- dlls/ntdll/unix/signal_i386.c | 2 +- dlls/ntdll/unix/signal_x86_64.c | 2 +- dlls/ntdll/unix/thread.c | 6 ++++-- dlls/ntdll/unix/unix_private.h | 2 +- 7 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index f9ad22f4044..69d5d80267d 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -239,7 +239,7 @@ static void check_context_exception_request_( DWORD flags, BOOL hardware_excepti
if (!(flags & CONTEXT_EXCEPTION_REPORTING)) return; expected_flags |= hardware_exception ? CONTEXT_EXCEPTION_ACTIVE : CONTEXT_SERVICE_ACTIVE; - todo_wine ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n", + ok_(__FILE__, line)( (flags & exception_reporting_flags) == expected_flags, "got %#lx, expected %#lx.\n", flags, expected_flags ); } #endif @@ -11191,7 +11191,7 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags ); + ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags );
WriteRelease( &p.sync, 4 ); } @@ -11225,7 +11225,7 @@ static void test_context_exception_request(void) c.ContextFlags = CONTEXT_CONTROL | CONTEXT_EXCEPTION_REQUEST; ret = GetThreadContext( thread, &c ); ok( ret, "got error %lu.\n", GetLastError() ); - todo_wine ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags ); + ok( c.ContextFlags == expected_flags, "got %#lx, expected %#lx.\n", c.ContextFlags, expected_flags );
WriteRelease( &p.sync, 8 ); } diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 9c67309a4c7..1a49fc8f957 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -545,7 +545,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec void *stack_ptr = (void *)(SP_sig(sigcontext) & ~7); NTSTATUS status;
- status = send_debug_event( rec, context, TRUE ); + status = send_debug_event( rec, context, TRUE, TRUE ); if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) { restore_context( context, sigcontext ); diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index afb5964758e..58911d9b1f2 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -699,7 +699,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec void *stack_ptr = (void *)(SP_sig(sigcontext) & ~15); NTSTATUS status;
- status = send_debug_event( rec, context, TRUE ); + status = send_debug_event( rec, context, TRUE, TRUE ); if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) { restore_context( context, sigcontext ); diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 9588d480a42..6457f0221bd 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1450,7 +1450,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, void *stack_ptr, struct exc_stack_layout *stack; size_t stack_size; unsigned int xstate_size; - NTSTATUS status = send_debug_event( rec, context, TRUE ); + NTSTATUS status = send_debug_event( rec, context, TRUE, TRUE );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) { diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index d439848a113..a163d5d0b33 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1426,7 +1426,7 @@ static void setup_raise_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec context->EFlags &= ~0x100; /* clear single-step flag */ }
- status = send_debug_event( rec, context, TRUE ); + status = send_debug_event( rec, context, TRUE, TRUE ); if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) { restore_context( xcontext, sigcontext ); diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 21b581ddc7c..6922ad2cba6 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1506,7 +1506,7 @@ void wait_suspend( CONTEXT *context ) * * Send an EXCEPTION_DEBUG_EVENT event to the debugger. */ -NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) +NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance, BOOL exception ) { unsigned int ret; DWORD i; @@ -1543,6 +1543,8 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c select_op.wait.handles[0] = handle;
contexts_to_server( server_contexts, context ); + server_contexts[0].flags |= SERVER_CTX_EXEC_SPACE; + server_contexts[0].exec_space.space.space = exception ? EXEC_SPACE_EXCEPTION : EXEC_SPACE_SYSCALL; server_select( &select_op, offsetof( select_op_t, wait.handles[1] ), SELECT_INTERRUPTIBLE, TIMEOUT_INFINITE, server_contexts, NULL );
@@ -1565,7 +1567,7 @@ NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_c */ NTSTATUS WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ) { - NTSTATUS status = send_debug_event( rec, context, first_chance ); + NTSTATUS status = send_debug_event( rec, context, first_chance, !(is_win64 || is_wow64() || is_old_wow64()) );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED) return NtContinue( context, FALSE ); diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index ec11f9d4795..b278ab8df84 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -244,7 +244,7 @@ extern void DECLSPEC_NORETURN abort_thread( int status ); extern void DECLSPEC_NORETURN abort_process( int status ); extern void DECLSPEC_NORETURN exit_process( int status ); extern void wait_suspend( CONTEXT *context ); -extern NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance ); +extern NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance, BOOL exception ); extern NTSTATUS set_thread_context( HANDLE handle, const void *context, BOOL *self, USHORT machine ); extern NTSTATUS get_thread_context( HANDLE handle, void *context, BOOL *self, USHORT machine ); extern unsigned int alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct object_attributes **ret,
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=145020
Your paranoid android.
=== build (build log) ===
../wine/dlls/ntdll/tests/exception.c:11050:22: error: ���old_wow64��� undeclared (first use in this function); did you mean ���is_wow64���? ../wine/dlls/ntdll/tests/exception.c:11183:22: error: ���old_wow64��� undeclared (first use in this function); did you mean ���is_wow64���? Task: The exe32 Wine build failed
=== debian11 (build log) ===
../wine/dlls/ntdll/tests/exception.c:11050:22: error: ���old_wow64��� undeclared (first use in this function); did you mean ���is_wow64���? ../wine/dlls/ntdll/tests/exception.c:11183:22: error: ���old_wow64��� undeclared (first use in this function); did you mean ���is_wow64���? Task: The win32 Wine build failed
=== debian11b (build log) ===
../wine/dlls/ntdll/tests/exception.c:11183:22: error: ���old_wow64��� undeclared (first use in this function); did you mean ���is_wow64���? Task: The wow64 Wine build failed