Re: MSVCRT: added support for re-throwing exceptions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




THANK YOU ALBERTO!!!

This is just what I have been looking for with StarTeam, which now gets 
further!  Since your patch seems to have wrapped, I took the liberty of
patching it in by hand and resubmitting it.  Here goes:

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

"The purpose of government is to rein in the rights of the people"
 --President Bill Clinton, MTV interview, 1993
diff -ur -x CVS -x 'bigdif*' ../wine.test/dlls/msvcrt/cppexcept.c ./dlls/msvcrt/cppexcept.c
--- ../wine.test/dlls/msvcrt/cppexcept.c	2002-10-03 20:26:18.000000000 -0500
+++ ./dlls/msvcrt/cppexcept.c	2002-10-28 08:24:10.000000000 -0600
@@ -172,6 +172,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 );
@@ -236,6 +240,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];
@@ -300,13 +308,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;
 }
@@ -383,9 +391,10 @@
     if (!descr->tryblock_count) return ExceptionContinueSearch;
 
     exc_type = (cxx_exception_type *)rec->ExceptionInformation[2];
+
     if (rec->ExceptionCode != CXX_EXCEPTION) goto normal_handler;
     if (rec->ExceptionInformation[0] != CXX_FRAME_MAGIC) goto normal_handler;
-    if (exc_type->custom_handler)
+    if (exc_type!=NULL && exc_type->custom_handler)
         return exc_type->custom_handler( rec, frame, exc_context, dispatch, descr, 0, 0, 0 );
 
  normal_handler:
@@ -422,6 +431,8 @@
 
 #endif  /* __i386__ */
 
+extern DWORD LastExceptionObj_tls_index, LastExceptionType_tls_index;
+
 /*********************************************************************
  *		_CxxThrowException (MSVCRT.@)
  */
@@ -429,6 +440,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-10-25 00:03:04.000000000 -0500
+++ ./dlls/msvcrt/main.c	2002-10-28 08:26:47.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;
 }
 

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux