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 0f697fd3bd0..e4cd8f8f8b5 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -240,7 +240,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 @@ -1121,7 +1121,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);
@@ -3594,7 +3594,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, @@ -4357,7 +4357,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) @@ -4445,7 +4445,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), @@ -11157,13 +11157,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 ); @@ -11213,13 +11213,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 ],