rendered paste bodydiff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index d18f3d2..e6c45fc 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -39,6 +39,7 @@
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 void *code_mem;
/* Test various instruction combinations that cause a protection fault on the i386,
@@ -184,6 +185,79 @@ 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 )
+{
+ trace( "exception: %08x flags:%x addr:%p context: Eip:%x\n",
+ rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress, context->Eip );
+
+ ok((DWORD)rec->ExceptionAddress == (DWORD)code_mem + 0xb, "ExceptionAddress at %p instead of %x\n",
+ rec->ExceptionAddress, (DWORD)code_mem + 0xb);
+
+ /* check that context.Eip is fixed up only for EXCEPTION_BREAKPOINT
+ * even if raised by RtlRaiseException
+ */
+ if(rec->ExceptionCode == EXCEPTION_BREAKPOINT)
+ {
+ todo_wine {
+ ok((DWORD)context->Eip == (DWORD)code_mem + 0xa, "Eip at %x instead of %x\n",
+ context->Eip, (DWORD)code_mem + 0xa);
+ }
+ }
+ else
+ {
+ ok((DWORD)context->Eip == (DWORD)code_mem + 0xb, "Eip at %x instead of %x\n",
+ context->Eip, (DWORD)code_mem + 0xb);
+ }
+
+ /* 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 && ((DWORD)context->Eip == (DWORD)code_mem + 0xa))
+ context->Eip += 1;
+ return ExceptionContinueExecution;
+}
+
+
+static const BYTE call_one_arg_code[] = {
+ 0x8b, 0x44, 0x24, 0x08, /* mov eax, [esp+8] */
+ 0x50, /* push eax */
+ 0x8b, 0x44, 0x24, 0x08, /* mov eax, [esp+8] */
+ 0xff, 0xd0, /* call eax */
+ 0x90, /* nop */
+ 0x90, /* nop */
+ 0x90, /* nop */
+ 0x90, /* nop */
+ 0xc3, /* ret */
+};
+
+
+static void run_exception_test2(DWORD exception_code, const void* context//,
+ /*const void *code, unsigned int code_size*/)
+{
+
+ EXCEPTION_REGISTRATION_RECORD frame;
+ EXCEPTION_RECORD record;
+
+ void (*func)(void* args, void* raisefunc) = code_mem;
+
+ record.ExceptionCode = exception_code;
+ record.ExceptionFlags = 0;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = NULL; // does not matter, copied from context.Eip
+ record.NumberParameters = 0;
+// trace("raising exception: %x setting record.ExceptionAddress to %p\n", exception_code, record.ExceptionAddress);
+
+ frame.Handler = handler2;
+ frame.Prev = pNtCurrentTeb()->Tib.ExceptionList;
+
+ memcpy(code_mem, call_one_arg_code, sizeof(call_one_arg_code));
+
+ pNtCurrentTeb()->Tib.ExceptionList = &frame;
+ func(pRtlRaiseException, &record);
+ pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
+}
+
+
static DWORD handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
{
@@ -391,6 +465,8 @@ static void test_exceptions(void)
pNtGetContextThread = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtGetContextThread" );
pNtSetContextThread = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtSetContextThread" );
+ pRtlRaiseException = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"), "RtlRaiseException" );
+
if (!pNtGetContextThread || !pNtSetContextThread)
{
trace( "NtGetContextThread/NtSetContextThread not found, skipping tests\n" );
@@ -400,6 +476,15 @@ static void test_exceptions(void)
/* test handling of debug registers */
run_exception_test(dreg_handler, NULL, &segfault_code, sizeof(segfault_code));
+ if (pRtlRaiseException)
+ {
+ run_exception_test2(0x12345, NULL);
+ run_exception_test2(EXCEPTION_BREAKPOINT, NULL);
+ run_exception_test2(EXCEPTION_INVALID_HANDLE, NULL);
+ }
+ else
+ skip( "RtlRaiseException not found\n" );
+
ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
res = pNtGetContextThread(GetCurrentThread(), &ctx);
ok (res == STATUS_SUCCESS,"NtGetContextThread failed with %x\n", res);