From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/cppexcept.h | 1 + dlls/msvcrt/except.c | 20 +++++---- dlls/ucrtbase/tests/cpp.c | 85 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 7 deletions(-)
diff --git a/dlls/msvcrt/cppexcept.h b/dlls/msvcrt/cppexcept.h index 3070884000f..2bd2e2f9c62 100644 --- a/dlls/msvcrt/cppexcept.h +++ b/dlls/msvcrt/cppexcept.h @@ -136,6 +136,7 @@ typedef struct #define TYPE_FLAG_CONST 1 #define TYPE_FLAG_VOLATILE 2 #define TYPE_FLAG_REFERENCE 8 +#define TYPE_FLAG_IUNKNOWN 16
void WINAPI DECLSPEC_NORETURN _CxxThrowException(void*,const cxx_exception_type*);
diff --git a/dlls/msvcrt/except.c b/dlls/msvcrt/except.c index cdb9a58822d..bed1df0276e 100644 --- a/dlls/msvcrt/except.c +++ b/dlls/msvcrt/except.c @@ -26,6 +26,8 @@ #include <stdarg.h> #include <stdbool.h>
+#define COBJMACROS + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -33,6 +35,7 @@ #include "winternl.h" #include "msvcrt.h" #include "excpt.h" +#include "unknwn.h" #include "wincon.h" #include "wine/exception.h" #include "wine/debug.h" @@ -949,17 +952,20 @@ BOOL __cdecl _IsExceptionObjectToBeDestroyed(const void *obj) */ void CDECL __DestructExceptionObject(EXCEPTION_RECORD *rec) { - cxx_exception_type *info = (cxx_exception_type*) rec->ExceptionInformation[2]; - void *object = (void*)rec->ExceptionInformation[1]; + cxx_exception_type *info; + void *object;
TRACE("(%p)\n", rec);
- if (!is_cxx_exception( rec )) return; - - if (!info || !info->destructor) - return; + if (!rec || !is_cxx_exception( rec )) return; + info = (cxx_exception_type*)rec->ExceptionInformation[2]; + if (!info) return; + object = (void*)rec->ExceptionInformation[1];
- call_dtor( cxx_rva( info->destructor, rec->ExceptionInformation[3] ), object ); + if (info->destructor) + call_dtor( cxx_rva( info->destructor, rec->ExceptionInformation[3] ), object ); + else if (info->flags & TYPE_FLAG_IUNKNOWN && *(IUnknown**)object) + IUnknown_Release( *(IUnknown**)object ); }
/********************************************************************* diff --git a/dlls/ucrtbase/tests/cpp.c b/dlls/ucrtbase/tests/cpp.c index 5e62aafa1a8..da06b2cbf2f 100644 --- a/dlls/ucrtbase/tests/cpp.c +++ b/dlls/ucrtbase/tests/cpp.c @@ -26,8 +26,35 @@ #include <winbase.h> #include <verrsrc.h> #include <dbghelp.h> +#include <unknwn.h> #include "wine/test.h"
+#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +DEFINE_EXPECT(iunknown_except_Release); + typedef unsigned char MSVCRT_bool;
typedef struct { @@ -47,6 +74,8 @@ typedef struct _type_info_list char name[1]; } type_info_list;
+void CDECL __DestructExceptionObject(EXCEPTION_RECORD*); + static void* (CDECL *p_malloc)(size_t); static void (CDECL *p___std_exception_copy)(const __std_exception_data*, __std_exception_data*); static void (CDECL *p___std_exception_destroy)(__std_exception_data*); @@ -239,10 +268,66 @@ static void test___unDName(void) } }
+static HRESULT WINAPI iunknown_except_QueryInterface(IUnknown *iface, + REFIID riid, void**ppv) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static ULONG WINAPI iunknown_except_AddRef(IUnknown *iface) +{ + ok(0, "unexpected call\n"); + return 2; +} + +static ULONG WINAPI iunknown_except_Release(IUnknown *iface) +{ + CHECK_EXPECT(iunknown_except_Release); + return 1; +} + +static IUnknownVtbl iunknown_except_vtbl = { + iunknown_except_QueryInterface, + iunknown_except_AddRef, + iunknown_except_Release +}; + +static IUnknown iunknown_except = { &iunknown_except_vtbl }; + +static void test___DestructExceptionObject(void) +{ + IUnknown *piunk = &iunknown_except; + EXCEPTION_RECORD rec; + struct + { + UINT flags; + UINT arch_specific_data[8]; + } info = { 0x10 }; + + __DestructExceptionObject(NULL); + + memset(&rec, 0, sizeof(rec)); + rec.ExceptionCode = 0xe06d7363; +#ifdef __i386__ + rec.NumberParameters = 3; +#else + rec.NumberParameters = 4; +#endif + rec.ExceptionInformation[0] = 0x19930520; + rec.ExceptionInformation[1] = (ULONG_PTR)&piunk; + rec.ExceptionInformation[2] = (ULONG_PTR)&info; + rec.ExceptionInformation[3] = (ULONG_PTR)GetModuleHandleA(NULL); + SET_EXPECT(iunknown_except_Release); + __DestructExceptionObject(&rec); + CHECK_CALLED(iunknown_except_Release); +} + START_TEST(cpp) { if (!init()) return; test___std_exception(); test___std_type_info(); test___unDName(); + test___DestructExceptionObject(); }