Another unmerged patch I'd like to see go in. cppexcept.c has changed a bit since this was submitted so I've tried to merge in the changes (at a glance, this seems to have worked). Let me know if there's anything that needs fixing before it can go in. LICENSE: LGPL CHANGELOG: * dlls/msvcrt: main.c, cppexcept.c: Alberto Massari <alby@exln.com> - allow MSVC C++ apps to reraise exceptions without infinite recursion in the exception handlers. -- gmt "War is an ugly thing, but not the ugliest of things; the decayed and degraded state of moral and patriotic feeling which thinks that nothing is worth war is much worse. A man who has nothing for which he is willing to fight; nothing he cares about more than his own personal safety; is a miserable creature who has no chance of being free, unless made and kept so by the exertions of better persons than himself." -- John Stuart Mill
diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/msvcrt/cppexcept.c ./dlls/msvcrt/cppexcept.c --- ../wine.test/dlls/msvcrt/cppexcept.c 2002-10-31 20:13:49.000000000 -0600 +++ ./dlls/msvcrt/cppexcept.c 2002-11-12 22:06:11.000000000 -0600 @@ -176,6 +176,10 @@ { int i; + if(type==NULL) + return; + + DPRINTF( "exception type:\n" ); DPRINTF( "flags %x destr %p handler %p type info %p\n", type->flags, type->destructor, type->custom_handler, type->type_info_table ); @@ -240,6 +244,10 @@ { UINT i; + if(exc_type==NULL || exc_type->type_info_table==NULL) + return NULL; + + for (i = 0; i < exc_type->type_info_table->count; i++) { cxx_type_info *type = exc_type->type_info_table->info[i]; @@ -304,13 +312,13 @@ MSVCRT_terminate(); } handler = descr->unwind_table[trylevel].handler; + trylevel = descr->unwind_table[trylevel].prev; if (handler) { TRACE( "calling unwind handler %p trylevel %d last %d ebp %p\n", handler, trylevel, last_level, &frame->ebp ); call_ebp_func( handler, &frame->ebp ); } - trylevel = descr->unwind_table[trylevel].prev; } frame->trylevel = last_level; } @@ -447,6 +455,8 @@ rec = msvcrt_get_thread_data()->exc_record; exc_type = (cxx_exception_type *)rec->ExceptionInformation[2]; } + else if (exc_type->custom_handler) + return exc_type->custom_handler( rec, frame, exc_context, dispatch, descr, 0, 0, 0 ); if (TRACE_ON(seh)) { @@ -481,6 +491,8 @@ #endif /* __i386__ */ +extern DWORD LastExceptionObj_tls_index, LastExceptionType_tls_index; + /********************************************************************* * _CxxThrowException (MSVCRT.@) */ @@ -488,6 +500,17 @@ { DWORD args[3]; + if(object==NULL && type==NULL) + { + object=TlsGetValue(LastExceptionObj_tls_index); + type=(cxx_exception_type*)TlsGetValue(LastExceptionType_tls_index); + } + else + { + TlsSetValue(LastExceptionObj_tls_index,object); + TlsSetValue(LastExceptionType_tls_index,type); + } + args[0] = CXX_FRAME_MAGIC; args[1] = (DWORD)object; args[2] = (DWORD)type; diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/msvcrt/main.c ./dlls/msvcrt/main.c --- ../wine.test/dlls/msvcrt/main.c 2002-11-04 21:30:27.000000000 -0600 +++ ./dlls/msvcrt/main.c 2002-11-12 22:01:55.000000000 -0600 @@ -29,6 +29,10 @@ /* Index to TLS */ DWORD MSVCRT_tls_index; +/* TLS for re-throwing exceptions */ +DWORD LastExceptionObj_tls_index; +DWORD LastExceptionType_tls_index; + static inline BOOL msvcrt_init_tls(void); static inline BOOL msvcrt_free_tls(void); const char* msvcrt_get_reason(DWORD reason) WINE_UNUSED; @@ -91,6 +95,21 @@ ERR("TlsAlloc() failed!\n"); return FALSE; } + + LastExceptionObj_tls_index=TlsAlloc(); + if (LastExceptionObj_tls_index == TLS_OUT_OF_INDEXES) + { + ERR("TlsAlloc() failed!\n"); + return FALSE; + } + + LastExceptionType_tls_index=TlsAlloc(); + if(LastExceptionType_tls_index == TLS_OUT_OF_INDEXES) + { + ERR("TlsAlloc() failed!\n"); + return FALSE; + } + return TRUE; } @@ -101,6 +120,16 @@ ERR("TlsFree() failed!\n"); return FALSE; } + if (!TlsFree(LastExceptionObj_tls_index)) + { + ERR("TlsFree() failed!\n"); + return FALSE; + } + if (!TlsFree(LastExceptionType_tls_index)) + { + ERR("TlsFree() failed!\n"); + return FALSE; + } return TRUE; }