[PATCH 0/1] MR9906: ntdll: Make VEH registration structure compatible.
From: Paul Gofman <pgofman@codeweavers.com> --- dlls/ntdll/exception.c | 51 ++++++++++++++++-------------- dlls/ntdll/tests/exception.c | 60 ++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 23 deletions(-) diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index 691781017a2..14381e0923c 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -40,13 +40,14 @@ WINE_DECLARE_DEBUG_CHANNEL(threadname); typedef struct { - struct list entry; - PVECTORED_EXCEPTION_HANDLER func; - ULONG count; + LIST_ENTRY entry; + ULONG_PTR *count; + void *unknown; + PVECTORED_EXCEPTION_HANDLER *func; } VECTORED_HANDLER; -static struct list vectored_exception_handlers = LIST_INIT(vectored_exception_handlers); -static struct list vectored_continue_handlers = LIST_INIT(vectored_continue_handlers); +static LIST_ENTRY vectored_exception_handlers = { &vectored_exception_handlers, &vectored_exception_handlers }; +static LIST_ENTRY vectored_continue_handlers = { &vectored_continue_handlers, &vectored_continue_handlers }; static RTL_CRITICAL_SECTION vectored_handlers_section; static RTL_CRITICAL_SECTION_DEBUG critsect_debug = @@ -99,35 +100,37 @@ static const char *debugstr_exception_code( DWORD code ) } -static VECTORED_HANDLER *add_vectored_handler( struct list *handler_list, ULONG first, +static VECTORED_HANDLER *add_vectored_handler( LIST_ENTRY *handler_list, ULONG first, PVECTORED_EXCEPTION_HANDLER func ) { - VECTORED_HANDLER *handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) ); + VECTORED_HANDLER *handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) + sizeof(*handler->count) ); if (handler) { handler->func = RtlEncodePointer( func ); - handler->count = 1; + handler->count = (ULONG_PTR *)(handler + 1); + *handler->count = 1; RtlEnterCriticalSection( &vectored_handlers_section ); - if (first) list_add_head( handler_list, &handler->entry ); - else list_add_tail( handler_list, &handler->entry ); + if (first) InsertHeadList( handler_list, &handler->entry ); + else InsertTailList( handler_list, &handler->entry ); RtlLeaveCriticalSection( &vectored_handlers_section ); } return handler; } -static ULONG remove_vectored_handler( struct list *handler_list, VECTORED_HANDLER *handler ) +static ULONG remove_vectored_handler( LIST_ENTRY *handler_list, VECTORED_HANDLER *handler ) { - struct list *ptr; + PLIST_ENTRY mark, entry; ULONG ret = FALSE; RtlEnterCriticalSection( &vectored_handlers_section ); - LIST_FOR_EACH( ptr, handler_list ) + mark = handler_list; + for (entry = mark->Flink; entry != mark; entry = entry->Flink) { - VECTORED_HANDLER *curr_handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry ); + VECTORED_HANDLER *curr_handler = CONTAINING_RECORD( entry, VECTORED_HANDLER, entry ); if (curr_handler == handler) { - if (!--curr_handler->count) list_remove( ptr ); + if (!--*curr_handler->count) RemoveEntryList( entry ); else handler = NULL; /* don't free it yet */ ret = TRUE; break; @@ -146,21 +149,24 @@ static ULONG remove_vectored_handler( struct list *handler_list, VECTORED_HANDLE */ static LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) { - struct list *ptr; LONG ret = EXCEPTION_CONTINUE_SEARCH; EXCEPTION_POINTERS except_ptrs; PVECTORED_EXCEPTION_HANDLER func; VECTORED_HANDLER *handler, *to_free = NULL; + PLIST_ENTRY mark, entry; except_ptrs.ExceptionRecord = rec; except_ptrs.ContextRecord = context; RtlEnterCriticalSection( &vectored_handlers_section ); - ptr = list_head( &vectored_exception_handlers ); - while (ptr) + + mark = &vectored_exception_handlers; + entry = mark->Flink; + while (entry != mark) { - handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry ); - handler->count++; + handler = CONTAINING_RECORD( entry, VECTORED_HANDLER, entry ); + entry = entry->Flink; + ++*handler->count; func = RtlDecodePointer( handler->func ); RtlLeaveCriticalSection( &vectored_handlers_section ); RtlFreeHeap( GetProcessHeap(), 0, to_free ); @@ -172,10 +178,9 @@ static LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) TRACE( "handler at %p returned %lx\n", func, ret ); RtlEnterCriticalSection( &vectored_handlers_section ); - ptr = list_next( &vectored_exception_handlers, ptr ); - if (!--handler->count) /* removed during execution */ + if (!--*handler->count) /* removed during execution */ { - list_remove( &handler->entry ); + RemoveEntryList( &handler->entry ); to_free = handler; } if (ret == EXCEPTION_CONTINUE_EXECUTION) break; diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 1de3617ef89..30b60398f4b 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -12353,6 +12353,65 @@ static void test_context_exception_request(void) CloseHandle( p.event ); } +typedef struct +{ + LIST_ENTRY entry; + ULONG_PTR *count; + void *unk1; + PVECTORED_EXCEPTION_HANDLER func; +} +VECTORED_HANDLER; + +static VECTORED_HANDLER *test_RtlAddVectoredExceptionHandler_vh2; + +static LONG CALLBACK test_RtlAddVectoredExceptionHandler_handler2( EXCEPTION_POINTERS *info ) +{ + EXCEPTION_RECORD *rec = info->ExceptionRecord; + + ok( rec->ExceptionCode == 0xeadbeef, "got %#lx, address %p.\n", rec->ExceptionCode, rec->ExceptionAddress ); + ok( *test_RtlAddVectoredExceptionHandler_vh2->count == 2, "got %Iu.\n", *test_RtlAddVectoredExceptionHandler_vh2->count ); + return EXCEPTION_CONTINUE_EXECUTION; +} + +static LONG CALLBACK test_RtlAddVectoredExceptionHandler_handler( EXCEPTION_POINTERS *info ) +{ + ok( 0, "got here.\n" ); + return EXCEPTION_CONTINUE_SEARCH; +} + +static void test_RtlAddVectoredExceptionHandler(void) +{ + VECTORED_HANDLER *vh, *vh2; + void *func; + + vh = pRtlAddVectoredExceptionHandler( TRUE, test_RtlAddVectoredExceptionHandler_handler ); + ok( !!vh, "got NULL.\n" ); + if ((ULONG)(ULONG_PTR)vh->count == 1) + { + win_skip( "Old layout, skipping tests.\n" ); + pRtlRemoveVectoredExceptionHandler( vh ); + return; + } + ok( *vh->count == 1, "got %Iu.\n", *vh->count ); + func = DecodePointer( vh->func ); + ok( func == test_RtlAddVectoredExceptionHandler_handler, "got %p, %p.\n", func, test_RtlAddVectoredExceptionHandler_handler ); + + vh2 = pRtlAddVectoredExceptionHandler( TRUE, test_RtlAddVectoredExceptionHandler_handler2 ); + ok( !!vh2, "got NULL.\n" ); + ok( *vh2->count == 1, "got %Iu.\n", *vh->count ); + func = DecodePointer( vh2->func ); + ok( func == test_RtlAddVectoredExceptionHandler_handler2, "got %p, %p.\n", func, test_RtlAddVectoredExceptionHandler_handler2 ); + + ok( vh->entry.Blink == (void *)vh2, "got %p, %p.\n", vh->entry.Flink, vh2 ); + ok( vh2->entry.Flink == (void *)vh, "got %p, %p.\n", vh->entry.Blink, vh ); + + test_RtlAddVectoredExceptionHandler_vh2 = vh2; + RaiseException( 0xeadbeef, 0, 0, NULL ); + + pRtlRemoveVectoredExceptionHandler( vh ); + pRtlRemoveVectoredExceptionHandler( vh2 ); +} + START_TEST(exception) { HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); @@ -12656,5 +12715,6 @@ START_TEST(exception) test_unload_trace(); test_backtrace(); test_context_exception_request(); + test_RtlAddVectoredExceptionHandler(); VirtualFree(code_mem, 0, MEM_RELEASE); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9906
Rec Room traverses VEH handler list. That also depends on RtlDecodePointer / RtlEncodePointer being compatible with Windows and use process cookie, I have patches for that part I am planning to send next. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9906#note_127138
participants (2)
-
Paul Gofman -
Paul Gofman (@gofman)