ntdll: Move __C_specific_handler implementation to unwind.c.

This commit is contained in:
Alexandre Julliard 2024-03-13 10:44:21 +01:00
parent 83949ee269
commit 7b5267cf63
5 changed files with 245 additions and 340 deletions

View file

@ -38,19 +38,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
static void dump_scope_table( ULONG base, const SCOPE_TABLE *table )
{
unsigned int i;
TRACE( "scope table at %p\n", table );
for (i = 0; i < table->Count; i++)
TRACE( " %u: %lx-%lx handler %lx target %lx\n", i,
base + table->ScopeRecord[i].BeginAddress,
base + table->ScopeRecord[i].EndAddress,
base + table->ScopeRecord[i].HandlerAddress,
base + table->ScopeRecord[i].JumpTarget );
}
/* undocumented, copied from the corresponding ARM64 structure */
typedef union _DISPATCHER_CONTEXT_NONVOLREG_ARM
{
@ -603,9 +590,9 @@ ULONG WINAPI RtlWalkFrameChain( void **buffer, ULONG count, ULONG flags )
}
extern LONG __C_ExecuteExceptionFilter(PEXCEPTION_POINTERS ptrs, PVOID frame,
PEXCEPTION_FILTER filter,
PUCHAR nonvolatile);
/*******************************************************************
* __C_ExecuteExceptionFilter
*/
__ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter,
"push {r4-r11,lr}\n\t"
".seh_save_regs_w {r4-r11,lr}\n\t"
@ -614,94 +601,6 @@ __ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter,
"blx r2\n\t"
"pop {r4-r11,pc}\n\t" )
extern void __C_ExecuteTerminationHandler(BOOL abnormal, PVOID frame,
PTERMINATION_HANDLER handler,
PUCHAR nonvolatile);
/* This is, implementation wise, identical to __C_ExecuteExceptionFilter. */
__ASM_GLOBAL_FUNC( __C_ExecuteTerminationHandler,
"b " __ASM_NAME("__C_ExecuteExceptionFilter") "\n\t");
/*******************************************************************
* __C_specific_handler (NTDLL.@)
*/
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec,
void *frame,
CONTEXT *context,
struct _DISPATCHER_CONTEXT *dispatch )
{
SCOPE_TABLE *table = dispatch->HandlerData;
ULONG i;
DWORD ControlPc = dispatch->ControlPc;
TRACE( "%p %p %p %p\n", rec, frame, context, dispatch );
if (TRACE_ON(seh)) dump_scope_table( dispatch->ImageBase, table );
if (dispatch->ControlPcIsUnwound)
ControlPc -= 2;
if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
PTERMINATION_HANDLER handler;
if (table->ScopeRecord[i].JumpTarget) continue;
if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND &&
dispatch->TargetPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
dispatch->TargetPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
break;
}
handler = (PTERMINATION_HANDLER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
dispatch->ScopeIndex = i+1;
TRACE( "calling __finally %p frame %p\n", handler, frame );
__C_ExecuteTerminationHandler( TRUE, frame, handler,
dispatch->NonVolatileRegisters );
}
}
return ExceptionContinueSearch;
}
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
if (!table->ScopeRecord[i].JumpTarget) continue;
if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER)
{
EXCEPTION_POINTERS ptrs;
PEXCEPTION_FILTER filter;
filter = (PEXCEPTION_FILTER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
ptrs.ExceptionRecord = rec;
ptrs.ContextRecord = context;
TRACE( "calling filter %p ptrs %p frame %p\n", filter, &ptrs, frame );
switch (__C_ExecuteExceptionFilter( &ptrs, frame, filter,
dispatch->NonVolatileRegisters ))
{
case EXCEPTION_EXECUTE_HANDLER:
break;
case EXCEPTION_CONTINUE_SEARCH:
continue;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
}
}
TRACE( "unwinding to target %lx\n", dispatch->ImageBase + table->ScopeRecord[i].JumpTarget );
RtlUnwindEx( frame, (char *)dispatch->ImageBase + table->ScopeRecord[i].JumpTarget,
rec, 0, dispatch->ContextRecord, dispatch->HistoryTable );
}
}
return ExceptionContinueSearch;
}
/***********************************************************************
* RtlRaiseException (NTDLL.@)

View file

@ -40,19 +40,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
WINE_DECLARE_DEBUG_CHANNEL(relay);
static void dump_scope_table( ULONG64 base, const SCOPE_TABLE *table )
{
unsigned int i;
TRACE( "scope table at %p\n", table );
for (i = 0; i < table->Count; i++)
TRACE( " %u: %I64x-%I64x handler %I64x target %I64x\n", i,
base + table->ScopeRecord[i].BeginAddress,
base + table->ScopeRecord[i].EndAddress,
base + table->ScopeRecord[i].HandlerAddress,
base + table->ScopeRecord[i].JumpTarget );
}
/*******************************************************************
* syscalls
*/
@ -635,49 +622,30 @@ ULONG WINAPI RtlWalkFrameChain( void **buffer, ULONG count, ULONG flags )
}
extern LONG __C_ExecuteExceptionFilter(PEXCEPTION_POINTERS ptrs, PVOID frame,
PEXCEPTION_FILTER filter,
PUCHAR nonvolatile);
/***********************************************************************
* __C_ExecuteExceptionFilter
*/
__ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter,
"stp x29, x30, [sp, #-96]!\n\t"
__ASM_SEH(".seh_save_fplr_x 96\n\t")
".seh_save_fplr_x 96\n\t"
"stp x19, x20, [sp, #16]\n\t"
__ASM_SEH(".seh_save_regp x19, 16\n\t")
".seh_save_regp x19, 16\n\t"
"stp x21, x22, [sp, #32]\n\t"
__ASM_SEH(".seh_save_regp x21, 32\n\t")
".seh_save_regp x21, 32\n\t"
"stp x23, x24, [sp, #48]\n\t"
__ASM_SEH(".seh_save_regp x23, 48\n\t")
".seh_save_regp x23, 48\n\t"
"stp x25, x26, [sp, #64]\n\t"
__ASM_SEH(".seh_save_regp x25, 64\n\t")
".seh_save_regp x25, 64\n\t"
"stp x27, x28, [sp, #80]\n\t"
__ASM_SEH(".seh_save_regp x27, 80\n\t")
"mov x29, sp\n\t"
__ASM_SEH(".seh_set_fp\n\t")
__ASM_SEH(".seh_endprologue\n\t")
__ASM_CFI(".cfi_def_cfa x29, 96\n\t")
__ASM_CFI(".cfi_offset x29, -96\n\t")
__ASM_CFI(".cfi_offset x30, -88\n\t")
__ASM_CFI(".cfi_offset x19, -80\n\t")
__ASM_CFI(".cfi_offset x20, -72\n\t")
__ASM_CFI(".cfi_offset x21, -64\n\t")
__ASM_CFI(".cfi_offset x22, -56\n\t")
__ASM_CFI(".cfi_offset x23, -48\n\t")
__ASM_CFI(".cfi_offset x24, -40\n\t")
__ASM_CFI(".cfi_offset x25, -32\n\t")
__ASM_CFI(".cfi_offset x26, -24\n\t")
__ASM_CFI(".cfi_offset x27, -16\n\t")
__ASM_CFI(".cfi_offset x28, -8\n\t")
"ldp x19, x20, [x3, #0]\n\t"
".seh_save_regp x27, 80\n\t"
".seh_endprologue\n\t"
"ldp x19, x20, [x3, #0]\n\t" /* nonvolatile regs */
"ldp x21, x22, [x3, #16]\n\t"
"ldp x23, x24, [x3, #32]\n\t"
"ldp x25, x26, [x3, #48]\n\t"
"ldp x27, x28, [x3, #64]\n\t"
/* Overwrite the frame parameter with Fp from the
* nonvolatile regs */
"ldr x1, [x3, #80]\n\t"
"blr x2\n\t"
"ldr x1, [x3, #80]\n\t" /* x29 = frame */
"blr x2\n\t" /* filter */
"ldp x19, x20, [sp, #16]\n\t"
"ldp x21, x22, [sp, #32]\n\t"
"ldp x23, x24, [sp, #48]\n\t"
@ -686,94 +654,6 @@ __ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter,
"ldp x29, x30, [sp], #96\n\t"
"ret")
extern void __C_ExecuteTerminationHandler(BOOL abnormal, PVOID frame,
PTERMINATION_HANDLER handler,
PUCHAR nonvolatile);
/* This is, implementation wise, identical to __C_ExecuteExceptionFilter. */
__ASM_GLOBAL_FUNC( __C_ExecuteTerminationHandler,
"b " __ASM_NAME("__C_ExecuteExceptionFilter") "\n\t");
/*******************************************************************
* __C_specific_handler (NTDLL.@)
*/
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec,
void *frame,
CONTEXT *context,
struct _DISPATCHER_CONTEXT *dispatch )
{
SCOPE_TABLE *table = dispatch->HandlerData;
ULONG i;
DWORD64 ControlPc = dispatch->ControlPc;
TRACE( "%p %p %p %p\n", rec, frame, context, dispatch );
if (TRACE_ON(seh)) dump_scope_table( dispatch->ImageBase, table );
if (dispatch->ControlPcIsUnwound)
ControlPc -= 4;
if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
PTERMINATION_HANDLER handler;
if (table->ScopeRecord[i].JumpTarget) continue;
if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND &&
dispatch->TargetPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
dispatch->TargetPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
break;
}
handler = (PTERMINATION_HANDLER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
dispatch->ScopeIndex = i+1;
TRACE( "calling __finally %p frame %p\n", handler, frame );
__C_ExecuteTerminationHandler( TRUE, frame, handler,
dispatch->NonVolatileRegisters );
}
}
return ExceptionContinueSearch;
}
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
if (!table->ScopeRecord[i].JumpTarget) continue;
if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER)
{
EXCEPTION_POINTERS ptrs;
PEXCEPTION_FILTER filter;
filter = (PEXCEPTION_FILTER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
ptrs.ExceptionRecord = rec;
ptrs.ContextRecord = context;
TRACE( "calling filter %p ptrs %p frame %p\n", filter, &ptrs, frame );
switch (__C_ExecuteExceptionFilter( &ptrs, frame, filter,
dispatch->NonVolatileRegisters ))
{
case EXCEPTION_EXECUTE_HANDLER:
break;
case EXCEPTION_CONTINUE_SEARCH:
continue;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
}
}
TRACE( "unwinding to target %I64x\n", dispatch->ImageBase + table->ScopeRecord[i].JumpTarget );
RtlUnwindEx( frame, (char *)dispatch->ImageBase + table->ScopeRecord[i].JumpTarget,
rec, 0, dispatch->ContextRecord, dispatch->HistoryTable );
}
}
return ExceptionContinueSearch;
}
/***********************************************************************
* RtlRaiseException (NTDLL.@)

View file

@ -2215,19 +2215,6 @@ ULONG WINAPI RtlWalkFrameChain( void **buffer, ULONG count, ULONG flags )
}
/*******************************************************************
* __C_specific_handler (NTDLL.@)
*/
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec,
void *frame,
CONTEXT *context,
struct _DISPATCHER_CONTEXT *dispatch )
{
FIXME( "not implemented\n" );
return ExceptionContinueSearch;
}
static int code_match( BYTE *code, const BYTE *seq, size_t len )
{
for ( ; len; len--, code++, seq++) if (*seq && *code != *seq) return 0;

View file

@ -46,20 +46,6 @@ ALL_SYSCALLS64
#undef SYSCALL_ENTRY
static void dump_scope_table( ULONG64 base, const SCOPE_TABLE *table )
{
unsigned int i;
TRACE( "scope table at %p\n", table );
for (i = 0; i < table->Count; i++)
TRACE( " %u: %p-%p handler %p target %p\n", i,
(char *)base + table->ScopeRecord[i].BeginAddress,
(char *)base + table->ScopeRecord[i].EndAddress,
(char *)base + table->ScopeRecord[i].HandlerAddress,
(char *)base + table->ScopeRecord[i].JumpTarget );
}
/***********************************************************************
* virtual_unwind
*/
@ -852,82 +838,6 @@ void WINAPI RtlUnwindEx( PVOID end_frame, PVOID target_ip, EXCEPTION_RECORD *rec
}
/*******************************************************************
* __C_specific_handler (NTDLL.@)
*/
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec,
void *frame,
CONTEXT *context,
struct _DISPATCHER_CONTEXT *dispatch )
{
SCOPE_TABLE *table = dispatch->HandlerData;
ULONG i;
TRACE( "%p %p %p %p\n", rec, frame, context, dispatch );
if (TRACE_ON(seh)) dump_scope_table( dispatch->ImageBase, table );
if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (dispatch->ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
dispatch->ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
PTERMINATION_HANDLER handler;
if (table->ScopeRecord[i].JumpTarget) continue;
if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND &&
dispatch->TargetIp >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
dispatch->TargetIp < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
break;
}
handler = (PTERMINATION_HANDLER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
dispatch->ScopeIndex = i+1;
TRACE( "calling __finally %p frame %p\n", handler, frame );
handler( TRUE, frame );
}
}
return ExceptionContinueSearch;
}
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (dispatch->ControlPc >= dispatch->ImageBase + table->ScopeRecord[i].BeginAddress &&
dispatch->ControlPc < dispatch->ImageBase + table->ScopeRecord[i].EndAddress)
{
if (!table->ScopeRecord[i].JumpTarget) continue;
if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER)
{
EXCEPTION_POINTERS ptrs;
PEXCEPTION_FILTER filter;
filter = (PEXCEPTION_FILTER)(dispatch->ImageBase + table->ScopeRecord[i].HandlerAddress);
ptrs.ExceptionRecord = rec;
ptrs.ContextRecord = context;
TRACE( "calling filter %p ptrs %p frame %p\n", filter, &ptrs, frame );
switch (filter( &ptrs, frame ))
{
case EXCEPTION_EXECUTE_HANDLER:
break;
case EXCEPTION_CONTINUE_SEARCH:
continue;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
}
}
TRACE( "unwinding to target %p\n", (char *)dispatch->ImageBase + table->ScopeRecord[i].JumpTarget );
RtlUnwindEx( frame, (char *)dispatch->ImageBase + table->ScopeRecord[i].JumpTarget,
rec, 0, dispatch->ContextRecord, dispatch->HistoryTable );
}
}
return ExceptionContinueSearch;
}
/***********************************************************************
* RtlRaiseException (NTDLL.@)
*/

