Module: wine Branch: master Commit: a30bc5808e253fd6e3405cc85f3dd353b7285463 URL: http://source.winehq.org/git/wine.git/?a=commit;h=a30bc5808e253fd6e3405cc85f...
Author: Peter Oberndorfer kumbayo84@arcor.de Date: Thu Feb 15 19:45:51 2007 +0100
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.
---
dlls/ntdll/tests/exception.c | 59 +++++++++++++++++++++++++++++++++++++++++- 1 files changed, 58 insertions(+), 1 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index e892bc6..557f779 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -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));