From: Piotr Caban <piotr@codeweavers.com>
Subject: msvcrt: Add i386 __CxxExceptionFilter implementation
Message-Id: <560A6691.7070606@codeweavers.com>
Date: Tue, 29 Sep 2015 12:23:13 +0200

Signed-off-by: Piotr Caban <piotr@codeweavers.com>
---
  dlls/msvcr100/msvcr100.spec         |  2 +-
  dlls/msvcr110/msvcr110.spec         |  2 +-
  dlls/msvcr120/msvcr120.spec         |  2 +-
  dlls/msvcr120_app/msvcr120_app.spec |  2 +-
  dlls/msvcr70/msvcr70.spec           |  2 +-
  dlls/msvcr71/msvcr71.spec           |  2 +-
  dlls/msvcr80/msvcr80.spec           |  2 +-
  dlls/msvcr90/msvcr90.spec           |  2 +-
  dlls/msvcrt/except_arm.c            |  9 +++++
  dlls/msvcrt/except_i386.c           | 71 
+++++++++++++++++++++++++++++++++----
  dlls/msvcrt/except_x86_64.c         |  9 +++++
  dlls/msvcrt/msvcrt.spec             |  2 +-
  dlls/ucrtbase/ucrtbase.spec         |  2 +-
  13 files changed, 92 insertions(+), 17 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index edff2c9..8ceecc9 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -548,7 +548,7 @@
 @ stub __CxxCallUnwindStdDelDtor
 @ stub __CxxCallUnwindVecDtor
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) __CxxFrameHandler
diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec
index 9dda90a..e42ec11 100644
--- a/dlls/msvcr110/msvcr110.spec
+++ b/dlls/msvcr110/msvcr110.spec
@@ -875,7 +875,7 @@
 @ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler
 @ cdecl -arch=i386,x86_64,arm __CppXcptFilter(long ptr)
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) __CxxFrameHandler
diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec
index 6e13eef..9f04cbf 100644
--- a/dlls/msvcr120/msvcr120.spec
+++ b/dlls/msvcr120/msvcr120.spec
@@ -859,7 +859,7 @@
 @ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler
 @ cdecl -arch=i386,x86_64,arm __CppXcptFilter(long ptr)
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) __CxxFrameHandler
diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec
index bc4d63b..d3591c1 100644
--- a/dlls/msvcr120_app/msvcr120_app.spec
+++ b/dlls/msvcr120_app/msvcr120_app.spec
@@ -853,7 +853,7 @@
 @ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) msvcr120.__C_specific_handler
 @ cdecl -arch=i386,x86_64,arm __CppXcptFilter(long ptr) msvcr120.__CppXcptFilter
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr) msvcr120.__CxxDetectRethrow
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr) msvcr120.__CxxExceptionFilter
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr) msvcr120.__CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) msvcr120.__CxxFrameHandler2
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) msvcr120.__CxxFrameHandler3
diff --git a/dlls/msvcr70/msvcr70.spec b/dlls/msvcr70/msvcr70.spec
index eb3464b..3382652 100644
--- a/dlls/msvcr70/msvcr70.spec
+++ b/dlls/msvcr70/msvcr70.spec
@@ -119,7 +119,7 @@
 @ stub __CxxCallUnwindDtor
 @ stub __CxxCallUnwindVecDtor
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ stdcall -arch=i386 __CxxLongjmpUnwind(ptr)
 @ cdecl -arch=i386,x86_64,arm __CxxQueryExceptionSize()
