rendered paste bodydiff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index be82a84..05dd7cc 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -261,8 +261,8 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
}
/* Call handler */
- TRACE( "calling handler at %p code=%x flags=%x\n",
- frame->Handler, rec->ExceptionCode, rec->ExceptionFlags );
+ TRACE( "calling handler at %p code=%x flags=%x address=%p\n",
+ frame->Handler, rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
res = EXC_CallHandler( rec, frame, context, &dispatch, frame->Handler, EXC_RaiseHandler );
TRACE( "handler at %p returned %x\n", frame->Handler, res );
@@ -302,6 +302,10 @@ static NTSTATUS raise_exception( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL f
{
NTSTATUS status;
+ if (rec->ExceptionCode == EXCEPTION_BREAKPOINT)
+// GET_IP(context) = (char *)GET_IP(context) - 1;
+ context->Eip = (char *)context->Eip - 1;
+
if (first_chance)
{
DWORD c;
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index d18f3d2..c7fd195 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -39,6 +39,9 @@
static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
static NTSTATUS (WINAPI *pNtGetContextThread)(HANDLE,CONTEXT*);
static NTSTATUS (WINAPI *pNtSetContextThread)(HANDLE,CONTEXT*);
+static NTSTATUS (WINAPI *pRtlRaiseException)(EXCEPTION_RECORD *rec);
+static NTSTATUS (WINAPI *pNtRaiseException)(EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance);
+// static PVOID (WINAPI RtlAddVectoredExceptionHandler)(ULONG first, PVECTORED_EXCEPTION_HANDLER func);
static void *code_mem;
/* Test various instruction combinations that cause a protection fault on the i386,
@@ -162,6 +165,8 @@ static const struct exception
0, 5, STATUS_ACCESS_VIOLATION, 2, { 1, 0xffffffff } },
};
+static const BYTE int3_code[] = { 0xCC, 0xc3 }; /* int 3, ret */
+
static int got_exception;
static void run_exception_test(const void *handler, const void* context,
@@ -184,6 +189,120 @@ static void run_exception_test(const void *handler, const void* context,
pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
}
+static DWORD handler2( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
+ CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
+{
+// const struct exception *except = *(const struct exception **)(frame + 1);
+// unsigned int i, entry = except - exceptions;
+ CONTEXT ctx;
+ NTSTATUS ret;
+
+ got_exception++;
+ trace( "exception2: %08x flags:%x addr:%p context: Eip:%x\n",
+ rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, context->Eip );
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ContextFlags = CONTEXT_CONTROL;//CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
+ ret = pNtGetContextThread(GetCurrentThread(), &ctx);/* not fully valid as we are currently running */
+ ok(!ret, "NtGetContextThread failed\n");
+ trace( "NtGetContextThread Eip:%p\n", ctx.Eip);
+
+// trace( "\n", context->Eip);
+
+// ok( rec->ExceptionCode == except->status,
+// "%u: Wrong exception code %x/%x\n", entry, rec->ExceptionCode, except->status );
+// ok( rec->ExceptionAddress == (char*)code_mem + except->offset,
+// "%u: Wrong exception address %p/%p\n", entry,
+// rec->ExceptionAddress, (char*)code_mem + except->offset );
+
+// ok( rec->NumberParameters == except->nb_params,
+// "%u: Wrong number of parameters %u/%u\n", entry, rec->NumberParameters, except->nb_params );
+
+ /* Most CPUs (except Intel Core apparently) report a segment limit violation */
+ /* instead of page faults for accesses beyond 0xffffffff */
+// if (except->nb_params == 2 && except->params[1] >= 0xfffffffd)
+// {
+// if (rec->ExceptionInformation[0] == 0 && rec->ExceptionInformation[1] == 0xffffffff)
+// goto skip_params;
+// }
+
+// for (i = 0; i < rec->NumberParameters; i++)
+// ok( rec->ExceptionInformation[i] == except->params[i],
+// "%u: Wrong parameter %d: %lx/%x\n",
+// entry, i, rec->ExceptionInformation[i], except->params[i] );
+
+// skip_params:
+ /* don't handle exception if it's not the address we expected */
+// if (rec->ExceptionAddress != (char*)code_mem + except->offset) return ExceptionContinueSearch;
+
+// if(got_exception == 2)
+ /* Eip in context is decreased by 1
+ * Increase it again, else execution will continue in the middle of a instruction */
+ if(rec->ExceptionCode == EXCEPTION_BREAKPOINT)
+ context->Eip += 1;
+ return ExceptionContinueExecution;
+}
+
+static void run_exception_test2(DWORD exception_code, const void* context//,
+ /*const void *code, unsigned int code_size*/)
+{
+ struct {
+ EXCEPTION_REGISTRATION_RECORD frame;
+ const void *context;
+ } exc_frame;
+ EXCEPTION_RECORD record;
+
+ record.ExceptionCode = exception_code;
+ record.ExceptionFlags = 0;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = NULL;//&int3_code;
+ record.NumberParameters = 0;
+ trace("raising exception: %x setting record.ExceptionAddress to %x\n", exception_code, record.ExceptionAddress);
+
+ exc_frame.frame.Handler = handler2;
+ exc_frame.frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
+ exc_frame.context = context;
+
+ pNtCurrentTeb()->Tib.ExceptionList = &exc_frame.frame;
+ pRtlRaiseException(&record);
+ pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
+}
+
+static void run_exception_test3(DWORD exception_code, const void* context//,
+ /*const void *code, unsigned int code_size*/)
+{
+ struct {
+ EXCEPTION_REGISTRATION_RECORD frame;
+ const void *context;
+ } exc_frame;
+
+ EXCEPTION_RECORD record;
+ CONTEXT ctx, ctx2;
+ NTSTATUS ret;
+
+ ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+ ret = pNtGetContextThread(GetCurrentThread(), &ctx);/* not fully valid as we are currently running */
+ ok(!ret, "NtGetContextThread failed\n");
+ memcpy(&ctx2, &ctx, sizeof(ctx));
+
+ record.ExceptionCode = exception_code;
+ record.ExceptionFlags = 0;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = NULL;//&int3_code;
+ record.NumberParameters = 0;
+ trace("setting record.ExceptionAddress to %x\n", record.ExceptionAddress);
+
+ exc_frame.frame.Handler = handler2;
+ exc_frame.frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
+ exc_frame.context = context;
+
+ pNtCurrentTeb()->Tib.ExceptionList = &exc_frame.frame;
+ pNtRaiseException(&record, &ctx, TRUE);
+ ok(memcmp(&ctx2, &ctx, sizeof(ctx)) == 0, "context should be the same after call\n");
+ pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
+}
+
+
static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
{
@@ -373,15 +492,15 @@ static DWORD int3_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD
{
ok( rec->ExceptionAddress == code_mem, "exception address not at: %p, but at %p\n",
code_mem, rec->ExceptionAddress);
- todo_wine {
+// todo_wine {
ok( context->Eip == (DWORD)code_mem, "eip not at: %p, but at %#x\n", code_mem, context->Eip);
- }
+// }
if(context->Eip == (DWORD)code_mem) context->Eip++; /* skip breakpoint */
return ExceptionContinueExecution;
}
-static const BYTE int3_code[] = { 0xCC, 0xc3 }; /* int 3, ret */
+// static const BYTE int3_code[] = { 0xCC, 0xc3 }; /* int 3, ret */
static void test_exceptions(void)
@@ -391,7 +510,11 @@ static void test_exceptions(void)
pNtGetContextThread = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtGetContextThread" );
pNtSetContextThread = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtSetContextThread" );
- if (!pNtGetContextThread || !pNtSetContextThread)
+ pRtlRaiseException = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlRaiseException" );
+ pNtRaiseException = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtRaiseException" );
+// pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlAddVectoredExceptionHandler" );
+
+ if (!pNtGetContextThread || !pNtSetContextThread || !pRtlRaiseException || !pNtRaiseException /*|| !pRtlAddVectoredExceptionHandler*/)
{
trace( "NtGetContextThread/NtSetContextThread not found, skipping tests\n" );
return;
@@ -399,6 +522,11 @@ static void test_exceptions(void)
/* test handling of debug registers */
run_exception_test(dreg_handler, NULL, &segfault_code, sizeof(segfault_code));
+ run_exception_test2(0x12345, NULL);
+ run_exception_test2(EXCEPTION_BREAKPOINT, NULL);
+
+ run_exception_test3(0x12345, NULL);
+ run_exception_test3(EXCEPTION_BREAKPOINT, NULL);
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
res = pNtGetContextThread(GetCurrentThread(), &ctx);