📄 cppexcept.c
字号:
handler, trylevel, last_level, &frame->ebp );
call_ebp_func( handler, &frame->ebp );
}
trylevel = descr->unwind_table[trylevel].prev;
}
frame->trylevel = last_level;
}
/* exception frame for nested exceptions in catch block */
struct catch_func_nested_frame
{
EXCEPTION_REGISTRATION_RECORD frame; /* standard exception frame */
EXCEPTION_RECORD *prev_rec; /* previous record to restore in thread data */
cxx_exception_frame *cxx_frame; /* frame of parent exception */
cxx_function_descr *descr; /* descriptor of parent exception */
int trylevel; /* current try level */
};
/* handler for exceptions happening while calling a catch function */
static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
{
struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame;
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
{
msvcrt_get_thread_data()->exc_record = nested_frame->prev_rec;
return ExceptionContinueSearch;
}
else
{
TRACE( "got nested exception in catch function\n" );
return cxx_frame_handler( rec, nested_frame->cxx_frame, context,
NULL, nested_frame->descr, &nested_frame->frame,
nested_frame->trylevel );
}
}
/* find and call the appropriate catch block for an exception */
/* returns the address to continue execution to after the catch block was called */
__inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame,
cxx_function_descr *descr, int nested_trylevel,
cxx_exception_type *info )
{
UINT i;
int j;
void *addr, *object = (void *)rec->ExceptionInformation[1];
struct catch_func_nested_frame nested_frame;
int trylevel = frame->trylevel;
MSVCRT_thread_data *thread_data = msvcrt_get_thread_data();
for (i = 0; i < descr->tryblock_count; i++)
{
tryblock_info *tryblock = &descr->tryblock[i];
if (trylevel < tryblock->start_level) continue;
if (trylevel > tryblock->end_level) continue;
/* got a try block */
for (j = 0; j < tryblock->catchblock_count; j++)
{
catchblock_info *catchblock = &tryblock->catchblock[j];
const cxx_type_info *type = find_caught_type( info, catchblock );
if (!type) continue;
TRACE( "matched type %p in tryblock %d catchblock %d\n", type, i, j );
/* copy the exception to its destination on the stack */
copy_exception( object, frame, catchblock, type );
/* unwind the stack */
RtlUnwind( frame, 0, rec, 0 );
cxx_local_unwind( frame, descr, tryblock->start_level );
frame->trylevel = tryblock->end_level + 1;
/* call the catch block */
TRACE( "calling catch block %p for type %p addr %p ebp %p\n",
catchblock, type, catchblock->handler, &frame->ebp );
/* setup an exception block for nested exceptions */
//nested_frame.frame.Handler = catch_function_nested_handler;
nested_frame.frame.Handler = (PEXCEPTION_HANDLER)catch_function_nested_handler;
nested_frame.prev_rec = thread_data->exc_record;
nested_frame.cxx_frame = frame;
nested_frame.descr = descr;
nested_frame.trylevel = nested_trylevel + 1;
__wine_push_frame( &nested_frame.frame );
thread_data->exc_record = rec;
addr = call_ebp_func( catchblock->handler, &frame->ebp );
thread_data->exc_record = nested_frame.prev_rec;
__wine_pop_frame( &nested_frame.frame );
if (info->destructor) call_dtor( info->destructor, object );
TRACE( "done, continuing at %p\n", addr );
return addr;
}
}
return NULL;
}
/*********************************************************************
* cxx_frame_handler
*
* Implementation of __CxxFrameHandler.
*/
static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch,
cxx_function_descr *descr, EXCEPTION_REGISTRATION_RECORD* nested_frame,
int nested_trylevel )
{
cxx_exception_type *exc_type;
void *next_ip;
PEXCEPTION_RECORD orig_rec = rec;
if (descr->magic != CXX_FRAME_MAGIC)
{
ERR( "invalid frame magic %x\n", descr->magic );
return ExceptionContinueSearch;
}
if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND))
{
if (descr->unwind_count && !nested_trylevel) cxx_local_unwind( frame, descr, -1 );
return ExceptionContinueSearch;
}
if (!descr->tryblock_count) return ExceptionContinueSearch;
exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
if (rec->ExceptionCode == CXX_EXCEPTION &&
rec->ExceptionInformation[0] > CXX_FRAME_MAGIC &&
exc_type->custom_handler)
{
return exc_type->custom_handler( rec, frame, exc_context, dispatch,
descr, nested_trylevel, nested_frame, 0 );
}
if (!exc_type) /* nested exception, fetch info from original exception */
{
rec = msvcrt_get_thread_data()->exc_record;
exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
}
if (TRACE_ON(seh))
{
TRACE("handling C++ exception rec %p frame %p trylevel %d descr %p nested_frame %p\n",
rec, frame, frame->trylevel, descr, nested_frame );
dump_exception_type( exc_type );
dump_function_descr( descr, exc_type );
}
next_ip = call_catch_block( rec, frame, descr, frame->trylevel, exc_type );
if (!next_ip) return ExceptionContinueSearch;
orig_rec->ExceptionFlags &= ~EH_NONCONTINUABLE;
exc_context->Eip = (DWORD)next_ip;
exc_context->Ebp = (DWORD)&frame->ebp;
exc_context->Esp = ((DWORD*)frame)[-1];
return ExceptionContinueExecution;
}
/*********************************************************************
* __CxxFrameHandler (MSVCRT.@)
*/
DWORD __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch )
{
cxx_function_descr *descr;
__asm__ __volatile__("mov %%eax, %0\n" : "=m"(descr));
return cxx_frame_handler(rec, (cxx_exception_frame *)frame,
exc_context, dispatch, descr, NULL, 0 );
}
#endif /* __i386__ */
/*********************************************************************
* _CxxThrowException (MSVCRT.@)
*/
void _CxxThrowException( void *object, const cxx_exception_type *type )
{
DWORD args[3];
args[0] = CXX_FRAME_MAGIC;
args[1] = (DWORD)object;
args[2] = (DWORD)type;
RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
}
/*********************************************************************
* __CxxDetectRethrow (MSVCRT.@)
*/
BOOL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs)
{
PEXCEPTION_RECORD rec;
if (!ptrs)
return FALSE;
rec = ptrs->ExceptionRecord;
if (rec->ExceptionCode == CXX_EXCEPTION &&
rec->NumberParameters == 3 &&
rec->ExceptionInformation[0] == CXX_FRAME_MAGIC &&
rec->ExceptionInformation[2])
{
ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record;
return TRUE;
}
return (msvcrt_get_thread_data()->exc_record == rec);
}
/*********************************************************************
* __CxxQueryExceptionSize (MSVCRT.@)
*/
unsigned int __CxxQueryExceptionSize(void)
{
return sizeof(cxx_exception_type);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -