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.
This commit is contained in:
Peter Oberndorfer 2007-02-15 19:45:51 +01:00 committed by Alexandre Julliard
parent 6ede7a1130
commit a30bc5808e
1 changed files with 58 additions and 1 deletions

View File

@ -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));