ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cppexcept.c
Go to the documentation of this file.
00001 /*
00002  * msvcrt C++ exception handling
00003  *
00004  * Copyright 2002 Alexandre Julliard
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  *
00020  * NOTES
00021  * A good reference is the article "How a C++ compiler implements
00022  * exception handling" by Vishal Kochhar, available on
00023  * www.thecodeproject.com.
00024  */
00025 
00026 #define __WINE_DEBUG_CHANNEL__
00027 #include <precomp.h>
00028 #include <stdarg.h>
00029 
00030 #include <wine/exception.h>
00031 #include <internal/wine/msvcrt.h>
00032 #include <internal/wine/cppexcept.h>
00033 
00034 #ifdef __i386__  /* CxxFrameHandler is not supported on non-i386 */
00035 
00036 WINE_DEFAULT_DEBUG_CHANNEL(seh);
00037 
00038 DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
00039                                PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
00040                                const cxx_function_descr *descr,
00041                                EXCEPTION_REGISTRATION_RECORD* nested_frame, int nested_trylevel );
00042 
00043 /* call a function with a given ebp */
00044 #ifdef _MSC_VER
00045 #pragma warning(disable:4731) // don't warn about modification of ebp
00046 #endif
00047 static inline void *call_ebp_func( void *func, void *_ebp )
00048 {
00049     void *result;
00050 #ifdef _MSC_VER
00051     __asm
00052     {
00053         mov eax, func
00054         push ebx
00055         push ebp
00056         mov ebp, _ebp
00057         call eax
00058         pop ebp
00059         pop ebx
00060         mov result, eax
00061     }
00062 #else
00063     int dummy;
00064     __asm__ __volatile__ ("pushl %%ebx\n\t"
00065                           "pushl %%ebp\n\t"
00066                           "movl %4,%%ebp\n\t"
00067                           "call *%%eax\n\t"
00068                           "popl %%ebp\n\t"
00069                           "popl %%ebx"
00070                           : "=a" (result), "=S" (dummy), "=D" (dummy)
00071                           : "0" (func), "1" (_ebp) : "ecx", "edx", "memory" );
00072 #endif
00073     return result;
00074 }
00075 #ifdef _MSC_VER
00076 #pragma warning(default:4731)
00077 #endif
00078 
00079 /* call a copy constructor */
00080 static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
00081 {
00082     TRACE( "calling copy ctor %p object %p src %p\n", func, this, src );
00083 #ifdef _MSC_VER
00084     if (has_vbase)
00085     {
00086         __asm
00087         {
00088             mov ecx, this
00089             push 1
00090             push src
00091             call func
00092         }
00093     }
00094     else
00095     {
00096         __asm
00097         {
00098             mov ecx, this
00099             push src
00100             call func
00101         }
00102     }
00103 #else
00104     if (has_vbase)
00105         /* in that case copy ctor takes an extra bool indicating whether to copy the base class */
00106         __asm__ __volatile__("pushl $1; pushl %2; call *%0"
00107                              : : "r" (func), "c" (this), "r" (src) : "eax", "edx", "memory" );
00108     else
00109         __asm__ __volatile__("pushl %2; call *%0"
00110                              : : "r" (func), "c" (this), "r" (src) : "eax", "edx", "memory" );
00111 #endif
00112 }
00113 
00114 /* call the destructor of the exception object */
00115 static inline void call_dtor( void *func, void *object )
00116 {
00117 #ifdef _MSC_VER
00118     __asm
00119     {
00120         mov ecx, object
00121         call func
00122     }
00123 #else
00124     __asm__ __volatile__("call *%0" : : "r" (func), "c" (object) : "eax", "edx", "memory" );
00125 #endif
00126 }
00127 
00128 #ifdef _MSC_VER
00129 #pragma warning(push)
00130 #pragma warning(disable:4731)
00131 /* continue execution to the specified address after exception is caught */
00132 __forceinline void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr )
00133 {
00134     __asm
00135     {
00136         mov eax, addr
00137         mov edx, frame
00138         mov esp, [edx-4]
00139         lea ebp, [edx+12]
00140         jmp eax
00141     }
00142     for (;;) ; /* unreached */
00143 }
00144 #pragma warning(pop)
00145 #else
00146 /* continue execution to the specified address after exception is caught */
00147 static inline void DECLSPEC_NORETURN continue_after_catch( cxx_exception_frame* frame, void *addr )
00148 {
00149     __asm__ __volatile__("movl -4(%0),%%esp; leal 12(%0),%%ebp; jmp *%1"
00150                          : : "r" (frame), "a" (addr) );
00151     for (;;) ; /* unreached */
00152 }
00153 #endif
00154 
00155 static inline void dump_type( const cxx_type_info *type )
00156 {
00157     TRACE( "flags %x type %p %s offsets %d,%d,%d size %d copy ctor %p\n",
00158              type->flags, type->type_info, dbgstr_type_info(type->type_info),
00159              type->offsets.this_offset, type->offsets.vbase_descr, type->offsets.vbase_offset,
00160              type->size, type->copy_ctor );
00161 }
00162 
00163 static void dump_exception_type( const cxx_exception_type *type )
00164 {
00165     UINT i;
00166 
00167     TRACE( "flags %x destr %p handler %p type info %p\n",
00168              type->flags, type->destructor, type->custom_handler, type->type_info_table );
00169     for (i = 0; i < type->type_info_table->count; i++)
00170     {
00171         TRACE( "    %d: ", i );
00172         dump_type( type->type_info_table->info[i] );
00173     }
00174 }
00175 
00176 static void dump_function_descr( const cxx_function_descr *descr )
00177 {
00178 #ifndef WINE_NO_TRACE_MSGS
00179     UINT i;
00180     int j;
00181 
00182     TRACE( "magic %x\n", descr->magic );
00183     TRACE( "unwind table: %p %d\n", descr->unwind_table, descr->unwind_count );
00184     for (i = 0; i < descr->unwind_count; i++)
00185     {
00186         TRACE( "    %d: prev %d func %p\n", i,
00187                  descr->unwind_table[i].prev, descr->unwind_table[i].handler );
00188     }
00189     TRACE( "try table: %p %d\n", descr->tryblock, descr->tryblock_count );
00190     for (i = 0; i < descr->tryblock_count; i++)
00191     {
00192         TRACE( "    %d: start %d end %d catchlevel %d catch %p %d\n", i,
00193                  descr->tryblock[i].start_level, descr->tryblock[i].end_level,
00194                  descr->tryblock[i].catch_level, descr->tryblock[i].catchblock,
00195                  descr->tryblock[i].catchblock_count );
00196         for (j = 0; j < descr->tryblock[i].catchblock_count; j++)
00197         {
00198             const catchblock_info *ptr = &descr->tryblock[i].catchblock[j];
00199             TRACE( "        %d: flags %x offset %d handler %p type %p %s\n",
00200                      j, ptr->flags, ptr->offset, ptr->handler,
00201                      ptr->type_info, dbgstr_type_info( ptr->type_info ) );
00202         }
00203     }
00204 #endif
00205     if (descr->magic <= CXX_FRAME_MAGIC_VC6) return;
00206     TRACE( "expect list: %p\n", descr->expect_list );
00207     if (descr->magic <= CXX_FRAME_MAGIC_VC7) return;
00208     TRACE( "flags: %08x\n", descr->flags );
00209 }
00210 
00211 /* check if the exception type is caught by a given catch block, and return the type that matched */
00212 static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type,
00213                                               const catchblock_info *catchblock )
00214 {
00215     UINT i;
00216 
00217     for (i = 0; i < exc_type->type_info_table->count; i++)
00218     {
00219         const cxx_type_info *type = exc_type->type_info_table->info[i];
00220 
00221         if (!catchblock->type_info) return type;   /* catch(...) matches any type */
00222         if (catchblock->type_info != type->type_info)
00223         {
00224             if (strcmp( catchblock->type_info->mangled, type->type_info->mangled )) continue;
00225         }
00226         /* type is the same, now check the flags */
00227         if ((exc_type->flags & TYPE_FLAG_CONST) &&
00228             !(catchblock->flags & TYPE_FLAG_CONST)) continue;
00229         if ((exc_type->flags & TYPE_FLAG_VOLATILE) &&
00230             !(catchblock->flags & TYPE_FLAG_VOLATILE)) continue;
00231         return type;  /* it matched */
00232     }
00233     return NULL;
00234 }
00235 
00236 
00237 /* copy the exception object where the catch block wants it */
00238 static void copy_exception( void *object, cxx_exception_frame *frame,
00239                             const catchblock_info *catchblock, const cxx_type_info *type )
00240 {
00241     void **dest_ptr;
00242 
00243     if (!catchblock->type_info || !catchblock->type_info->mangled[0]) return;
00244     if (!catchblock->offset) return;
00245     dest_ptr = (void **)((char *)&frame->ebp + catchblock->offset);
00246 
00247     if (catchblock->flags & TYPE_FLAG_REFERENCE)
00248     {
00249         *dest_ptr = get_this_pointer( &type->offsets, object );
00250     }
00251     else if (type->flags & CLASS_IS_SIMPLE_TYPE)
00252     {
00253         memmove( dest_ptr, object, type->size );
00254         /* if it is a pointer, adjust it */
00255         if (type->size == sizeof(void *)) *dest_ptr = get_this_pointer( &type->offsets, *dest_ptr );
00256     }
00257     else  /* copy the object */
00258     {
00259         if (type->copy_ctor)
00260             call_copy_ctor( type->copy_ctor, dest_ptr, get_this_pointer(&type->offsets,object),
00261                             (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) );
00262         else
00263             memmove( dest_ptr, get_this_pointer(&type->offsets,object), type->size );
00264     }
00265 }
00266 
00267 /* unwind the local function up to a given trylevel */
00268 static void cxx_local_unwind( cxx_exception_frame* frame, const cxx_function_descr *descr, int last_level)
00269 {
00270     void (*handler)(void);
00271     int trylevel = frame->trylevel;
00272 
00273     while (trylevel != last_level)
00274     {
00275         if (trylevel < 0 || (unsigned)trylevel >= descr->unwind_count)
00276         {
00277             ERR( "invalid trylevel %d\n", trylevel );
00278             MSVCRT_terminate();
00279         }
00280         handler = descr->unwind_table[trylevel].handler;
00281         if (handler)
00282         {
00283             TRACE( "calling unwind handler %p trylevel %d last %d ebp %p\n",
00284                    handler, trylevel, last_level, &frame->ebp );
00285             call_ebp_func( handler, &frame->ebp );
00286         }
00287         trylevel = descr->unwind_table[trylevel].prev;
00288     }
00289     frame->trylevel = last_level;
00290 }
00291 
00292 /* exception frame for nested exceptions in catch block */
00293 struct catch_func_nested_frame
00294 {
00295     EXCEPTION_REGISTRATION_RECORD frame;     /* standard exception frame */
00296     EXCEPTION_RECORD             *prev_rec;  /* previous record to restore in thread data */
00297     cxx_exception_frame          *cxx_frame; /* frame of parent exception */
00298     const cxx_function_descr     *descr;     /* descriptor of parent exception */
00299     int                           trylevel;  /* current try level */
00300     EXCEPTION_RECORD             *rec;       /* rec associated with frame */
00301 };
00302 
00303 /* handler for exceptions happening while calling a catch function */
00304 static DWORD catch_function_nested_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
00305                                             CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **dispatcher )
00306 {
00307     struct catch_func_nested_frame *nested_frame = (struct catch_func_nested_frame *)frame;
00308 
00309     if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
00310     {
00311         msvcrt_get_thread_data()->exc_record = nested_frame->prev_rec;
00312         return ExceptionContinueSearch;
00313     }
00314 
00315     TRACE( "got nested exception in catch function\n" );
00316 
00317     if(rec->ExceptionCode == CXX_EXCEPTION)
00318     {
00319         PEXCEPTION_RECORD prev_rec = nested_frame->rec;
00320         if(rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0)
00321         {
00322             /* exception was rethrown */
00323             rec->ExceptionInformation[1] = prev_rec->ExceptionInformation[1];
00324             rec->ExceptionInformation[2] = prev_rec->ExceptionInformation[2];
00325             TRACE("detect rethrow: re-propagate: obj: %lx, type: %lx\n",
00326                     rec->ExceptionInformation[1], rec->ExceptionInformation[2]);
00327         }
00328         else {
00329             /* new exception in exception handler, destroy old */
00330             void *object = (void*)prev_rec->ExceptionInformation[1];
00331             cxx_exception_type *info = (cxx_exception_type*) prev_rec->ExceptionInformation[2];
00332             TRACE("detect threw new exception in catch block - destroy old(obj: %p type: %p)\n",
00333                     object, info);
00334             if(info && info->destructor)
00335                 call_dtor( info->destructor, object );
00336         }
00337     }
00338 
00339     return cxx_frame_handler( rec, nested_frame->cxx_frame, context,
00340                               NULL, nested_frame->descr, &nested_frame->frame,
00341                               nested_frame->trylevel );
00342 }
00343 
00344 /* find and call the appropriate catch block for an exception */
00345 /* returns the address to continue execution to after the catch block was called */
00346 static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame *frame,
00347                                      const cxx_function_descr *descr, int nested_trylevel,
00348                                      cxx_exception_type *info )
00349 {
00350     UINT i;
00351     int j;
00352     void *addr, *object = (void *)rec->ExceptionInformation[1];
00353     struct catch_func_nested_frame nested_frame;
00354     int trylevel = frame->trylevel;
00355     thread_data_t *thread_data = msvcrt_get_thread_data();
00356     DWORD save_esp = ((DWORD*)frame)[-1];
00357 
00358     for (i = 0; i < descr->tryblock_count; i++)
00359     {
00360         const tryblock_info *tryblock = &descr->tryblock[i];
00361 
00362         if (trylevel < tryblock->start_level) continue;
00363         if (trylevel > tryblock->end_level) continue;
00364 
00365         /* got a try block */
00366         for (j = 0; j < tryblock->catchblock_count; j++)
00367         {
00368             const catchblock_info *catchblock = &tryblock->catchblock[j];
00369             if(info)
00370             {
00371                 const cxx_type_info *type = find_caught_type( info, catchblock );
00372                 if (!type) continue;
00373 
00374                 TRACE( "matched type %p in tryblock %d catchblock %d\n", type, i, j );
00375 
00376                 /* copy the exception to its destination on the stack */
00377                 copy_exception( object, frame, catchblock, type );
00378             }
00379             else
00380             {
00381                 /* no CXX_EXCEPTION only proceed with a catch(...) block*/
00382                 if(catchblock->type_info)
00383                     continue;
00384                 TRACE("found catch(...) block\n");
00385             }
00386 
00387             /* unwind the stack */
00388             RtlUnwind( frame, 0, rec, 0 );
00389             cxx_local_unwind( frame, descr, tryblock->start_level );
00390             frame->trylevel = tryblock->end_level + 1;
00391 
00392             /* call the catch block */
00393             TRACE( "calling catch block %p addr %p ebp %p\n",
00394                    catchblock, catchblock->handler, &frame->ebp );
00395 
00396             /* setup an exception block for nested exceptions */
00397 
00398             nested_frame.frame.Handler = (PEXCEPTION_ROUTINE)catch_function_nested_handler;
00399             nested_frame.prev_rec  = thread_data->exc_record;
00400             nested_frame.cxx_frame = frame;
00401             nested_frame.descr     = descr;
00402             nested_frame.trylevel  = nested_trylevel + 1;
00403             nested_frame.rec = rec;
00404 
00405             __wine_push_frame( &nested_frame.frame );
00406             thread_data->exc_record = rec;
00407             addr = call_ebp_func( catchblock->handler, &frame->ebp );
00408             thread_data->exc_record = nested_frame.prev_rec;
00409             __wine_pop_frame( &nested_frame.frame );
00410 
00411             ((DWORD*)frame)[-1] = save_esp;
00412             if (info && info->destructor) call_dtor( info->destructor, object );
00413             TRACE( "done, continuing at %p\n", addr );
00414 
00415             continue_after_catch( frame, addr );
00416         }
00417     }
00418 }
00419 
00420 
00421 /*********************************************************************
00422  *      cxx_frame_handler
00423  *
00424  * Implementation of __CxxFrameHandler.
00425  */
00426 DWORD CDECL cxx_frame_handler( PEXCEPTION_RECORD rec, cxx_exception_frame* frame,
00427                                PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch,
00428                                const cxx_function_descr *descr,
00429                                EXCEPTION_REGISTRATION_RECORD* nested_frame,
00430                                int nested_trylevel )
00431 {
00432     cxx_exception_type *exc_type;
00433 
00434     if (descr->magic < CXX_FRAME_MAGIC_VC6 || descr->magic > CXX_FRAME_MAGIC_VC8)
00435     {
00436         ERR( "invalid frame magic %x\n", descr->magic );
00437         return ExceptionContinueSearch;
00438     }
00439     if (descr->magic >= CXX_FRAME_MAGIC_VC8 &&
00440         (descr->flags & FUNC_DESCR_SYNCHRONOUS) &&
00441         (rec->ExceptionCode != CXX_EXCEPTION))
00442         return ExceptionContinueSearch;  /* handle only c++ exceptions */
00443 
00444     if (rec->ExceptionFlags & (EH_UNWINDING|EH_EXIT_UNWIND))
00445     {
00446         if (descr->unwind_count && !nested_trylevel) cxx_local_unwind( frame, descr, -1 );
00447         return ExceptionContinueSearch;
00448     }
00449     if (!descr->tryblock_count) return ExceptionContinueSearch;
00450 
00451     if(rec->ExceptionCode == CXX_EXCEPTION)
00452     {
00453         exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
00454 
00455         if (rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8 &&
00456                 exc_type->custom_handler)
00457         {
00458             return exc_type->custom_handler( rec, frame, context, dispatch,
00459                                          descr, nested_trylevel, nested_frame, 0 );
00460         }
00461 
00462         if (TRACE_ON(seh))
00463         {
00464             TRACE("handling C++ exception rec %p frame %p trylevel %d descr %p nested_frame %p\n",
00465                   rec, frame, frame->trylevel, descr, nested_frame );
00466             dump_exception_type( exc_type );
00467             dump_function_descr( descr );
00468         }
00469     }
00470     else
00471     {
00472         exc_type = NULL;
00473         TRACE("handling C exception code %x  rec %p frame %p trylevel %d descr %p nested_frame %p\n",
00474               rec->ExceptionCode,  rec, frame, frame->trylevel, descr, nested_frame );
00475     }
00476 
00477     call_catch_block( rec, frame, descr, frame->trylevel, exc_type );
00478     return ExceptionContinueSearch;
00479 }
00480 
00481 
00482 /*********************************************************************
00483  *      __CxxFrameHandler (MSVCRT.@)
00484  */
00485 extern DWORD CDECL __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
00486                                       PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch );
00487 #ifdef _MSC_VER
00488 DWORD _declspec(naked) __CxxFrameHandler( PEXCEPTION_RECORD rec, EXCEPTION_REGISTRATION_RECORD* frame,
00489                                       PCONTEXT context, EXCEPTION_REGISTRATION_RECORD** dispatch )
00490 {
00491     __asm
00492     {
00493         push 0
00494         push 0
00495         push eax
00496         push [esp + 28]
00497         push [esp + 28]
00498         push [esp + 28]
00499         push [esp + 28]
00500         call cxx_frame_handler
00501         add esp, 28
00502         ret
00503     }
00504 }
00505 #else
00506 __ASM_GLOBAL_FUNC( __CxxFrameHandler,
00507                    "pushl $0\n\t"        /* nested_trylevel */
00508                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
00509                    "pushl $0\n\t"        /* nested_frame */
00510                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
00511                    "pushl %eax\n\t"      /* descr */
00512                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
00513                    "pushl 28(%esp)\n\t"  /* dispatch */
00514                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
00515                    "pushl 28(%esp)\n\t"  /* context */
00516                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
00517                    "pushl 28(%esp)\n\t"  /* frame */
00518                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
00519                    "pushl 28(%esp)\n\t"  /* rec */
00520                    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
00521                    "call " __ASM_NAME("cxx_frame_handler") "\n\t"
00522                    "add $28,%esp\n\t"
00523                    __ASM_CFI(".cfi_adjust_cfa_offset -28\n\t")
00524                    "ret" )
00525 #endif
00526 
00527 /*********************************************************************
00528  *      __CxxLongjmpUnwind (MSVCRT.@)
00529  *
00530  * Callback meant to be used as UnwindFunc for setjmp/longjmp.
00531  */
00532 void __stdcall __CxxLongjmpUnwind( const struct __JUMP_BUFFER *buf )
00533 {
00534     cxx_exception_frame *frame = (cxx_exception_frame *)buf->Registration;
00535     const cxx_function_descr *descr = (const cxx_function_descr *)buf->UnwindData[0];
00536 
00537     TRACE( "unwinding frame %p descr %p trylevel %ld\n", frame, descr, buf->TryLevel );
00538     cxx_local_unwind( frame, descr, buf->TryLevel );
00539 }
00540 
00541 #endif  /* __i386__ */
00542 
00543 
00544 /*********************************************************************
00545  *      __CppXcptFilter (MSVCRT.@)
00546  */
00547 int CDECL __CppXcptFilter(NTSTATUS ex, PEXCEPTION_POINTERS ptr)
00548 {
00549     /* only filter c++ exceptions */
00550     if (ex != CXX_EXCEPTION) return EXCEPTION_CONTINUE_SEARCH;
00551     return _XcptFilter( ex, ptr );
00552 }
00553 
00554 /*********************************************************************
00555  *      _CxxThrowException (MSVCRT.@)
00556  */
00557 void WINAPI _CxxThrowException( exception *object, const cxx_exception_type *type )
00558 {
00559     ULONG_PTR args[3];
00560 
00561     args[0] = CXX_FRAME_MAGIC_VC6;
00562     args[1] = (ULONG_PTR)object;
00563     args[2] = (ULONG_PTR)type;
00564     RaiseException( CXX_EXCEPTION, EH_NONCONTINUABLE, 3, args );
00565 }
00566 
00567 /*********************************************************************
00568  *      __CxxDetectRethrow (MSVCRT.@)
00569  */
00570 BOOL CDECL __CxxDetectRethrow(PEXCEPTION_POINTERS ptrs)
00571 {
00572   PEXCEPTION_RECORD rec;
00573 
00574   if (!ptrs)
00575     return FALSE;
00576 
00577   rec = ptrs->ExceptionRecord;
00578 
00579   if (rec->ExceptionCode == CXX_EXCEPTION &&
00580       rec->NumberParameters == 3 &&
00581       rec->ExceptionInformation[0] == CXX_FRAME_MAGIC_VC6 &&
00582       rec->ExceptionInformation[2])
00583   {
00584     ptrs->ExceptionRecord = msvcrt_get_thread_data()->exc_record;
00585     return TRUE;
00586   }
00587   return (msvcrt_get_thread_data()->exc_record == rec);
00588 }
00589 
00590 /*********************************************************************
00591  *      __CxxQueryExceptionSize (MSVCRT.@)
00592  */
00593 unsigned int CDECL __CxxQueryExceptionSize(void)
00594 {
00595   return sizeof(cxx_exception_type);
00596 }

Generated on Sat May 26 2012 04:35:26 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.