View file

@ -37,6 +37,22 @@
WINE_DEFAULT_DEBUG_CHANNEL(unwind);
/***********************************************************************
* C specific handler
*/
extern LONG __C_ExecuteExceptionFilter( EXCEPTION_POINTERS *ptrs, void *frame,
PEXCEPTION_FILTER filter, BYTE *nonvolatile );
#define DUMP_SCOPE_TABLE(base,table) do { \
for (unsigned int i = 0; i < table->Count; i++) \
TRACE( " %u: %p-%p handler %p target %p\n", i, \
(char *)base + table->ScopeRecord[i].BeginAddress, \
(char *)base + table->ScopeRecord[i].EndAddress, \
(char *)base + table->ScopeRecord[i].HandlerAddress, \
(char *)base + table->ScopeRecord[i].JumpTarget ); \
} while(0)
/***********************************************************************
* Dynamic unwind tables
*/
@ -768,6 +784,7 @@ static ARM64_RUNTIME_FUNCTION *find_function_info_arm64( ULONG_PTR pc, ULONG_PTR
#define RtlVirtualUnwind RtlVirtualUnwind_arm64
#define RtlVirtualUnwind2 RtlVirtualUnwind2_arm64
#define RtlLookupFunctionEntry RtlLookupFunctionEntry_arm64
#define __C_specific_handler __C_specific_handler_arm64
#endif
/**********************************************************************
@ -822,6 +839,77 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PT
}
/*******************************************************************
* __C_specific_handler (NTDLL.@)
*/
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void *frame,
ARM64_NT_CONTEXT *context,
DISPATCHER_CONTEXT_ARM64 *dispatch )
{
const SCOPE_TABLE *table = dispatch->HandlerData;
ULONG_PTR base = dispatch->ImageBase;
ULONG_PTR pc = dispatch->ControlPc;
unsigned int i;
void *handler;
TRACE( "%p %p %p %p pc %Ix\n", rec, frame, context, dispatch, pc );
if (TRACE_ON(unwind)) DUMP_SCOPE_TABLE( base, table );
if (dispatch->ControlPcIsUnwound) pc -= 4;
if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (pc < base + table->ScopeRecord[i].BeginAddress) continue;
if (pc >= base + table->ScopeRecord[i].EndAddress) continue;
if (table->ScopeRecord[i].JumpTarget) continue;
if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND &&
dispatch->TargetPc >= base + table->ScopeRecord[i].BeginAddress &&
dispatch->TargetPc < base + table->ScopeRecord[i].EndAddress)
{
break;
}
handler = (void *)(base + table->ScopeRecord[i].HandlerAddress);
dispatch->ScopeIndex = i + 1;
TRACE( "scope %u calling __finally %p frame %p\n", i, handler, frame );
__C_ExecuteExceptionFilter( ULongToPtr(TRUE), frame, handler, dispatch->NonVolatileRegisters );
}
}
else
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (pc < base + table->ScopeRecord[i].BeginAddress) continue;
if (pc >= base + table->ScopeRecord[i].EndAddress) continue;
if (!table->ScopeRecord[i].JumpTarget) continue;
if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER)
{
EXCEPTION_POINTERS ptrs = { rec, context };
handler = (void *)(base + table->ScopeRecord[i].HandlerAddress);
TRACE( "scope %u calling filter %p ptrs %p frame %p\n", i, handler, &ptrs, frame );
switch (__C_ExecuteExceptionFilter( &ptrs, frame, handler, dispatch->NonVolatileRegisters ))
{
case EXCEPTION_EXECUTE_HANDLER:
break;
case EXCEPTION_CONTINUE_SEARCH:
continue;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
}
}
TRACE( "unwinding to target %Ix\n", base + table->ScopeRecord[i].JumpTarget );
RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget,
rec, 0, dispatch->ContextRecord, dispatch->HistoryTable );
}
}
return ExceptionContinueSearch;
}
/**********************************************************************
* RtlLookupFunctionEntry (NTDLL.@)
*/
@ -869,6 +957,7 @@ BOOLEAN CDECL RtlAddFunctionTable( RUNTIME_FUNCTION *table, DWORD count, ULONG_P
#undef RtlVirtualUnwind
#undef RtlVirtualUnwind2
#undef RtlLookupFunctionEntry
#undef __C_specific_handler
#endif
#endif /* __aarch64__ */
@ -1442,6 +1531,76 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PT
}
/*******************************************************************
* __C_specific_handler (NTDLL.@)
*/
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void *frame,
CONTEXT *context, DISPATCHER_CONTEXT *dispatch )
{
const SCOPE_TABLE *table = dispatch->HandlerData;
ULONG_PTR base = dispatch->ImageBase;
ULONG_PTR pc = dispatch->ControlPc;
unsigned int i;
void *handler;
TRACE( "%p %p %p %p pc %Ix\n", rec, frame, context, dispatch, pc );
if (TRACE_ON(unwind)) DUMP_SCOPE_TABLE( base, table );
if (dispatch->ControlPcIsUnwound) pc -= 2;
if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (pc < base + table->ScopeRecord[i].BeginAddress) continue;
if (pc >= base + table->ScopeRecord[i].EndAddress) continue;
if (table->ScopeRecord[i].JumpTarget) continue;
if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND &&
dispatch->TargetPc >= base + table->ScopeRecord[i].BeginAddress &&
dispatch->TargetPc < base + table->ScopeRecord[i].EndAddress)
{
break;
}
handler = (void *)(base + table->ScopeRecord[i].HandlerAddress);
dispatch->ScopeIndex = i + 1;
TRACE( "scope %u calling __finally %p frame %p\n", i, handler, frame );
__C_ExecuteExceptionFilter( ULongToPtr(TRUE), frame, handler, dispatch->NonVolatileRegisters );
}
}
else
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (pc < base + table->ScopeRecord[i].BeginAddress) continue;
if (pc >= base + table->ScopeRecord[i].EndAddress) continue;
if (!table->ScopeRecord[i].JumpTarget) continue;
if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER)
{
EXCEPTION_POINTERS ptrs = { rec, context };
handler = (void *)(base + table->ScopeRecord[i].HandlerAddress);
TRACE( "scope %u calling filter %p ptrs %p frame %p\n", i, handler, &ptrs, frame );
switch (__C_ExecuteExceptionFilter( &ptrs, frame, handler, dispatch->NonVolatileRegisters ))
{
case EXCEPTION_EXECUTE_HANDLER:
break;
case EXCEPTION_CONTINUE_SEARCH:
continue;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
}
}
TRACE( "unwinding to target %lx\n", base + table->ScopeRecord[i].JumpTarget );
RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget,
rec, 0, dispatch->ContextRecord, dispatch->HistoryTable );
}
}
return ExceptionContinueSearch;
}
/**********************************************************************
* RtlLookupFunctionEntry (NTDLL.@)
*/
@ -2034,6 +2193,76 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
}
/*******************************************************************
* __C_specific_handler (NTDLL.@)
*/
EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void *frame,
CONTEXT *context, DISPATCHER_CONTEXT *dispatch )
{
const SCOPE_TABLE *table = dispatch->HandlerData;
ULONG_PTR base = dispatch->ImageBase;
ULONG_PTR pc = dispatch->ControlPc;
unsigned int i;
TRACE( "%p %p %p %p pc %Ix\n", rec, frame, context, dispatch, pc );
if (TRACE_ON(unwind)) DUMP_SCOPE_TABLE( base, table );
if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND))
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (pc < base + table->ScopeRecord[i].BeginAddress) continue;
if (pc >= base + table->ScopeRecord[i].EndAddress) continue;
if (table->ScopeRecord[i].JumpTarget) continue;
if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND &&
dispatch->TargetIp >= base + table->ScopeRecord[i].BeginAddress &&
dispatch->TargetIp < base + table->ScopeRecord[i].EndAddress)
{
break;
}
else
{
PTERMINATION_HANDLER handler = (void *)(base + table->ScopeRecord[i].HandlerAddress);
dispatch->ScopeIndex = i + 1;
TRACE( "scope %u calling __finally %p frame %p\n", i, handler, frame );
handler( TRUE, frame );
}
}
}
else
{
for (i = dispatch->ScopeIndex; i < table->Count; i++)
{
if (pc < base + table->ScopeRecord[i].BeginAddress) continue;
if (pc >= base + table->ScopeRecord[i].EndAddress) continue;
if (!table->ScopeRecord[i].JumpTarget) continue;
if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER)
{
EXCEPTION_POINTERS ptrs = { rec, context };
PEXCEPTION_FILTER filter = (void *)(base + table->ScopeRecord[i].HandlerAddress);
TRACE( "scope %u calling filter %p ptrs %p frame %p\n", i, filter, &ptrs, frame );
switch (filter( &ptrs, frame ))
{
case EXCEPTION_EXECUTE_HANDLER:
break;
case EXCEPTION_CONTINUE_SEARCH:
continue;
case EXCEPTION_CONTINUE_EXECUTION:
return ExceptionContinueExecution;
}
}
TRACE( "unwinding to target %Ix\n", base + table->ScopeRecord[i].JumpTarget );
RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget,
rec, 0, dispatch->ContextRecord, dispatch->HistoryTable );
}
}
return ExceptionContinueSearch;
}
/**********************************************************************
* RtlLookupFunctionEntry (NTDLL.@)
*/