diff --git a/dlls/msvcr71/msvcr71.spec b/dlls/msvcr71/msvcr71.spec
index 92c71c3..fbdf839 100644
--- a/dlls/msvcr71/msvcr71.spec
+++ b/dlls/msvcr71/msvcr71.spec
@@ -114,7 +114,7 @@
 @ stub __CxxCallUnwindDtor
 @ stub __CxxCallUnwindVecDtor
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ stdcall -arch=i386 __CxxLongjmpUnwind(ptr)
 @ cdecl -arch=i386,x86_64,arm __CxxQueryExceptionSize()
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index cc10014..e83e056 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -182,7 +182,7 @@
 @ stub __CxxCallUnwindStdDelDtor
 @ stub __CxxCallUnwindVecDtor
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) __CxxFrameHandler
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index e5415c4..9aef185 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -173,7 +173,7 @@
 @ stub __CxxCallUnwindStdDelDtor
 @ stub __CxxCallUnwindVecDtor
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) __CxxFrameHandler
diff --git a/dlls/msvcrt/except_arm.c b/dlls/msvcrt/except_arm.c
index 465f310..62dadef 100644
--- a/dlls/msvcrt/except_arm.c
+++ b/dlls/msvcrt/except_arm.c
@@ -64,6 +64,15 @@ typedef struct _DISPATCHER_CONTEXT
     DWORD                 VirtualVfpHead;
 } DISPATCHER_CONTEXT;
 
+/*********************************************************************
+ *		__CxxExceptionFilter (MSVCRT.@)
+ */
+int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs,
+                                const type_info *ti, int flags, void **copy )
+{
+    FIXME( "%p %p %x %p: not implemented\n", ptrs, ti, flags, copy );
+    return EXCEPTION_CONTINUE_SEARCH;
+}
 
 /*********************************************************************
  *		__CxxFrameHandler (MSVCRT.@)
diff --git a/dlls/msvcrt/except_i386.c b/dlls/msvcrt/except_i386.c
index 2a4ef9d..6cbb758 100644
--- a/dlls/msvcrt/except_i386.c
+++ b/dlls/msvcrt/except_i386.c
@@ -266,7 +266,7 @@ static void dump_function_descr( const cxx_function_descr *descr )
 
 /* 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,
-                                              const catchblock_info *catchblock )
+                                              const type_info *catch_ti, UINT catch_flags )
 {
     UINT i;
 
@@ -274,16 +274,16 @@ static const cxx_type_info *find_caught_type( cxx_exception_type *exc_type,
     {
         const cxx_type_info *type = exc_type->type_info_table->info[i];
 
-        if (!catchblock->type_info) return type;   /* catch(...) matches any type */
-        if (catchblock->type_info != type->type_info)
+        if (!catch_ti) return type;   /* catch(...) matches any type */
+        if (catch_ti != type->type_info)
         {
-            if (strcmp( catchblock->type_info->mangled, type->type_info->mangled )) continue;
+            if (strcmp( catch_ti->mangled, type->type_info->mangled )) continue;
         }
         /* type is the same, now check the flags */
         if ((exc_type->flags & TYPE_FLAG_CONST) &&
-            !(catchblock->flags & TYPE_FLAG_CONST)) continue;
+            !(catch_flags & TYPE_FLAG_CONST)) continue;
         if ((exc_type->flags & TYPE_FLAG_VOLATILE) &&
-            !(catchblock->flags & TYPE_FLAG_VOLATILE)) continue;
+            !(catch_flags & TYPE_FLAG_VOLATILE)) continue;
         return type;  /* it matched */
     }
     return NULL;
@@ -442,7 +442,8 @@ static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame
             const catchblock_info *catchblock = &tryblock->catchblock[j];
             if(info)
             {
-                const cxx_type_info *type = find_caught_type( info, catchblock );
+                const cxx_type_info *type = find_caught_type( info,
+                        catchblock->type_info, catchblock->flags );
                 if (!type) continue;
 
                 TRACE( "matched type %p in tryblock %d catchblock %d\n", type, i, j );
@@ -491,6 +492,62 @@ static inline void call_catch_block( PEXCEPTION_RECORD rec, cxx_exception_frame
     }
 }
 
