Commit a30bc580 authored by Peter Oberndorfer's avatar Peter Oberndorfer Committed by Alexandre Julliard

ntdll: Add a vectored exception handling test to the existing RtlRaiseException test.

Show that context changes in vectored handler also affect stack handlers. Show that vectored handlers also get the changed context.Eip value.
parent 6ede7a11
......@@ -40,6 +40,8 @@ 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 PVOID (WINAPI *pRtlAddVectoredExceptionHandler)(ULONG first, PVECTORED_EXCEPTION_HANDLER func);
static ULONG (WINAPI *pRtlRemoveVectoredExceptionHandler)(PVOID handler);
static void *code_mem;
/* Test various instruction combinations that cause a protection fault on the i386,
......@@ -164,6 +166,7 @@ static const struct exception
};
static int got_exception;
static BOOL have_vectored_api;
static void run_exception_test(const void *handler, const void* context,
const void *code, unsigned int code_size)
......@@ -185,6 +188,39 @@ static void run_exception_test(const void *handler, const void* context,
pNtCurrentTeb()->Tib.ExceptionList = exc_frame.frame.Prev;
}
LONG CALLBACK rtlraiseexception_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
{
PCONTEXT context = ExceptionInfo->ContextRecord;
PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
trace("vect. handler %08x addr:%p context.Eip:%x\n", rec->ExceptionCode,
rec->ExceptionAddress, context->Eip);
todo_wine {
ok(rec->ExceptionAddress == (char *)code_mem + 0xb, "ExceptionAddress at %p instead of %p\n",
rec->ExceptionAddress, (char *)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(context->Eip == (DWORD)code_mem + 0xa, "Eip at %x instead of %x\n",
context->Eip, (DWORD)code_mem + 0xa);
}
}
else
{
ok(context->Eip == (DWORD)code_mem + 0xb, "Eip at %x instead of %x\n",
context->Eip, (DWORD)code_mem + 0xb);
}
/* test if context change is preserved from vectored handler to stack handlers */
context->Eax = 0xf00f00f0;
return EXCEPTION_CONTINUE_SEARCH;
}
static DWORD rtlraiseexception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
{
......@@ -212,6 +248,10 @@ static DWORD rtlraiseexception_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTR
context->Eip, (DWORD)code_mem + 0xb);
}
if(have_vectored_api)
ok(context->Eax == 0xf00f00f0, "Eax is %x, should have been set to 0xf00f00f0 in vectored handler\n",
context->Eax);
/* 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 == (DWORD)code_mem + 0xa))
......@@ -235,9 +275,9 @@ static const BYTE call_one_arg_code[] = {
static void run_rtlraiseexception_test(DWORD exceptioncode)
{
EXCEPTION_REGISTRATION_RECORD frame;
EXCEPTION_RECORD record;
PVOID vectored_handler = NULL;
void (*func)(void* function, EXCEPTION_RECORD* record) = code_mem;
......@@ -253,7 +293,16 @@ static void run_rtlraiseexception_test(DWORD exceptioncode)
memcpy(code_mem, call_one_arg_code, sizeof(call_one_arg_code));
pNtCurrentTeb()->Tib.ExceptionList = &frame;
if (have_vectored_api)
{
vectored_handler = pRtlAddVectoredExceptionHandler(TRUE, &rtlraiseexception_vectored_handler);
ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
}
func(pRtlRaiseException, &record);
if (have_vectored_api)
pRtlRemoveVectoredExceptionHandler(vectored_handler);
pNtCurrentTeb()->Tib.ExceptionList = frame.Prev;
}
......@@ -466,12 +515,20 @@ 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" );
pRtlAddVectoredExceptionHandler = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"),
"RtlAddVectoredExceptionHandler" );
pRtlRemoveVectoredExceptionHandler = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"),
"RtlRemoveVectoredExceptionHandler" );
if (!pNtGetContextThread || !pNtSetContextThread)
{
trace( "NtGetContextThread/NtSetContextThread not found, skipping tests\n" );
return;
}
if (pRtlAddVectoredExceptionHandler && pRtlRemoveVectoredExceptionHandler)
have_vectored_api = TRUE;
else
skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
/* test handling of debug registers */
run_exception_test(dreg_handler, NULL, &segfault_code, sizeof(segfault_code));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment