From: Piotr Caban piotr@codeweavers.com
--- dlls/vccorlib140/cxx.h | 38 ++++++++++++++++++-- dlls/vccorlib140/except.c | 58 ++++++++++++++++++++++++------- dlls/vccorlib140/tests/vccorlib.c | 2 +- 3 files changed, 81 insertions(+), 17 deletions(-)
diff --git a/dlls/vccorlib140/cxx.h b/dlls/vccorlib140/cxx.h index a114b5fc07a..1834f77f03e 100644 --- a/dlls/vccorlib140/cxx.h +++ b/dlls/vccorlib140/cxx.h @@ -180,7 +180,13 @@ static const cxx_type_info_table type ## _cxx_type_table = \ static const cxx_exception_type type ## _exception_type = \ { TYPE_FLAG_WINRT, NULL, NULL, & type ## _cxx_type_table };
-#define INIT_CXX_TYPE(name,base) (void)name ## _exception_type +#define DEFINE_CXX_BASE(type, flags, off, mangled_name) \ +static type_info type ## _type_info = { &type_info_vtable, NULL, mangled_name }; \ +static const cxx_type_info type ## _cxx_type_info[1] = \ + { { flags, &type ##_type_info, { off, -1, 0 }, sizeof(void*), NULL } }; + +#define INIT_CXX_TYPE(name,base) /* nothing to do */ +#define INIT_CXX_BASE(name,base) /* nothing to do */
#elif defined __WINE_PE_BUILD
@@ -208,7 +214,22 @@ void __asm_dummy_ ## type ## _exception_type(void) \ #define DEFINE_CXX_TYPE(type, ...) \ DEFINE_CXX_TYPE2(type, type ## _cxx_type_info, ##__VA_ARGS__)
+#define DEFINE_CXX_BASE(type, flags, off, mangled_name) \ +type_info type ## _type_info = { &type_info_vtable, NULL, mangled_name }; \ +extern const cxx_type_info type ## _cxx_type_info[1]; \ +void __asm_dummy_ ## type ## _exception_type(void) \ +{\ + asm( ".balign 4\n\t" \ + __ASM_GLOBL(#type "_cxx_type_info") "\n\t" \ + ".long %c0\n\t" \ + ".rva " #type "_type_info\n\t" \ + ".long %c1, -1, 0, %c2\n\t" \ + ".long 0\n\t" \ + :: "i"(flags), "i"(off), "i"(sizeof(void *)) ); \ +} + #define INIT_CXX_TYPE(name,base) /* nothing to do */ +#define INIT_CXX_BASE(name,base) /* nothing to do */
#else /* CXX_USE_RVA */
@@ -228,7 +249,18 @@ static void init_ ## type ## _cxx(char *base) \ type ## _exception_type.type_info_table = (char *)&type ## _cxx_type_table - base; \ }
+#define DEFINE_CXX_BASE(type, flags, off, mangled_name) \ +static type_info type ## _type_info = { &type_info_vtable, NULL, mangled_name }; \ +static cxx_type_info type ## _cxx_type_info[1] = \ + { { flags, 0xdeadbeef, { off, -1, 0 }, sizeof(void *), 0 } }; \ +\ +static void init_ ## type ## _cxx_base(char *base) \ +{ \ + type ## _cxx_type_info[0].type_info = (char *)&type ## _type_info - base; \ +} + #define INIT_CXX_TYPE(name,base) init_ ## name ## _cxx((void *)(base)) +#define INIT_CXX_BASE(name,base) init_ ## name ## _cxx_base((void *)(base))
#endif /* CXX_USE_RVA */
@@ -364,7 +396,7 @@ typedef struct typedef struct { UINT count; - const cxx_type_info *info[5]; + const cxx_type_info *info[10]; } cxx_type_info_table;
typedef struct @@ -389,7 +421,7 @@ typedef struct typedef struct { UINT count; - unsigned int info[5]; + unsigned int info[10]; } cxx_type_info_table;
typedef struct diff --git a/dlls/vccorlib140/except.c b/dlls/vccorlib140/except.c index 89d21f25aac..e8b65d47237 100644 --- a/dlls/vccorlib140/except.c +++ b/dlls/vccorlib140/except.c @@ -37,11 +37,14 @@ extern void WINAPI DECLSPEC_NORETURN _CxxThrowException(void *, const cxx_except extern const void **__cdecl __current_exception(void);
#ifdef _WIN64 -#define EXCEPTION_REF_NAME(name) ".PE$AAV" #name "Exception@Platform@@" +#define REF_NAME(name) ".PE" name #else -#define EXCEPTION_REF_NAME(name) ".P$AAV" #name "Exception@Platform@@" +#define REF_NAME(name) ".P" name #endif
+#define CLASS_REF_NAME(name) REF_NAME("$AAV" name "@Platform@@") +#define INTERFACE_REF_NAME(name) REF_NAME("$AAU" name "@Platform@@") + /* Data members of the "Exception" C++/CX class. * A back-pointer to this struct is stored just before the IInspectable vtable of an Exception object. * TODO: The message fields are likely obtained from IRestrictedErrorInfo::GetErrorDetails, so we @@ -201,9 +204,24 @@ static HRESULT WINAPI Exception_GetTrustLevel(IInspectable *iface, TrustLevel *l return E_NOTIMPL; }
-DEFINE_RTTI_DATA(Exception_ref, 0, EXCEPTION_REF_NAME()); +DEFINE_CXX_BASE(Exception_void_ref, CLASS_IS_SIMPLE_TYPE, + 0, REF_NAME("AX")); +DEFINE_CXX_BASE(Exception_IClosable_ref, CLASS_IS_SIMPLE_TYPE | CLASS_IS_WINRT, + offsetof(struct Exception, IClosable_iface), INTERFACE_REF_NAME("IDisposable")); +DEFINE_CXX_BASE(Exception_IEquatable_ref, CLASS_IS_SIMPLE_TYPE | CLASS_IS_WINRT, + offsetof(struct Exception, IEquatable_iface), INTERFACE_REF_NAME("IEquatable")); +DEFINE_CXX_BASE(Exception_IPrintable_ref, CLASS_IS_SIMPLE_TYPE | CLASS_IS_WINRT, + offsetof(struct Exception, IPrintable_iface), INTERFACE_REF_NAME("IPrintable")); +DEFINE_CXX_BASE(Exception_Object_ref, CLASS_IS_SIMPLE_TYPE | CLASS_IS_WINRT, + 0, CLASS_REF_NAME("Object")); +type_info Exception_ref_type_info = { &type_info_vtable, NULL, CLASS_REF_NAME("Exception") }; typedef struct Exception *Exception_ref; -DEFINE_CXX_TYPE(Exception_ref); +DEFINE_CXX_TYPE(Exception_ref, + Exception_Object_ref_cxx_type_info, + Exception_IPrintable_ref_cxx_type_info, + Exception_IEquatable_ref_cxx_type_info, + Exception_IClosable_ref_cxx_type_info, + Exception_void_ref_cxx_type_info);
DEFINE_RTTI_BASE(Exception_IClosable, offsetof(struct Exception, IClosable_iface), 1, ".?AUIDisposable@Platform@@"); @@ -314,9 +332,15 @@ struct Exception *__cdecl Exception_hstring_ctor(struct Exception *this, HRESULT return this; }
-DEFINE_RTTI_DATA(COMException_ref, 0, EXCEPTION_REF_NAME(COM), Exception_ref_rtti_base_descriptor); +type_info COMException_ref_type_info = { &type_info_vtable, NULL, CLASS_REF_NAME("COMException") }; typedef struct Exception *COMException_ref; -DEFINE_CXX_TYPE(COMException_ref, Exception_ref_cxx_type_info); +DEFINE_CXX_TYPE(COMException_ref, + Exception_ref_cxx_type_info, + Exception_Object_ref_cxx_type_info, + Exception_IPrintable_ref_cxx_type_info, + Exception_IEquatable_ref_cxx_type_info, + Exception_IClosable_ref_cxx_type_info, + Exception_void_ref_cxx_type_info);
DEFINE_RTTI_DATA(COMException, 0, ".?AVCOMException@Platform@@", Exception_rtti_base_descriptor, @@ -375,11 +399,17 @@ struct Exception *__cdecl COMException_hstring_ctor(struct Exception *this, HRES }
#define WINRT_EXCEPTION(name, hr) \ - DEFINE_RTTI_DATA(name##Exception_ref, 0, EXCEPTION_REF_NAME(name), \ - COMException_ref_rtti_base_descriptor, Exception_ref_rtti_base_descriptor); \ + type_info name ## Exception_ref ## _type_info = \ + { &type_info_vtable, NULL, CLASS_REF_NAME(#name "Exception") }; \ typedef COMException_ref name##Exception_ref; \ - DEFINE_CXX_TYPE(name##Exception_ref, COMException_ref_cxx_type_info, \ - Exception_ref_cxx_type_info); \ + DEFINE_CXX_TYPE(name##Exception_ref, \ + COMException_ref_cxx_type_info, \ + Exception_ref_cxx_type_info, \ + Exception_Object_ref_cxx_type_info, \ + Exception_IPrintable_ref_cxx_type_info, \ + Exception_IEquatable_ref_cxx_type_info, \ + Exception_IClosable_ref_cxx_type_info, \ + Exception_void_ref_cxx_type_info); \ \ DEFINE_RTTI_DATA(name##Exception, 0, ".?AV" #name "Exception@Platform@@", \ COMException_rtti_base_descriptor, \ @@ -534,7 +564,11 @@ HSTRING __cdecl Exception_get_Message(struct Exception *this)
void init_exception(void *base) { - INIT_RTTI(Exception_ref, base); + INIT_CXX_BASE(Exception_void_ref, base); + INIT_CXX_BASE(Exception_IClosable_ref, base); + INIT_CXX_BASE(Exception_IEquatable_ref, base); + INIT_CXX_BASE(Exception_IPrintable_ref, base); + INIT_CXX_BASE(Exception_Object_ref, base); INIT_CXX_TYPE(Exception_ref, base); INIT_RTTI_BASE(Exception_IClosable, base); INIT_RTTI_BASE(Exception_IEquatable, base); @@ -543,13 +577,11 @@ void init_exception(void *base) INIT_RTTI(Exception, base); INIT_RTTI(Exception_Closable, base);
- INIT_RTTI(COMException_ref, base); INIT_CXX_TYPE(COMException_ref, base); INIT_RTTI(COMException, base); INIT_RTTI(COMException_Closable, base);
#define WINRT_EXCEPTION(name, hr) \ - INIT_RTTI(name##Exception_ref, base); \ INIT_CXX_TYPE(name##Exception_ref, base); \ INIT_RTTI(name##Exception, base); \ INIT_RTTI(name##Exception_Closable, base); diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index c4f669d8190..03ded3fafcb 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -1509,7 +1509,7 @@ static void test_exceptions(void)
cxx_info = (cxx_type_info *)(base + type_info_table->info[j]); if (j == type_info_table->count - 1) - todo_wine ok(cxx_info->flags == CLASS_IS_SIMPLE_TYPE, "got flags %u\n", cxx_info->flags); + ok(cxx_info->flags == CLASS_IS_SIMPLE_TYPE, "got flags %u\n", cxx_info->flags); else ok(cxx_info->flags == (CLASS_IS_SIMPLE_TYPE | CLASS_IS_IUNKNOWN), "got flags %u\n", cxx_info->flags); ok(cxx_info->size == sizeof(void *), "got size %u\n", cxx_info->size);