1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

ntdll: Share exception dispatch implementation across platforms.

This commit is contained in:
Alexandre Julliard 2024-02-20 20:27:46 +01:00
parent 61564202b5
commit 8bd411da0a
6 changed files with 88 additions and 254 deletions

View file

@ -36,6 +36,7 @@
#include "ntdll_misc.h" #include "ntdll_misc.h"
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
typedef struct typedef struct
{ {
@ -58,7 +59,7 @@ static RTL_CRITICAL_SECTION vectored_handlers_section = { &critsect_debug, -1, 0
static PRTL_EXCEPTION_FILTER unhandled_exception_filter; static PRTL_EXCEPTION_FILTER unhandled_exception_filter;
const char *debugstr_exception_code( DWORD code ) static const char *debugstr_exception_code( DWORD code )
{ {
switch (code) switch (code)
{ {
@ -143,7 +144,7 @@ static ULONG remove_vectored_handler( struct list *handler_list, VECTORED_HANDLE
* *
* Call the vectored handlers chain. * Call the vectored handlers chain.
*/ */
LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) static LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
{ {
struct list *ptr; struct list *ptr;
LONG ret = EXCEPTION_CONTINUE_SEARCH; LONG ret = EXCEPTION_CONTINUE_SEARCH;
@ -185,6 +186,77 @@ LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
} }
/*******************************************************************
* dispatch_exception
*/
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD i;
switch (rec->ExceptionCode)
{
case EXCEPTION_WINE_STUB:
if (rec->ExceptionInformation[1] >> 16)
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
rec->ExceptionAddress,
(char *)rec->ExceptionInformation[0], (char *)rec->ExceptionInformation[1] );
else
MESSAGE( "wine: Call from %p to unimplemented function %s.%u, aborting\n",
rec->ExceptionAddress,
(char *)rec->ExceptionInformation[0], (USHORT)rec->ExceptionInformation[1] );
break;
case EXCEPTION_WINE_NAME_THREAD:
if (rec->ExceptionInformation[0] == 0x1000)
{
const char *name = (char *)rec->ExceptionInformation[1];
DWORD tid = (DWORD)rec->ExceptionInformation[2];
if (tid == -1 || tid == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a(name) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", tid, debugstr_a(name) );
set_native_thread_name( tid, name );
}
break;
case DBG_PRINTEXCEPTION_C:
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
break;
case DBG_PRINTEXCEPTION_WIDE_C:
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
break;
case STATUS_ASSERTION_FAILURE:
ERR( "assertion failure exception\n" );
break;
default:
if (!TRACE_ON(seh)) WARN( "%s exception (code=%lx) raised\n",
debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
break;
}
TRACE( "code=%lx (%s) flags=%lx addr=%p\n",
rec->ExceptionCode, debugstr_exception_code(rec->ExceptionCode),
rec->ExceptionFlags, rec->ExceptionAddress );
for (i = 0; i < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); i++)
TRACE( " info[%ld]=%p\n", i, (void *)rec->ExceptionInformation[i] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_seh_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
#if defined(__WINE_PE_BUILD) && !defined(__i386__) #if defined(__WINE_PE_BUILD) && !defined(__i386__)
/******************************************************************* /*******************************************************************

View file

@ -60,7 +60,8 @@ extern UINT_PTR page_size;
#endif #endif
/* exceptions */ /* exceptions */
extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ); extern NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *context );
extern NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context );
extern NTSTATUS WINAPI dispatch_user_callback( void *args, ULONG len, ULONG id ); extern NTSTATUS WINAPI dispatch_user_callback( void *args, ULONG len, ULONG id );
extern EXCEPTION_DISPOSITION WINAPI user_callback_handler( EXCEPTION_RECORD *record, void *frame, extern EXCEPTION_DISPOSITION WINAPI user_callback_handler( EXCEPTION_RECORD *record, void *frame,
CONTEXT *context, void *dispatch ); CONTEXT *context, void *dispatch );
@ -86,7 +87,6 @@ extern void (WINAPI *pWow64PrepareForException)( EXCEPTION_RECORD *rec, CONTEXT
/* debug helpers */ /* debug helpers */
extern LPCSTR debugstr_us( const UNICODE_STRING *str ); extern LPCSTR debugstr_us( const UNICODE_STRING *str );
extern const char *debugstr_exception_code( DWORD code );
extern void set_native_thread_name( DWORD tid, const char *name ); extern void set_native_thread_name( DWORD tid, const char *name );
/* init routines */ /* init routines */

View file

@ -35,7 +35,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */ /* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
@ -335,11 +334,11 @@ static DWORD call_teb_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCH
/********************************************************************** /**********************************************************************
* call_function_handlers * call_seh_handlers
* *
* Call the per-function handlers. * Call the SEH handlers.
*/ */
static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{ {
EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
UNWIND_HISTORY_TABLE table; UNWIND_HISTORY_TABLE table;
@ -441,64 +440,6 @@ static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_con
/******************************************************************* /*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@) * KiUserExceptionDispatcher (NTDLL.@)
*/ */
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD c;
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
{
if (rec->ExceptionInformation[1] >> 16)
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
else
MESSAGE( "wine: Call from %p to unimplemented function %s.%Id, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < rec->NumberParameters; c++)
TRACE( " info[%ld]=%08Ix\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_function_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
__ASM_GLOBAL_FUNC( KiUserExceptionDispatcher, __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher,
__ASM_SEH(".seh_custom 0xee,0x02\n\t") /* MSFT_OP_CONTEXT */ __ASM_SEH(".seh_custom 0xee,0x02\n\t") /* MSFT_OP_CONTEXT */
__ASM_SEH(".seh_endprologue\n\t") __ASM_SEH(".seh_endprologue\n\t")

View file

@ -37,7 +37,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */ /* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
@ -338,11 +337,11 @@ static DWORD call_teb_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCH
/********************************************************************** /**********************************************************************
* call_function_handlers * call_seh_handlers
* *
* Call the per-function handlers. * Call the SEH handlers.
*/ */
static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{ {
EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
UNWIND_HISTORY_TABLE table; UNWIND_HISTORY_TABLE table;
@ -441,65 +440,6 @@ static NTSTATUS call_function_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_con
} }
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD c;
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
{
if (rec->ExceptionInformation[1] >> 16)
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
else
MESSAGE( "wine: Call from %p to unimplemented function %s.%Id, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < rec->NumberParameters; c++)
TRACE( " info[%ld]=%016I64x\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_function_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
/******************************************************************* /*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@) * KiUserExceptionDispatcher (NTDLL.@)
*/ */

View file

@ -37,7 +37,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
struct x86_thread_data struct x86_thread_data
{ {
@ -139,11 +138,11 @@ static DWORD unwind_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECOR
/********************************************************************** /**********************************************************************
* call_stack_handlers * call_seh_handlers
* *
* Call the stack handlers chain. * Call the SEH handlers chain.
*/ */
static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
{ {
EXCEPTION_REGISTRATION_RECORD *frame, *dispatch, *nested_frame; EXCEPTION_REGISTRATION_RECORD *frame, *dispatch, *nested_frame;
DWORD res; DWORD res;
@ -195,64 +194,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
/******************************************************************* /*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@) * KiUserExceptionDispatcher (NTDLL.@)
*/ */
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD c;
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
{
if (rec->ExceptionInformation[1] >> 16)
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
else
MESSAGE( "wine: Call from %p to unimplemented function %s.%Id, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < rec->NumberParameters; c++)
TRACE( " info[%ld]=%08Ix\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
__ASM_STDCALL_FUNC( KiUserExceptionDispatcher, 8, __ASM_STDCALL_FUNC( KiUserExceptionDispatcher, 8,
"pushl 4(%esp)\n\t" "pushl 4(%esp)\n\t"
"pushl 4(%esp)\n\t" "pushl 4(%esp)\n\t"

View file

@ -35,7 +35,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(seh); WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(relay);
WINE_DECLARE_DEBUG_CHANNEL(threadname);
/* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */ /* layering violation: the setjmp buffer is defined in msvcrt, but used by RtlUnwindEx */
@ -258,11 +257,11 @@ static DWORD call_teb_handler( EXCEPTION_RECORD *rec, CONTEXT *context, DISPATCH
/********************************************************************** /**********************************************************************
* call_stack_handlers * call_seh_handlers
* *
* Call the stack handlers chain. * Call the SEH handlers chain.
*/ */
static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context )
{ {
EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList; EXCEPTION_REGISTRATION_RECORD *teb_frame = NtCurrentTeb()->Tib.ExceptionList;
UNWIND_HISTORY_TABLE table; UNWIND_HISTORY_TABLE table;
@ -359,65 +358,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
} }
NTSTATUS WINAPI dispatch_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
{
NTSTATUS status;
DWORD c;
if (rec->ExceptionCode == EXCEPTION_WINE_STUB)
{
if (rec->ExceptionInformation[1] >> 16)
MESSAGE( "wine: Call from %p to unimplemented function %s.%s, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], (char*)rec->ExceptionInformation[1] );
else
MESSAGE( "wine: Call from %p to unimplemented function %s.%I64d, aborting\n",
rec->ExceptionAddress,
(char*)rec->ExceptionInformation[0], rec->ExceptionInformation[1] );
}
else if (rec->ExceptionCode == EXCEPTION_WINE_NAME_THREAD && rec->ExceptionInformation[0] == 0x1000)
{
if ((DWORD)rec->ExceptionInformation[2] == -1 || (DWORD)rec->ExceptionInformation[2] == GetCurrentThreadId())
WARN_(threadname)( "Thread renamed to %s\n", debugstr_a((char *)rec->ExceptionInformation[1]) );
else
WARN_(threadname)( "Thread ID %04lx renamed to %s\n", (DWORD)rec->ExceptionInformation[2],
debugstr_a((char *)rec->ExceptionInformation[1]) );
set_native_thread_name((DWORD)rec->ExceptionInformation[2], (char *)rec->ExceptionInformation[1]);
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_C)
{
WARN( "%s\n", debugstr_an((char *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else if (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C)
{
WARN( "%s\n", debugstr_wn((WCHAR *)rec->ExceptionInformation[1], rec->ExceptionInformation[0] - 1) );
}
else
{
if (rec->ExceptionCode == STATUS_ASSERTION_FAILURE)
ERR( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
else
WARN( "%s exception (code=%lx) raised\n", debugstr_exception_code(rec->ExceptionCode), rec->ExceptionCode );
}
TRACE( "code=%lx flags=%lx addr=%p\n",
rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
for (c = 0; c < min( EXCEPTION_MAXIMUM_PARAMETERS, rec->NumberParameters ); c++)
TRACE( " info[%ld]=%016I64x\n", c, rec->ExceptionInformation[c] );
TRACE_CONTEXT( context );
if (call_vectored_handlers( rec, context ) == EXCEPTION_CONTINUE_EXECUTION)
NtContinue( context, FALSE );
if ((status = call_stack_handlers( rec, context )) == STATUS_SUCCESS)
NtContinue( context, FALSE );
if (status != STATUS_UNHANDLED_EXCEPTION) RtlRaiseStatus( status );
return NtRaiseException( rec, context, FALSE );
}
/******************************************************************* /*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@) * KiUserExceptionDispatcher (NTDLL.@)
*/ */