Fixes _exception_code() inside exception handlers.
From: Jacek Caban jacek@codeweavers.com
Fixes _exception_code() inside exception handlers. --- dlls/ntdll/tests/exception.c | 56 ++++++++++++++++++++++++++++++++++++ dlls/ntdll/unwind.c | 9 ++++-- 2 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index f88d9714d13..550c99a06b8 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -2639,8 +2639,42 @@ static void WINAPI termination_handler(ULONG flags, ULONG64 frame) ok(frame == 0x1234, "frame = %p\n", (void*)frame); }
+struct exception_code_context +{ + EXCEPTION_RECORD *rec; + CONTEXT *context; + DISPATCHER_CONTEXT *dispatch; +}; + +static void invoke_c_handler(struct exception_code_context *ctx, ULONG_PTR frame) +{ + p__C_specific_handler(ctx->rec, frame, ctx->context, ctx->dispatch); + ok(0, "__C_specific_handler returned\n"); +} + +static void check_exception_code(ULONG_PTR code) +{ + ok(code == 0x123, "code = %llx\n", code); +} + +static char call_invoke_c_handler_code[] = { + 0x48,0x83,0xec,0x28, /* 0: subq $0x28, %rsp*/ + 0x48,0x89,0xe2, /* 4: movq %rsp, %rdx */ + 0x48,0xb8,0,0,0,0,0,0,0,0, /* 7: movabsq $invoke_c_handler, %rax */ + 0xff,0xd0, /* 17: callq *%rax */ + 0xcc, /* 19: int3 */ + /* exception handler: */ + 0x48,0x89,0xc1, /* 20: movq %rax, %rcx */ + 0x48,0xb8,0,0,0,0,0,0,0,0, /* 23: movabsq $check_exception_code, %rax */ + 0xff,0xd0, /* 33: callq *%rax */ + 0x48,0x83,0xc4,0x28, /* 35: addq $0x28, %rsp */ + 0xc3 /* 39: retq */ +}; + static void test___C_specific_handler(void) { + void (*test_exception_code)(void *ctx) = code_mem; + struct exception_code_context ctx; DISPATCHER_CONTEXT dispatch; EXCEPTION_RECORD rec; CONTEXT context; @@ -2681,6 +2715,28 @@ static void test___C_specific_handler(void) ok(termination_handler_called == 1, "termination_handler_called = %d\n", termination_handler_called); ok(dispatch.ScopeIndex == 1, "dispatch.ScopeIndex = %ld\n", dispatch.ScopeIndex); + + *(void **)&call_invoke_c_handler_code[9] = invoke_c_handler; + *(void **)&call_invoke_c_handler_code[25] = check_exception_code; + memcpy(code_mem, call_invoke_c_handler_code, sizeof(call_invoke_c_handler_code)); + memset(&rec, 0, sizeof(rec)); + memset(&dispatch, 0, sizeof(dispatch)); + memset(&context, 0, sizeof(context)); + rec.ExceptionCode = 0x123; + dispatch.ImageBase = (ULONG_PTR)code_mem - 0x1000; + dispatch.ControlPc = (ULONG_PTR)code_mem + 7; + dispatch.HandlerData = &scope_table; + dispatch.ContextRecord = &context; + scope_table.Count = 1; + scope_table.ScopeRecord[0].BeginAddress = 0x1000; + scope_table.ScopeRecord[0].EndAddress = 0x1013; + scope_table.ScopeRecord[0].HandlerAddress = EXCEPTION_EXECUTE_HANDLER; + scope_table.ScopeRecord[0].JumpTarget = 0x1014; + + ctx.rec = &rec; + ctx.context = &context; + ctx.dispatch = &dispatch; + test_exception_code(&ctx); }
/* This is heavily based on the i386 exception tests. */ diff --git a/dlls/ntdll/unwind.c b/dlls/ntdll/unwind.c index c11bd9ddb9c..cd898086862 100644 --- a/dlls/ntdll/unwind.c +++ b/dlls/ntdll/unwind.c @@ -902,7 +902,8 @@ EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void * } TRACE( "unwinding to target %Ix\n", base + table->ScopeRecord[i].JumpTarget ); RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget, - rec, 0, (CONTEXT *)dispatch->ContextRecord, dispatch->HistoryTable ); + rec, ULongToPtr(rec->ExceptionCode), (CONTEXT *)dispatch->ContextRecord, + dispatch->HistoryTable ); } } return ExceptionContinueSearch; @@ -1593,7 +1594,8 @@ EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void * } TRACE( "unwinding to target %lx\n", base + table->ScopeRecord[i].JumpTarget ); RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget, - rec, 0, dispatch->ContextRecord, dispatch->HistoryTable ); + rec, ULongToPtr(rec->ExceptionCode), dispatch->ContextRecord, + dispatch->HistoryTable ); } } return ExceptionContinueSearch; @@ -2261,7 +2263,8 @@ EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void * } TRACE( "unwinding to target %Ix\n", base + table->ScopeRecord[i].JumpTarget ); RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget, - rec, 0, dispatch->ContextRecord, dispatch->HistoryTable ); + rec, ULongToPtr(rec->ExceptionCode), dispatch->ContextRecord, + dispatch->HistoryTable ); } } return ExceptionContinueSearch;