ntdll: Implement Rtl[Add|Remove]VectoredContinueHandler semi-stubs.

This commit is contained in:
Sebastian Lackner 2014-11-14 00:12:07 +01:00 committed by Alexandre Julliard
parent 009b6a25bb
commit 275ee4b376
2 changed files with 49 additions and 41 deletions

View File

@ -47,7 +47,8 @@ typedef struct
ULONG count; ULONG count;
} VECTORED_HANDLER; } 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 vectored_handlers_section;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug = 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 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 * wait_suspend
* *
@ -165,7 +207,7 @@ LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
except_ptrs.ContextRecord = context; except_ptrs.ContextRecord = context;
RtlEnterCriticalSection( &vectored_handlers_section ); RtlEnterCriticalSection( &vectored_handlers_section );
ptr = list_head( &vectored_handlers ); ptr = list_head( &vectored_exception_handlers );
while (ptr) while (ptr)
{ {
handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry ); 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 ); TRACE( "handler at %p returned %x\n", func, ret );
RtlEnterCriticalSection( &vectored_handlers_section ); RtlEnterCriticalSection( &vectored_handlers_section );
ptr = list_next( &vectored_handlers, ptr ); ptr = list_next( &vectored_exception_handlers, ptr );
if (!--handler->count) /* removed during execution */ if (!--handler->count) /* removed during execution */
{ {
list_remove( &handler->entry ); list_remove( &handler->entry );
@ -228,8 +270,7 @@ void WINAPI RtlRaiseStatus( NTSTATUS status )
*/ */
PVOID WINAPI RtlAddVectoredContinueHandler( ULONG first, PVECTORED_EXCEPTION_HANDLER func ) PVOID WINAPI RtlAddVectoredContinueHandler( ULONG first, PVECTORED_EXCEPTION_HANDLER func )
{ {
FIXME("%u %p stub\n", first, func); return add_vectored_handler( &vectored_continue_handlers, first, func );
return NULL;
} }
@ -238,8 +279,7 @@ PVOID WINAPI RtlAddVectoredContinueHandler( ULONG first, PVECTORED_EXCEPTION_HAN
*/ */
ULONG WINAPI RtlRemoveVectoredContinueHandler( PVOID handler ) ULONG WINAPI RtlRemoveVectoredContinueHandler( PVOID handler )
{ {
FIXME("%p stub\n", handler); return remove_vectored_handler( &vectored_continue_handlers, handler );
return FALSE;
} }
@ -248,17 +288,7 @@ ULONG WINAPI RtlRemoveVectoredContinueHandler( PVOID handler )
*/ */
PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HANDLER func ) PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HANDLER func )
{ {
VECTORED_HANDLER *handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) ); return add_vectored_handler( &vectored_exception_handlers, first, func );
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;
} }
@ -267,24 +297,7 @@ PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HA
*/ */
ULONG WINAPI RtlRemoveVectoredExceptionHandler( PVOID handler ) ULONG WINAPI RtlRemoveVectoredExceptionHandler( PVOID handler )
{ {
struct list *ptr; return remove_vectored_handler( &vectored_exception_handlers, handler );
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;
} }

View File

@ -1803,13 +1803,10 @@ static void test_vectored_continue_handler(void)
} }
handler1 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef); handler1 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef);
todo_wine
ok(handler1 != 0, "RtlAddVectoredContinueHandler failed\n"); ok(handler1 != 0, "RtlAddVectoredContinueHandler failed\n");
handler2 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef); handler2 = pRtlAddVectoredContinueHandler(TRUE, (void *)0xdeadbeef);
todo_wine
ok(handler2 != 0, "RtlAddVectoredContinueHandler failed\n"); ok(handler2 != 0, "RtlAddVectoredContinueHandler failed\n");
todo_wine
ok(handler1 != handler2, "RtlAddVectoredContinueHandler returned same handler\n"); ok(handler1 != handler2, "RtlAddVectoredContinueHandler returned same handler\n");
if (pRtlRemoveVectoredExceptionHandler) if (pRtlRemoveVectoredExceptionHandler)
@ -1819,11 +1816,9 @@ static void test_vectored_continue_handler(void)
} }
ret = pRtlRemoveVectoredContinueHandler(handler1); ret = pRtlRemoveVectoredContinueHandler(handler1);
todo_wine
ok(ret, "RtlRemoveVectoredContinueHandler failed\n"); ok(ret, "RtlRemoveVectoredContinueHandler failed\n");
ret = pRtlRemoveVectoredContinueHandler(handler2); ret = pRtlRemoveVectoredContinueHandler(handler2);
todo_wine
ok(ret, "RtlRemoveVectoredContinueHandler failed\n"); ok(ret, "RtlRemoveVectoredContinueHandler failed\n");
ret = pRtlRemoveVectoredContinueHandler(handler1); ret = pRtlRemoveVectoredContinueHandler(handler1);