mirror of
https://github.com/reactos/reactos.git
synced 2025-05-22 10:35:54 +00:00
- Winesync cppexcept.c. This fixes try/catch C++ exception handling in various apps (like MFC based apps).
svn path=/trunk/; revision=30363
This commit is contained in:
parent
ace89b703c
commit
5b21408b33
4 changed files with 183 additions and 103 deletions
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
* NOTES
|
||||
* A good reference is the article "How a C++ compiler implements
|
||||
|
@ -39,44 +39,59 @@
|
|||
|
||||
#include <internal/wine/cppexcept.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||
|
||||
#ifdef __i386__ /* CxxFrameHandler is not supported on non-i386 */
|
||||
|
||||
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 );
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||
|
||||
DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
|
||||
PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
|
||||
const cxx_function_descr *descr,
|
||||
EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel );
|
||||
|
||||
/* call a function with a given ebp */
|
||||
__inline static void *call_ebp_func( void *func, void *ebp )
|
||||
static inline void *call_ebp_func( void *func, void *ebp )
|
||||
{
|
||||
void *ret;
|
||||
__asm__ __volatile__ ("pushl %%ebp; movl %2,%%ebp; call *%%eax; popl %%ebp" \
|
||||
: "=a" (ret) : "0" (func), "g" (ebp) : "ecx", "edx", "memory" );
|
||||
int dummy;
|
||||
__asm__ __volatile__ ("pushl %%ebx\n\t"
|
||||
"pushl %%ebp\n\t"
|
||||
"movl %4,%%ebp\n\t"
|
||||
"call *%%eax\n\t"
|
||||
"popl %%ebp\n\t"
|
||||
"popl %%ebx"
|
||||
: "=a" (ret), "=S" (dummy), "=D" (dummy)
|
||||
: "0" (func), "1" (ebp) : "ecx", "edx", "memory" );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* call a copy constructor */
|
||||
__inline static void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
|
||||
static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
|
||||
{
|
||||
TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
|
||||
if (has_vbase)
|
||||
/* in that case copy ctor takes an extra bool indicating whether to copy the base class */
|
||||
__asm__ __volatile__("pushl $1; pushl %2; call *%0"
|
||||
: : "r" (func), "c" (this), "g" (src) : "eax", "edx", "memory" );
|
||||
: : "r" (func), "c" (this), "r" (src) : "eax", "edx", "memory" );
|
||||
else
|
||||
__asm__ __volatile__("pushl %2; call *%0"
|
||||
: : "r" (func), "c" (this), "g" (src) : "eax", "edx", "memory" );
|
||||
: : "r" (func), "c" (this), "r" (src) : "eax", "edx", "memory" );
|
||||
}
|
||||
|
||||
/* call the destructor of the exception object */
|
||||
__inline static void call_dtor( void *func, void *object )
|
||||
static inline void call_dtor( void *func, void *object )
|
||||
{
|
||||
__asm__ __volatile__("call *%0" : : "r" (func), "c" (object) : "eax", "edx", "memory" );
|
||||
}
|
||||
|
||||
static void dump_type( const cxx_type_info *type )
|
||||
/* continue execution to the specified address after exception is caught */
|
||||
static inline void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr )
|
||||
{
|
||||
__asm__ __volatile__("movl -4(%0),%%esp; leal 12(%0),%%ebp; jmp *%1"
|
||||
: : "r" (frame), "a" (addr) );
|
||||
for (;;) ; /* unreached */
|
||||
}
|
||||
|
||||
static inline void dump_type( const cxx_type_info *type )
|
||||
{
|
||||
TRACE( "flags %x type %p %s offsets %d,%d,%d size %d copy ctor %p\n",
|
||||
type->flags, type->type_info, dbgstr_type_info(type->type_info),
|
||||
|
@ -88,49 +103,47 @@ static void dump_exception_type( const cxx_exception_type *type )
|
|||
{
|
||||
UINT i;
|
||||
|
||||
DPRINTF( "exception type:\n" );
|
||||
DPRINTF( "flags %x destr %p handler %p type info %p\n",
|
||||
TRACE( "flags %x destr %p handler %p type info %p\n",
|
||||
type->flags, type->destructor, type->custom_handler, type->type_info_table );
|
||||
for (i = 0; i < type->type_info_table->count; i++)
|
||||
{
|
||||
DPRINTF( " %d: ", i );
|
||||
TRACE( " %d: ", i );
|
||||
dump_type( type->type_info_table->info[i] );
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_function_descr( const cxx_function_descr *descr, const cxx_exception_type *info )
|
||||
static void dump_function_descr( const cxx_function_descr *descr )
|
||||
{
|
||||
UINT i;
|
||||
int j;
|
||||
|
||||
DPRINTF( "function descr:\n" );
|
||||
DPRINTF( "magic %x\n", descr->magic );
|
||||
DPRINTF( "unwind table: %p %d\n", descr->unwind_table, descr->unwind_count );
|
||||
TRACE( "magic %x\n", descr->magic );
|
||||
TRACE( "unwind table: %p %d\n", descr->unwind_table, descr->unwind_count );
|
||||
for (i = 0; i < descr->unwind_count; i++)
|
||||
{
|
||||
DPRINTF( " %d: prev %d func %p\n", i,
|
||||
TRACE( " %d: prev %d func %p\n", i,
|
||||
descr->unwind_table[i].prev, descr->unwind_table[i].handler );
|
||||
}
|
||||
DPRINTF( "try table: %p %d\n", descr->tryblock, descr->tryblock_count );
|
||||
TRACE( "try table: %p %d\n", descr->tryblock, descr->tryblock_count );
|
||||
for (i = 0; i < descr->tryblock_count; i++)
|
||||
{
|
||||
DPRINTF( " %d: start %d end %d catchlevel %d catch %p %d\n", i,
|
||||
TRACE( " %d: start %d end %d catchlevel %d catch %p %d\n", i,
|
||||
descr->tryblock[i].start_level, descr->tryblock[i].end_level,
|
||||
descr->tryblock[i].catch_level, descr->tryblock[i].catchblock,
|
||||
descr->tryblock[i].catchblock_count );
|
||||
for (j = 0; j < descr->tryblock[i].catchblock_count; j++)
|
||||
{
|
||||
catchblock_info *ptr = &descr->tryblock[i].catchblock[j];
|
||||
DPRINTF( " %d: flags %x offset %d handler %p type %p",
|
||||
j, ptr->flags, ptr->offset, ptr->handler, ptr->type_info );
|
||||
if (ptr->type_info) DPRINTF( " (%p %s)", ptr->type_info->name, ptr->type_info->mangled );
|
||||
DPRINTF( "\n" );
|
||||
const catchblock_info *ptr = &descr->tryblock[i].catchblock[j];
|
||||
TRACE( " %d: flags %x offset %d handler %p type %p %s\n",
|
||||
j, ptr->flags, ptr->offset, ptr->handler,
|
||||
ptr->type_info, dbgstr_type_info( ptr->type_info ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the exception type is caught by a given catch block, and return the type that matched */
|
||||
static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type, catchblock_info *catchblock )
|
||||
static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type,
|
||||
const catchblock_info *catchblock )
|
||||
{
|
||||
UINT i;
|
||||
|
||||
|
@ -156,7 +169,7 @@ static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type, catc
|
|||
|
||||
/* copy the exception object where the catch block wants it */
|
||||
static void copy_exception( void *object, cxx_exception_frame *frame,
|
||||
catchblock_info *catchblock, const cxx_type_info *type )
|
||||
const catchblock_info *catchblock, const cxx_type_info *type )
|
||||
{
|
||||
void **dest_ptr;
|
||||
|
||||
|
@ -185,14 +198,14 @@ static void copy_exception( void *object, cxx_exception_frame *frame,
|
|||
}
|
||||
|
||||
/* unwind the local function up to a given trylevel */
|
||||
static void cxx_local_unwind( cxx_exception_frame* frame, cxx_function_descr *descr, int last_level)
|
||||
static void cxx_local_unwind( cxx_exception_frame* frame, const cxx_function_descr *descr, int last_level)
|
||||
{
|
||||
void (*handler)();
|
||||
int trylevel = frame->trylevel;
|
||||
|
||||
while (trylevel != last_level)
|
||||
{
|
||||
if (trylevel < 0 || trylevel >= (int)descr->unwind_count)
|
||||
if (trylevel < 0 || trylevel >= descr->unwind_count)
|
||||
{
|
||||
ERR( "invalid trylevel %d\n", trylevel );
|
||||
MSVCRT_terminate();
|
||||
|
@ -215,8 +228,9 @@ 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 */
|
||||
const cxx_function_descr *descr; /* descriptor of parent exception */
|
||||
int trylevel; /* current try level */
|
||||
EXCEPTION_RECORD *rec; /* rec associated with frame */
|
||||
};
|
||||
|
||||
/* handler for exceptions happening while calling a catch function */
|
||||
|
@ -230,20 +244,41 @@ static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REG
|
|||
msvcrt_get_thread_data()->exc_record = nested_frame->prev_rec;
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
else
|
||||
|
||||
TRACE( "got nested exception in catch function\n" );
|
||||
|
||||
if(rec->ExceptionCode == CXX_EXCEPTION)
|
||||
{
|
||||
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 );
|
||||
PEXCEPTION_RECORD prev_rec = nested_frame->rec;
|
||||
if(rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0)
|
||||
{
|
||||
/* exception was rethrown */
|
||||
rec->ExceptionInformation[1] = prev_rec->ExceptionInformation[1];
|
||||
rec->ExceptionInformation[2] = prev_rec->ExceptionInformation[2];
|
||||
TRACE("detect rethrow: re-propagate: obj: %lx, type: %lx\n",
|
||||
rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
|
||||
}
|
||||
else {
|
||||
/* new exception in exception handler, destroy old */
|
||||
void *object = (void*)prev_rec->ExceptionInformation[1];
|
||||
cxx_exception_type *info = (cxx_exception_type*) prev_rec->ExceptionInformation[2];
|
||||
TRACE("detect threw new exception in catch block - destroy old(obj: %p type: %p)\n",
|
||||
object, info);
|
||||
if(info && info->destructor)
|
||||
call_dtor( info->destructor, object );
|
||||
}
|
||||
}
|
||||
|
||||
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 )
|
||||
static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame,
|
||||
const cxx_function_descr *descr, int nested_trylevel,
|
||||
cxx_exception_type *info )
|
||||
{
|
||||
UINT i;
|
||||
int j;
|
||||
|
@ -251,10 +286,11 @@ __inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_fra
|
|||
struct catch_func_nested_frame nested_frame;
|
||||
int trylevel = frame->trylevel;
|
||||
MSVCRT_thread_data *thread_data = msvcrt_get_thread_data();
|
||||
DWORD save_esp = ((DWORD*)frame)[-1];
|
||||
|
||||
for (i = 0; i < descr->tryblock_count; i++)
|
||||
{
|
||||
tryblock_info *tryblock = &descr->tryblock[i];
|
||||
const tryblock_info *tryblock = &descr->tryblock[i];
|
||||
|
||||
if (trylevel < tryblock->start_level) continue;
|
||||
if (trylevel > tryblock->end_level) continue;
|
||||
|
@ -262,14 +298,24 @@ __inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_fra
|
|||
/* 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;
|
||||
const catchblock_info *catchblock = &tryblock->catchblock[j];
|
||||
if(info)
|
||||
{
|
||||
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 );
|
||||
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 );
|
||||
/* copy the exception to its destination on the stack */
|
||||
copy_exception( object, frame, catchblock, type );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no CXX_EXCEPTION only proceed with a catch(...) block*/
|
||||
if(catchblock->type_info)
|
||||
continue;
|
||||
TRACE("found catch(...) block\n");
|
||||
}
|
||||
|
||||
/* unwind the stack */
|
||||
RtlUnwind( frame, 0, rec, 0 );
|
||||
|
@ -277,17 +323,17 @@ __inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_fra
|
|||
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 );
|
||||
TRACE( "calling catch block %p addr %p ebp %p\n",
|
||||
catchblock, 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;
|
||||
nested_frame.rec = rec;
|
||||
|
||||
__wine_push_frame( &nested_frame.frame );
|
||||
thread_data->exc_record = rec;
|
||||
|
@ -295,12 +341,13 @@ __inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_fra
|
|||
thread_data->exc_record = nested_frame.prev_rec;
|
||||
__wine_pop_frame( &nested_frame.frame );
|
||||
|
||||
if (info->destructor) call_dtor( info->destructor, object );
|
||||
((DWORD*)frame)[-1] = save_esp;
|
||||
if (info && info->destructor) call_dtor( info->destructor, object );
|
||||
TRACE( "done, continuing at %p\n", addr );
|
||||
return addr;
|
||||
|
||||
continue_after_catch( frame, addr );
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,14 +356,13 @@ __inline static void *call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_fra
|
|||
*
|
||||
* 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 )
|
||||
DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
|
||||
PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
|
||||
const 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)
|
||||
{
|
||||
|
@ -330,71 +376,88 @@ static DWORD cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* fram
|
|||
}
|
||||
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)
|
||||
if(rec->ExceptionCode == CXX_EXCEPTION)
|
||||
{
|
||||
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))
|
||||
if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC &&
|
||||
exc_type->custom_handler)
|
||||
{
|
||||
return exc_type->custom_handler( rec, frame, context, dispatch,
|
||||
descr, nested_trylevel, nested_frame, 0 );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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 );
|
||||
exc_type = NULL;
|
||||
TRACE("handling C exception code %x rec %p frame %p trylevel %d descr %p nested_frame %p\n",
|
||||
rec->ExceptionCode, rec, frame, frame->trylevel, descr, nested_frame );
|
||||
}
|
||||
|
||||
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;
|
||||
call_catch_block( rec, frame, descr, frame->trylevel, exc_type );
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
* __CxxFrameHandler (MSVCRT.@)
|
||||
*/
|
||||
DWORD __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
|
||||
PCONTEXT exc_context, EXCEPTION_REGISTRATION_RECORD** dispatch )
|
||||
{
|
||||
cxx_function_descr *descr;
|
||||
extern DWORD CDECL __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
|
||||
PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch );
|
||||
__ASM_GLOBAL_FUNC( __CxxFrameHandler,
|
||||
"pushl $0\n\t" /* nested_trylevel */
|
||||
"pushl $0\n\t" /* nested_frame */
|
||||
"pushl %eax\n\t" /* descr */
|
||||
"pushl 28(%esp)\n\t" /* dispatch */
|
||||
"pushl 28(%esp)\n\t" /* context */
|
||||
"pushl 28(%esp)\n\t" /* frame */
|
||||
"pushl 28(%esp)\n\t" /* rec */
|
||||
"call " __ASM_NAME("cxx_frame_handler") "\n\t"
|
||||
"add $28,%esp\n\t"
|
||||
"ret" )
|
||||
|
||||
__asm__ __volatile__("mov %%eax, %0\n" : "=m"(descr));
|
||||
return cxx_frame_handler(rec, (cxx_exception_frame *)frame,
|
||||
exc_context, dispatch, descr, NULL, 0 );
|
||||
|
||||
/*********************************************************************
|
||||
* __CxxLongjmpUnwind (MSVCRT.@)
|
||||
*
|
||||
* Callback meant to be used as UnwindFunc for setjmp/longjmp.
|
||||
*/
|
||||
void __stdcall __CxxLongjmpUnwind( const struct MSVCRT___JUMP_BUFFER *buf )
|
||||
{
|
||||
cxx_exception_frame *frame = (cxx_exception_frame *)buf->Registration;
|
||||
const cxx_function_descr *descr = (const cxx_function_descr *)buf->UnwindData[0];
|
||||
|
||||
TRACE( "unwinding frame %p descr %p trylevel %ld\n", frame, descr, buf->TryLevel );
|
||||
cxx_local_unwind( frame, descr, buf->TryLevel );
|
||||
}
|
||||
|
||||
#endif /* __i386__ */
|
||||
|
||||
/*********************************************************************
|
||||
* _CxxThrowException (MSVCRT.@)
|
||||
*/
|
||||
void _CxxThrowException( void *object, const cxx_exception_type *type )
|
||||
void CDECL _CxxThrowException( exception *object, const cxx_exception_type *type )
|
||||
{
|
||||
DWORD args[3];
|
||||
ULONG_PTR args[3];
|
||||
|
||||
args[0] = CXX_FRAME_MAGIC;
|
||||
args[1] = (DWORD)object;
|
||||
args[2] = (DWORD)type;
|
||||
args[1] = (ULONG_PTR)object;
|
||||
args[2] = (ULONG_PTR)type;
|
||||
RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* __CxxDetectRethrow (MSVCRT.@)
|
||||
*/
|
||||
BOOL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs)
|
||||
BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs)
|
||||
{
|
||||
PEXCEPTION_RECORD rec;
|
||||
|
||||
|
@ -417,7 +480,7 @@ BOOL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs)
|
|||
/*********************************************************************
|
||||
* __CxxQueryExceptionSize (MSVCRT.@)
|
||||
*/
|
||||
unsigned int __CxxQueryExceptionSize(void)
|
||||
unsigned int CDECL __CxxQueryExceptionSize(void)
|
||||
{
|
||||
return sizeof(cxx_exception_type);
|
||||
}
|
||||
|
|
|
@ -121,7 +121,7 @@ typedef struct __cxx_type_info_table
|
|||
|
||||
typedef DWORD (*cxx_exc_custom_handler)( PEXCEPTION_RECORD, cxx_exception_frame*,
|
||||
PCONTEXT, EXCEPTION_REGISTRATION_RECORD**,
|
||||
cxx_function_descr*, int nested_trylevel,
|
||||
const cxx_function_descr*, int nested_trylevel,
|
||||
EXCEPTION_REGISTRATION_RECORD *nested_frame, DWORD unknown3 );
|
||||
|
||||
/* type information for an exception object */
|
||||
|
@ -133,7 +133,7 @@ typedef struct __cxx_exception_type
|
|||
const cxx_type_info_table *type_info_table; /* list of types for this exception object */
|
||||
} cxx_exception_type;
|
||||
|
||||
void _CxxThrowException(void*,const cxx_exception_type*);
|
||||
void _CxxThrowException(exception*,const cxx_exception_type*);
|
||||
|
||||
static inline const char *dbgstr_type_info( const type_info *info )
|
||||
{
|
||||
|
|
|
@ -166,6 +166,23 @@ extern void msvcrt_free_args(void);
|
|||
#define _RT_CRNL 252
|
||||
#define _RT_BANNER 255
|
||||
|
||||
#ifdef __i386__
|
||||
struct MSVCRT___JUMP_BUFFER {
|
||||
unsigned long Ebp;
|
||||
unsigned long Ebx;
|
||||
unsigned long Edi;
|
||||
unsigned long Esi;
|
||||
unsigned long Esp;
|
||||
unsigned long Eip;
|
||||
unsigned long Registration;
|
||||
unsigned long TryLevel;
|
||||
/* Start of new struct members */
|
||||
unsigned long Cookie;
|
||||
unsigned long UnwindFunc;
|
||||
unsigned long UnwindData[6];
|
||||
};
|
||||
#endif /* __i386__ */
|
||||
|
||||
typedef void* (*malloc_func_t)(size_t);
|
||||
typedef void (*free_func_t)(void*);
|
||||
#define MSVCRT_malloc malloc
|
||||
|
|
|
@ -119,8 +119,8 @@ kernel32 -
|
|||
|
||||
msvcrt -
|
||||
reactos/dll/win32/msvcrt/wine/*.c # Out of sync
|
||||
reactos/lib/sdk/crt/except # Synced at XXXXXXXX
|
||||
reactos/lib/sdk/crt/cpp.c # Synced at 20071111
|
||||
reactos/lib/sdk/crt/cppexcept.c # Synced at 20071111
|
||||
reactos/lib/sdk/crt/wine # Synced at XXXXXXXX
|
||||
|
||||
User32 -
|
||||
|
|
Loading…
Reference in a new issue