+/*********************************************************************
+ *		__CxxExceptionFilter (MSVCRT.@)
+ */
+int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs,
+                                const type_info *ti, int flags, void **copy)
+{
+    const cxx_type_info *type;
+    PEXCEPTION_RECORD rec;
+
+    TRACE( "%p %p %x %p\n", ptrs, ti, flags, copy );
+
+    if (!ptrs) return EXCEPTION_CONTINUE_SEARCH;
+
+    /* handle catch(...) */
+    if (!ti) return EXCEPTION_EXECUTE_HANDLER;
+
+    rec = ptrs->ExceptionRecord;
+    if (rec->ExceptionCode != CXX_EXCEPTION || rec->NumberParameters != 3 ||
+            rec->ExceptionInformation[0] < CXX_FRAME_MAGIC_VC6 ||
+            rec->ExceptionInformation[0] > CXX_FRAME_MAGIC_VC8)
+        return EXCEPTION_CONTINUE_SEARCH;
+
+    if (rec->ExceptionInformation[1] == 0 && rec->ExceptionInformation[2] == 0)
+    {
+        rec = msvcrt_get_thread_data()->exc_record;
+        if (!rec) return EXCEPTION_CONTINUE_SEARCH;
+    }
+
+    type = find_caught_type( (cxx_exception_type*)rec->ExceptionInformation[2], ti, flags );
+    if (!type) return EXCEPTION_CONTINUE_SEARCH;
+
+    if (copy)
+    {
+        void *object = (void *)rec->ExceptionInformation[1];
+
+        if (flags & TYPE_FLAG_REFERENCE)
+        {
+            *copy = get_this_pointer( &type->offsets, object );
+        }
+        else if (type->flags & CLASS_IS_SIMPLE_TYPE)
+        {
+            memmove( copy, object, type->size );
+            /* if it is a pointer, adjust it */
+            if (type->size == sizeof(void*)) *copy = get_this_pointer( &type->offsets, *copy );
+        }
+        else  /* copy the object */
+        {
+            if (type->copy_ctor)
+                call_copy_ctor( type->copy_ctor, copy, get_this_pointer(&type->offsets,object),
+                        (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS) );
+            else
+                memmove( copy, get_this_pointer(&type->offsets,object), type->size );
+        }
+    }
+    return EXCEPTION_EXECUTE_HANDLER;
+}
 
 /*********************************************************************
  *		cxx_frame_handler
diff --git a/dlls/msvcrt/except_x86_64.c b/dlls/msvcrt/except_x86_64.c
index e2d2402..27d0a15 100644
--- a/dlls/msvcrt/except_x86_64.c
+++ b/dlls/msvcrt/except_x86_64.c
@@ -61,6 +61,15 @@ typedef struct _DISPATCHER_CONTEXT
     ULONG                 ScopeIndex;
 } DISPATCHER_CONTEXT;
 
+/*********************************************************************
+ *		__CxxExceptionFilter (MSVCRT.@)
+ */
+int CDECL __CxxExceptionFilter( PEXCEPTION_POINTERS ptrs,
+                                const type_info *ti, int flags, void **copy )
+{
+    FIXME( "%p %p %x %p: not implemented\n", ptrs, ti, flags, copy );
+    return EXCEPTION_CONTINUE_SEARCH;
+}
 
 /*********************************************************************
  *		__CxxFrameHandler (MSVCRT.@)
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 3bd47d2..bd854a4 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -178,7 +178,7 @@
 # stub __CxxCallUnwindDtor
 # stub __CxxCallUnwindVecDtor
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-# stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) __CxxFrameHandler
diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec
index 5623107..58c5ee3 100644
--- a/dlls/ucrtbase/ucrtbase.spec
+++ b/dlls/ucrtbase/ucrtbase.spec
@@ -50,7 +50,7 @@
 @ stub __BuildCatchObjectHelper
 @ stdcall -arch=x86_64 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler
 @ cdecl -arch=i386,x86_64,arm __CxxDetectRethrow(ptr)
-@ stub __CxxExceptionFilter
+@ cdecl -arch=i386,x86_64,arm __CxxExceptionFilter(ptr ptr long ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler(ptr ptr ptr ptr)
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler2(ptr ptr ptr ptr) __CxxFrameHandler
 @ cdecl -arch=i386,x86_64,arm -norelay __CxxFrameHandler3(ptr ptr ptr ptr) __CxxFrameHandler