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