Peter Oberndorfer : ntdll:
Add a vectored exception handling test to the existing
RtlRaiseException test .
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Feb 16 07:08:34 CST 2007
Module: wine
Branch: master
Commit: a30bc5808e253fd6e3405cc85f3dd353b7285463
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a30bc5808e253fd6e3405cc85f3dd353b7285463
Author: Peter Oberndorfer <kumbayo84 at 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));
More information about the wine-cvs
mailing list