From: Sebastian Lackner Subject: [2/2] ntdll: Implement Rtl[Add|Remove]VectoredContinueHandler semi-stubs. Message-Id: <54655004.4090505@fds-team.de> Date: Fri, 14 Nov 2014 01:42:44 +0100 This patch moves the code for vectored exception handlers to common functions, and then implements semi-stubs for continue handlers. --- dlls/ntdll/exception.c | 85 +++++++++++++++++++++++++------------------- dlls/ntdll/tests/exception.c | 5 --- 2 files changed, 49 insertions(+), 41 deletions(-) From 58cfe8df990c151121865f90f9a395205ca6ac33 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Fri, 14 Nov 2014 00:12:07 +0100 Subject: ntdll: Implement Rtl[Add|Remove]VectoredContinueHandler semi-stubs. --- dlls/ntdll/exception.c | 85 +++++++++++++++++++++++++------------------- dlls/ntdll/tests/exception.c | 5 --- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index 37edc77..5b4abb6 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -47,7 +47,8 @@ typedef struct ULONG count; } VECTORED_HANDLER; -static struct list vectored_handlers = LIST_INIT(vectored_handlers); +static struct list vectored_exception_handlers = LIST_INIT(vectored_exception_handlers); +static struct list vectored_continue_handlers = LIST_INIT(vectored_continue_handlers); static RTL_CRITICAL_SECTION vectored_handlers_section; static RTL_CRITICAL_SECTION_DEBUG critsect_debug = @@ -58,6 +59,47 @@ static RTL_CRITICAL_SECTION_DEBUG critsect_debug = }; static RTL_CRITICAL_SECTION vectored_handlers_section = { &critsect_debug, -1, 0, 0, 0, 0 }; + +static VECTORED_HANDLER *add_vectored_handler( struct list *handler_list, ULONG first, + PVECTORED_EXCEPTION_HANDLER func ) +{ + VECTORED_HANDLER *handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) ); + if (handler) + { + handler->func = RtlEncodePointer( func ); + handler->count = 1; + RtlEnterCriticalSection( &vectored_handlers_section ); + if (first) list_add_head( handler_list, &handler->entry ); + else list_add_tail( handler_list, &handler->entry ); + RtlLeaveCriticalSection( &vectored_handlers_section ); + } + return handler; +} + + +static ULONG remove_vectored_handler( struct list *handler_list, VECTORED_HANDLER *handler ) +{ + struct list *ptr; + ULONG ret = FALSE; + + RtlEnterCriticalSection( &vectored_handlers_section ); + LIST_FOR_EACH( ptr, handler_list ) + { + VECTORED_HANDLER *curr_handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry ); + if (curr_handler == handler) + { + if (!--curr_handler->count) list_remove( ptr ); + else handler = NULL; /* don't free it yet */ + ret = TRUE; + break; + } + } + RtlLeaveCriticalSection( &vectored_handlers_section ); + if (ret) RtlFreeHeap( GetProcessHeap(), 0, handler ); + return ret; +} + + /********************************************************************** * wait_suspend * @@ -165,7 +207,7 @@ LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) except_ptrs.ContextRecord = context; RtlEnterCriticalSection( &vectored_handlers_section ); - ptr = list_head( &vectored_handlers ); + ptr = list_head( &vectored_exception_handlers ); while (ptr) { handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry ); @@ -181,7 +223,7 @@ LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) TRACE( "handler at %p returned %x\n", func, ret ); RtlEnterCriticalSection( &vectored_handlers_section ); - ptr = list_next( &vectored_handlers, ptr ); + ptr = list_next( &vectored_exception_handlers, ptr ); if (!--handler->count) /* removed during execution */ { list_remove( &handler->entry ); @@ -228,8 +270,7 @@ void WINAPI RtlRaiseStatus( NTSTATUS status ) */ PVOID WINAPI RtlAddVectoredContinueHandler( ULONG first, PVECTORED_EXCEPTION_HANDLER func ) { - FIXME("%u %p stub\n", first, func); - return NULL; + return add_vectored_handler( &vectored_continue_handlers, first, func ); } @@ -238,8 +279,7 @@ PVOID WINAPI RtlAddVectoredContinueHandler( ULONG first, PVECTORED_EXCEPTION_HAN */ ULONG WINAPI RtlRemoveVectoredContinueHandler( PVOID handler ) { - FIXME("%p stub\n", handler); - return FALSE; + return remove_vectored_handler( &vectored_continue_handlers, handler ); } @@ -248,17 +288,7 @@ ULONG WINAPI RtlRemoveVectoredContinueHandler( PVOID handler ) */ PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HANDLER func ) { - VECTORED_HANDLER *handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) ); - if (handler) - { - handler->func = RtlEncodePointer( func ); - handler->count = 1; - RtlEnterCriticalSection( &vectored_handlers_section ); - if (first) list_add_head( &vectored_handlers, &handler->entry ); - else list_add_tail( &vectored_handlers, &handler->entry ); - RtlLeaveCriticalSection( &vectored_handlers_section ); - } - return handler; + return add_vectored_handler( &vectored_exception_handlers, first, func ); } @@ -267,24 +297,7 @@ PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HA */ ULONG WINAPI RtlRemoveVectoredExceptionHandler( PVOID handler ) { - struct list *ptr; - ULONG ret = FALSE; - - RtlEnterCriticalSection( &vectored_handlers_section ); - LIST_FOR_EACH( ptr, &vectored_handlers ) - { - VECTORED_HANDLER *curr_handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry ); - if (curr_handler == handler) - { - if (!--curr_handler->count) list_remove( ptr ); - else handler = NULL; /* don't free it yet */ - ret = TRUE; - break; - } - } - RtlLeaveCriticalSection( &vectored_handlers_section ); - if (ret) RtlFreeHeap( GetProcessHeap(), 0, handler ); - return ret; + return remove_vectored_handler( &vectored_exception_handlers, handler ); } diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 451e497..5cbab71 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -1803,13 +1803,10 @@ static void test_vectored_continue_handler(void) } handler1 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef); - todo_wine ok(handler1 != 0, "RtlAddVectoredContinueHandler failed\n"); handler2 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef); - todo_wine ok(handler2 != 0, "RtlAddVectoredContinueHandler failed\n"); - todo_wine ok(handler1 != handler2, "RtlAddVectoredContinueHandler returned same handler\n"); if (pRtlRemoveVectoredExceptionHandler) @@ -1819,11 +1816,9 @@ static void test_vectored_continue_handler(void) } ret = pRtlRemoveVectoredContinueHandler(handler1); - todo_wine ok(ret, "RtlRemoveVectoredContinueHandler failed\n"); ret = pRtlRemoveVectoredContinueHandler(handler2); - todo_wine ok(ret, "RtlRemoveVectoredContinueHandler failed\n"); ret = pRtlRemoveVectoredContinueHandler(handler1); -- 2.1.3