-- v7: vccorlib140: Implement __abi_translateCurrentException. vccorlib140: Implement Platform::Exception. vccorlib140: Implement AllocateException(WithWeakRef), FreeException. vccorlib140: Add stubs for Exception constructors.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/tests/Makefile.in | 2 +- dlls/vccorlib140/tests/vccorlib.c | 424 ++++++++++++++++++++++++++++- dlls/vccorlib140/vccorlib.c | 66 +++++ dlls/vccorlib140/vccorlib140.spec | 99 +++---- 4 files changed, 529 insertions(+), 62 deletions(-)
diff --git a/dlls/vccorlib140/tests/Makefile.in b/dlls/vccorlib140/tests/Makefile.in index 9d20ff64424..7d19fceb468 100644 --- a/dlls/vccorlib140/tests/Makefile.in +++ b/dlls/vccorlib140/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = vccorlib140.dll -IMPORTS = combase ole32 uuid +IMPORTS = combase ole32 oleaut32 uuid
SOURCES = \ vccorlib.c diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index 1b597a9325a..d6180578fbe 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -22,11 +22,13 @@ #define COBJMACROS
#include <stdbool.h> +#include <stdint.h>
#include "initguid.h" #include "activation.h" #include "objbase.h" #include "weakreference.h" +#include "restrictederrorinfo.h" #define WIDL_using_Windows_Foundation #include "windows.foundation.h" #include "winstring.h" @@ -110,6 +112,22 @@ DEFINE_EXPECT(PostInitialize); DEFINE_EXPECT(PreUninitialize); DEFINE_EXPECT(PostUninitialize);
+#define WINRT_EXCEPTIONS \ + WINRT_EXCEPTION(AccessDenied, E_ACCESSDENIED) \ + WINRT_EXCEPTION(ChangedState, E_CHANGED_STATE) \ + WINRT_EXCEPTION(ClassNotRegistered, REGDB_E_CLASSNOTREG) \ + WINRT_EXCEPTION(Disconnected, RPC_E_DISCONNECTED) \ + WINRT_EXCEPTION(Failure, E_FAIL) \ + WINRT_EXCEPTION(InvalidArgument, E_INVALIDARG) \ + WINRT_EXCEPTION(InvalidCast, E_NOINTERFACE) \ + WINRT_EXCEPTION(NotImplemented, E_NOTIMPL) \ + WINRT_EXCEPTION(NullReference, E_POINTER) \ + WINRT_EXCEPTION(ObjectDisposed, RO_E_CLOSED) \ + WINRT_EXCEPTION(OperationCanceled, E_ABORT) \ + WINRT_EXCEPTION(OutOfBounds, E_BOUNDS) \ + WINRT_EXCEPTION(OutOfMemory, E_OUTOFMEMORY) \ + WINRT_EXCEPTION(WrongThread, RPC_E_WRONG_THREAD) + struct __abi_type_descriptor { const WCHAR *name; @@ -130,6 +148,12 @@ static int (__cdecl *p_platform_type_GetTypeCode)(void *); static HSTRING (__cdecl *p_platform_type_ToString)(void *); static HSTRING (__cdecl *p_platform_type_get_FullName)(void *); static void *(WINAPI *pCreateValue)(int type, const void *); +static void *(__cdecl *pCreateException)(HRESULT); +static void *(__cdecl *pCreateExceptionWithMessage)(HRESULT, HSTRING); +static HSTRING (__cdecl *p_platform_exception_get_Message)(void *); +static void *(__cdecl *pAllocateException)(size_t); +static void *(__cdecl *pAllocateExceptionWithWeakRef)(ptrdiff_t, size_t); +static void (__cdecl *pFreeException)(void *);
static void *(__cdecl *p__RTtypeid)(const void *); static const char *(__thiscall *p_type_info_name)(void *); @@ -137,11 +161,13 @@ static const char *(__thiscall *p_type_info_raw_name)(void *); static int (__thiscall *p_type_info_opequals_equals)(void *, void *); static int (__thiscall *p_type_info_opnot_equals)(void *, void *);
+static HMODULE hmod; + static BOOL init(void) { - HMODULE hmod = LoadLibraryA("vccorlib140.dll"); HMODULE msvcrt = LoadLibraryA("msvcrt.dll");
+ hmod = LoadLibraryA("vccorlib140.dll"); if (!hmod) { win_skip("vccorlib140.dll not available\n"); @@ -173,6 +199,15 @@ static BOOL init(void) p_platform_type_ToString = (void *)GetProcAddress(hmod, "?ToString@Type@Platform@@U$AAAP$AAVString@2@XZ"); p_platform_type_get_FullName = (void *)GetProcAddress(hmod, "?get@FullName@Type@Platform@@Q$AAAP$AAVString@3@XZ"); pCreateValue = (void *)GetProcAddress(hmod, "?CreateValue@Details@Platform@@YAP$AAVObject@2@W4TypeCode@2@PBX@Z"); + pCreateException = (void *)GetProcAddress(hmod, "?CreateException@Exception@Platform@@SAP$AAV12@H@Z"); + pCreateExceptionWithMessage = (void *)GetProcAddress(hmod, + "?CreateException@Exception@Platform@@SAP$AAV12@HP$AAVString@2@@Z"); + p_platform_exception_get_Message = (void *)GetProcAddress(hmod, + "?get@Message@Exception@Platform@@Q$AAAP$AAVString@3@XZ"); + pAllocateException = (void *)GetProcAddress(hmod, "?AllocateException@Heap@Details@Platform@@SAPAXI@Z"); + pAllocateExceptionWithWeakRef = (void *)GetProcAddress(hmod, + "?AllocateException@Heap@Details@Platform@@SAPAXII@Z"); + pFreeException = (void *)GetProcAddress(hmod, "?FreeException@Heap@Details@Platform@@SAXPAX@Z"); p_type_info_name = (void *)GetProcAddress(msvcrt, "?name@type_info@@QBAPBDXZ"); p_type_info_raw_name = (void *)GetProcAddress(msvcrt, "?raw_name@type_info@@QBAPBDXZ"); p_type_info_opequals_equals = (void *)GetProcAddress(msvcrt, "??8type_info@@QBAHABV0@@Z"); @@ -198,6 +233,16 @@ static BOOL init(void) "?get@FullName@Type@Platform@@QE$AAAPE$AAVString@3@XZ"); pCreateValue = (void *)GetProcAddress(hmod, "?CreateValue@Details@Platform@@YAPE$AAVObject@2@W4TypeCode@2@PEBX@Z"); + pCreateException = (void *)GetProcAddress(hmod, + "?CreateException@Exception@Platform@@SAPE$AAV12@H@Z"); + pCreateExceptionWithMessage = (void *)GetProcAddress(hmod, + "?CreateException@Exception@Platform@@SAPE$AAV12@HPE$AAVString@2@@Z"); + p_platform_exception_get_Message = (void *)GetProcAddress(hmod, + "?get@Message@Exception@Platform@@QE$AAAPE$AAVString@3@XZ"); + pAllocateException = (void *)GetProcAddress(hmod, "?AllocateException@Heap@Details@Platform@@SAPEAX_K@Z"); + pAllocateExceptionWithWeakRef = (void *)GetProcAddress(hmod, + "?AllocateException@Heap@Details@Platform@@SAPEAX_K0@Z"); + pFreeException = (void *)GetProcAddress(hmod, "?FreeException@Heap@Details@Platform@@SAXPEAX@Z"); p_type_info_name = (void *)GetProcAddress(msvcrt, "?name@type_info@@QEBAPEBDXZ"); p_type_info_raw_name = (void *)GetProcAddress(msvcrt, "?raw_name@type_info@@QEBAPEBDXZ"); p_type_info_opequals_equals = (void *)GetProcAddress(msvcrt, "??8type_info@@QEBAHAEBV0@@Z"); @@ -222,6 +267,16 @@ static BOOL init(void) "?get@FullName@Type@Platform@@Q$AAAP$AAVString@3@XZ"); pCreateValue = (void *)GetProcAddress(hmod, "?CreateValue@Details@Platform@@YGP$AAVObject@2@W4TypeCode@2@PBX@Z"); + pCreateException = (void *)GetProcAddress(hmod, + "?CreateException@Exception@Platform@@SAP$AAV12@H@Z"); + pCreateExceptionWithMessage = (void *)GetProcAddress(hmod, + "?CreateException@Exception@Platform@@SAP$AAV12@HP$AAVString@2@@Z"); + p_platform_exception_get_Message = (void *)GetProcAddress(hmod, + "?get@Message@Exception@Platform@@Q$AAAP$AAVString@3@XZ"); + pAllocateException = (void *)GetProcAddress(hmod, "?AllocateException@Heap@Details@Platform@@SAPAXI@Z"); + pAllocateExceptionWithWeakRef = (void *)GetProcAddress(hmod, + "?AllocateException@Heap@Details@Platform@@SAPAXII@Z"); + pFreeException = (void *)GetProcAddress(hmod, "?FreeException@Heap@Details@Platform@@SAXPAX@Z"); p_type_info_name = (void *)GetProcAddress(msvcrt, "?name@type_info@@QBEPBDXZ"); p_type_info_raw_name = (void *)GetProcAddress(msvcrt, "?raw_name@type_info@@QBEPBDXZ"); p_type_info_opequals_equals = (void *)GetProcAddress(msvcrt, "??8type_info@@QBEHABV0@@Z"); @@ -240,6 +295,12 @@ static BOOL init(void) ok(p_platform_type_ToString != NULL, "Platform::Type::ToString not available\n"); ok(p_platform_type_get_FullName != NULL, "Platform::Type::FullName not available\n"); ok(pCreateValue != NULL, "CreateValue not available\n"); + ok(pCreateException != NULL, "CreateException not available\n"); + ok(pCreateExceptionWithMessage != NULL, "CreateExceptionWithMessage not available\n"); + ok(p_platform_exception_get_Message != NULL, "Platform::Exception::Message::get not available\n"); + ok(pAllocateException != NULL, "AllocateException not available\n"); + ok(pAllocateExceptionWithWeakRef != NULL, "AllocateExceptionWithWeakRef not available.\n"); + ok(pFreeException != NULL, "FreeException not available\n");
ok(p_type_info_name != NULL, "type_info::name not available\n"); ok(p_type_info_raw_name != NULL, "type_info::raw_name not available\n"); @@ -444,7 +505,7 @@ static void test_GetIidsFn(void)
static void test_Allocate(void) { - void *addr; + void *addr, **ptr, **base;
addr = pAllocate(0); ok(!!addr, "got addr %p\n", addr); @@ -454,6 +515,35 @@ static void test_Allocate(void) ok(!!addr, "got addr %p\n", addr); pFree(addr); pFree(NULL); + + /* AllocateException allocates additional space for two pointer-width fields, with the second field used as the + * back-pointer to the exception data. */ + addr = pAllocateException(0); + todo_wine ok(!!addr, "got addr %p\n", addr); + if (!addr) return; + ptr = (void **)((ULONG_PTR)addr - sizeof(void *)); + *ptr = NULL; /* The write should succeed. */ + base = (void **)((ULONG_PTR)addr - 2 * sizeof(void *)); + *base = NULL; + /* Since base is the actual allocation base, Free(base) should succeed. */ + pFree(base); + + addr = pAllocateException(sizeof(void *)); + ok(!!addr, "got addr %p\n", addr); + ptr = (void **)((ULONG_PTR)addr - sizeof(void *)); + *ptr = NULL; + base = (void **)((ULONG_PTR)addr - 2 * sizeof(void *)); + *base = NULL; + /* FreeException will derive the allocation base itself. */ + pFreeException(addr); + + /* Do what AllocateException does, manually. */ + base = pAllocate(sizeof(void *) * 2 + sizeof(UINT32)); + ok(!!base, "got base %p\n", base); + /* addr is what AllocateException would return. */ + addr = (void *)((ULONG_PTR)base + sizeof(void *) * 2); + /* FreeException should succeed with addr. */ + pFreeException(addr); }
#define test_refcount(a, b) test_refcount_(__LINE__, (a), (b)) @@ -473,7 +563,8 @@ struct control_block LONG ref_strong; IUnknown *object; bool is_inline; - UINT16 unknown; + UINT8 unknown; + bool is_exception; #ifdef _WIN32 char _padding[4]; #endif @@ -606,7 +697,8 @@ static void test_AllocateWithWeakRef_inline(void) ok(object->weakref->ref_strong == 1, "got ref_strong %lu\n", object->weakref->ref_strong); ok(object->weakref->object == &object->IUnknown_iface, "got object %p != %p\n", object->weakref->object, &object->IUnknown_iface); - ok(object->weakref->unknown == 0, "got unknown %d\n", object->weakref->unknown); + todo_wine ok(object->weakref->unknown == 0, "got unknown %d\n", object->weakref->unknown); + ok(!object->weakref->is_exception, "got is_exception %d\n", object->weakref->is_exception); /* The object is allocate within the weakref. */ ok((char *)object->weakref == ((char *)object - sizeof(struct control_block)), "got %p != %p\n", object->weakref, (char *)object - sizeof(struct control_block)); @@ -664,6 +756,49 @@ static void test_AllocateWithWeakRef(void) ok(object->weakref->object == &object->IUnknown_iface, "got object %p != %p\n", object->weakref->object, &object->IUnknown_iface); ok(object->weakref->unknown == 0, "got unknown %d\n", object->weakref->unknown); + ok(!object->weakref->is_exception, "got is_exception %d\n", object->weakref->is_exception); + + hr = IWeakReference_Resolve(weakref, &IID_IAgileObject, (IInspectable **)&out); + ok(hr == S_OK, "got hr %#lx\n", hr); + test_refcount(&object->IUnknown_iface, 2); + IUnknown_Release(out); + + call_func1(pReleaseTarget, object->weakref); + hr = IWeakReference_Resolve(weakref, &IID_IAgileObject, (IInspectable **)&out); + ok(hr == S_OK, "got hr %#lx\n", hr); + test_refcount(&object->IUnknown_iface, 2); + IUnknown_Release(out); + + count = IWeakReference_AddRef(weakref); + ok(count == 2, "got count %lu\n", count); + + count = IUnknown_Release(&object->IUnknown_iface); + ok(count == 0, "got count %lu\n", count); + test_refcount(weakref, 1); + out = (IUnknown *)0xdeadbeef; + hr = IWeakReference_Resolve(weakref, &IID_IAgileObject, (IInspectable **)&out); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(out == (IUnknown *)0xdeadbeef, "got out %p\n", out); + count = IWeakReference_Release(weakref); + ok(count == 0, "got count %lu\n", count); + + /* AllocateExceptionWithWeakRef will not store the control block inline, regardless of the size. */ + object = pAllocateExceptionWithWeakRef(offsetof(struct unknown_impl, weakref), sizeof(struct unknown_impl)); + todo_wine ok(object != NULL, "got object %p\n", object); + if (!object) return; + + object->strong_ref_free_val = -100; + ok(object->weakref != NULL, "got weakref %p\n", object->weakref); + object->IUnknown_iface.lpVtbl = &unknown_impl_vtbl; + weakref = &object->weakref->IWeakReference_iface; + + test_refcount(weakref, 1); + ok(!object->weakref->is_inline, "got is_inline %d\n", object->weakref->is_inline); + ok(object->weakref->ref_strong == 1, "got ref_strong %lu\n", object->weakref->ref_strong); + ok(object->weakref->object == &object->IUnknown_iface, "got object %p != %p\n", object->weakref->object, + &object->IUnknown_iface); + ok(object->weakref->unknown == 0, "got unknown %d\n", object->weakref->unknown); + ok(object->weakref->is_exception, "got is_exception %d\n", object->weakref->is_exception);
hr = IWeakReference_Resolve(weakref, &IID_IAgileObject, (IInspectable **)&out); ok(hr == S_OK, "got hr %#lx\n", hr); @@ -1020,6 +1155,286 @@ static void test_CreateValue(void) pUninitializeData(0); }
+typedef struct __type_info +{ + const void *vtable; + char *name; + char mangled[128]; +} rtti_type_info; +typedef struct +{ + UINT flags; + unsigned int type_info; + DWORD offsets[3]; + unsigned int size; + unsigned int copy_ctor; +} cxx_type_info; +typedef struct +{ + UINT count; + unsigned int info[1]; +} cxx_type_info_table; +typedef struct +{ + UINT flags; + unsigned int destructor; + unsigned int custom_handler; + unsigned int type_info_table; +} cxx_exception_type; + +struct exception_inner +{ + /* This only gets set when the exception is thrown. */ + BSTR message1; + /* Likewise, but can also be set by CreateExceptionWithMessage. */ + BSTR message2; + void *unknown1; + void *unknown2; + HRESULT hr; + /* Only gets set when the exception is thrown. */ + IRestrictedErrorInfo *error_info; + const cxx_exception_type *exception_type; + UINT32 unknown3; + void *unknown4; +}; + +struct platform_exception +{ + IInspectable IInspectable_iface; + const void *IPrintable_iface; + const void *IEquatable_iface; + IClosable IClosable_iface; + struct exception_inner inner; + /* Exceptions use the weakref control block for reference counting, even though they don't implement + * IWeakReferenceSource. */ + struct control_block *control_block; + /* This is lazily initialized, i.e, only when QueryInterface(IID_IMarshal) gets called. The default value is + * UINTPTR_MAX/-1 */ + IUnknown *marshal; +}; + +static void test_interface_layout_(int line, IUnknown *iface, const GUID *iid, const void *exp_ptr) +{ + IUnknown *out = NULL; + HRESULT hr; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&out); + ok_(__FILE__, line)(hr == S_OK, "got hr %#lx\n", hr); + if (SUCCEEDED(hr)) + { + ok_(__FILE__, line)((ULONG_PTR)out == (ULONG_PTR)exp_ptr, "got out %p != %p\n", out, exp_ptr); + IUnknown_Release(out); + } +} +#define test_interface_layout(iface, iid, exp_ptr) test_interface_layout_(__LINE__, (IUnknown *)(iface), iid, exp_ptr) + +static void test_exceptions(void) +{ +#define EXCEPTION_RTTI_NAME(name) (sizeof(void *) == 8) ? ".PE$AAV" #name "Exception@Platform@@" : ".P$AAV" #name "Exception@Platform@@" +#define WINRT_EXCEPTION(name, hr) \ + {hr, L"Platform." #name "Exception", ".?AV" #name "Exception@Platform@@", "class Platform::" #name "Exception", EXCEPTION_RTTI_NAME(name)}, + const struct exception_test_case + { + HRESULT hr; + const WCHAR *exp_winrt_name; + const char *exp_rtti_mangled_name; + const char *exp_rtti_name; + /* The mangled RTTI name of the cxx_exception_type received by the exception handler/filter. */ + const char *exp_exception_rtti_mangled_name; + } test_cases[] = { + WINRT_EXCEPTIONS + /* Generic exceptions */ + {E_HANDLE, L"Platform.COMException", ".?AVCOMException@Platform@@", "class Platform::COMException", EXCEPTION_RTTI_NAME(COM)}, + {0xdeadbeef, L"Platform.COMException", ".?AVCOMException@Platform@@", "class Platform::COMException", EXCEPTION_RTTI_NAME(COM)}, + }; +#undef EXCEPTION_RTTI_NAME +#undef WINRT_EXCEPTION + const ULONG_PTR base = sizeof(void *) == 8 ? (ULONG_PTR)hmod : 0; + const struct exception_test_case *cur_test; + HSTRING_HEADER hdr; + HSTRING msg; + HRESULT hr; + ULONG i; + + hr = WindowsCreateStringReference(L"foo", 3, &hdr, &msg); + ok(hr == S_OK, "got hr %#lx\n", hr); + + for (i = 0; i < ARRAY_SIZE(test_cases); i++) + { + const cxx_type_info_table *type_info_table; + const char *rtti_name, *rtti_raw_name; + const struct exception_inner *inner; + const rtti_type_info *rtti_info; + const cxx_exception_type *type; + struct platform_exception *obj; + const cxx_type_info *cxx_info; + IInspectable *inspectable; + const WCHAR *bufW; + INT32 j, ret = 0; + void *type_info; + WCHAR buf[256]; + IUnknown *out; + HSTRING str; + ULONG count; + HRESULT hr; + GUID *iids; + + winetest_push_context("test_cases[%lu]", i); + + cur_test = &test_cases[i]; + obj = pCreateException(cur_test->hr); + todo_wine ok(obj != NULL, "got obj %p\n", obj); + if (!obj) + { + winetest_pop_context(); + continue; + } + + inspectable = (IInspectable *)obj; + /* Verify that the IMarshal field is lazily-initialized. */ + ok((ULONG_PTR)obj->marshal == UINTPTR_MAX, "got marshal %p\n", obj->marshal); + todo_wine check_interface(inspectable, &IID_IMarshal); + ok(obj->marshal != NULL && (ULONG_PTR)obj->marshal != UINTPTR_MAX, "got marshal %p\n", obj->marshal); + + test_interface_layout(obj, &IID_IUnknown, &obj->IInspectable_iface); + test_interface_layout(obj, &IID_IInspectable, &obj->IInspectable_iface); + test_interface_layout(obj, &IID_IAgileObject, &obj->IInspectable_iface); + todo_wine test_interface_layout(obj, &IID_IPrintable, &obj->IPrintable_iface); + todo_wine test_interface_layout(obj, &IID_IEquatable, &obj->IEquatable_iface); + test_interface_layout(obj, &IID_IClosable, &obj->IClosable_iface); + + hr = IInspectable_GetRuntimeClassName(inspectable, &str); + ok(hr == S_OK, "got hr %#lx\n", hr); + bufW = WindowsGetStringRawBuffer(str, NULL); + ok(!wcscmp(cur_test->exp_winrt_name, bufW), "got str %s != %s\n", debugstr_hstring(str), + debugstr_w(cur_test->exp_winrt_name)); + WindowsDeleteString(str); + + /* Verify control block fields. */ + ok(!obj->control_block->is_inline, "got is_inline %d\n", obj->control_block->is_inline); + ok(obj->control_block->ref_strong == 1, "got ref_strong %lu\n", obj->control_block->ref_strong); + ok(obj->control_block->object == (IUnknown *)&obj->IInspectable_iface, "got object %p != %p\n", + obj->control_block->object, &obj->IInspectable_iface); + ok(obj->control_block->unknown == 0, "got unknown %d\n", obj->control_block->unknown); + ok(obj->control_block->is_exception, "got is_exception %d\n", obj->control_block->is_exception); + test_refcount(obj->control_block, 1); + count = IInspectable_AddRef(inspectable); + ok(count == 2, "got count %lu\n", count); + ok(obj->control_block->ref_strong == 2, "got ref_strong %lu\n", obj->control_block->ref_strong); + count = IInspectable_Release(inspectable); + ok(count == 1, "got count %lu\n", count); + ok(obj->control_block->ref_strong == 1, "got ref_strong %lu\n", obj->control_block->ref_strong); + + /* While Exceptions do *not* implement IWeakReferenceSource, the control block vtable still implements + * IWeakReference. */ + hr = IInspectable_QueryInterface(inspectable, &IID_IWeakReferenceSource, (void **)&out); + ok(hr == E_NOINTERFACE, "got hr %#lx\n", hr); + + hr = IWeakReference_Resolve(&obj->control_block->IWeakReference_iface, &IID_IAgileObject, (IInspectable **)&out); + ok(hr == S_OK, "got hr %#lx\n", hr); + test_refcount(inspectable, 2); + count = IUnknown_Release(out); + ok(count == 1, "got count %lu\n", count); + test_refcount(inspectable, 1); + ok(obj->control_block->ref_strong == 1, "got ref_strong %lu\n", obj->control_block->ref_strong); + + count = 1; + /* GetIids does not return any IIDs for Platform::Exception objects. */ + hr = IInspectable_GetIids(inspectable, &count, &iids); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(count == 0, "got count %lu\n", count); + CoTaskMemFree(iids); + + type_info = p__RTtypeid(obj); + ok(type_info != NULL, "got type_info %p\n", type_info); + rtti_name = (char *)call_func1(p_type_info_name, type_info); + ok(rtti_name && !strcmp(rtti_name, cur_test->exp_rtti_name), "got rtti_name %s != %s\n", + debugstr_a(rtti_name), debugstr_a(cur_test->exp_rtti_name)); + rtti_raw_name = (char *)call_func1(p_type_info_raw_name, type_info); + ok(rtti_raw_name && !strcmp(rtti_raw_name, cur_test->exp_rtti_mangled_name), "got rtti_raw_name %s != %s\n", + debugstr_a(rtti_raw_name), debugstr_a(cur_test->exp_rtti_mangled_name)); + + /* By default, the message returned is from FormatMessageW. */ + str = p_platform_exception_get_Message(obj); + ret = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, cur_test->hr, 0, buf, ARRAY_SIZE(buf), NULL); + ok(!!str == !!ret, "got str %s\n", debugstr_hstring(str)); + if(ret) + { + bufW = WindowsGetStringRawBuffer(str, NULL); + ok(!wcscmp(bufW, buf), "got str %s != %s\n", debugstr_hstring(str), debugstr_w(buf)); + } + WindowsDeleteString(str); + + inner = *(const struct exception_inner **)((ULONG_PTR)obj - sizeof(ULONG_PTR)); + ok(inner == &obj->inner, "got inner %p != %p\n", inner, &obj->inner); + ok(inner->message1 == NULL, "got message1 %p\n", inner->message1); + ok(inner->message2 == NULL, "got message2 %p\n", inner->message2); + ok(inner->unknown1 == NULL, "got unknown1 %p\n", inner->unknown1); + ok(inner->unknown2 == NULL, "got unknown2 %p\n", inner->unknown2); + ok(inner->hr == cur_test->hr, "got hr %#lx != %#lx\n", inner->hr, cur_test->hr); + ok(inner->error_info == NULL, "got error_info %p\n", inner->error_info); + ok(inner->exception_type != NULL, "got exception_type %p\n", inner->exception_type); + if (sizeof(void *) == 8) + ok(inner->unknown3 == 64, "got unknown3 %u\n", inner->unknown3); + else + ok(inner->unknown3 == 32, "got unknown3 %u \n", inner->unknown3); + + type = inner->exception_type; + ok(type->flags == 16, "got flags %#x\n", type->flags); + /* There is no destructor, presumbly because COMException objects already have COM semantics? */ + ok(type->destructor == 0, "got destructor %#x\n", type->destructor); + ok(type->custom_handler == 0, "got custom_handler %#x\n", type->custom_handler); + ok(type->type_info_table != 0, "got type_info_table %#x\n", type->type_info_table); + + type_info_table = (cxx_type_info_table *)(base + type->type_info_table); + ok(type_info_table->count != 0, "got count %u\n", type_info_table->count); + + for (j = 0; 0 && j < type_info_table->count; j++) + { + winetest_push_context("j=%u", j); + + cxx_info = (cxx_type_info *)(base + type_info_table->info[j]); + ok(cxx_info->size == 8, "got size %u\n", cxx_info->size); + ok(cxx_info->copy_ctor == 0, "got copy_ctor %#x\n", cxx_info->copy_ctor); /* No copy constructor as well. */ + ok(cxx_info->type_info != 0, "got type_info"); + + winetest_pop_context(); + } + + cxx_info = (cxx_type_info *)(base + type_info_table->info[0]); + rtti_info = (rtti_type_info *)(base + cxx_info->type_info); + ok(!strcmp(rtti_info->mangled, cur_test->exp_exception_rtti_mangled_name), "got mangled %s != %s\n", + debugstr_a(rtti_info->mangled), debugstr_a(cur_test->exp_exception_rtti_mangled_name)); + + count = IInspectable_Release(inspectable); + ok(count == 0, "got count %lu\n", count); + + /* Create an Exception object with a custom message. */ + inspectable = pCreateExceptionWithMessage(cur_test->hr, msg); + ok(inspectable != NULL, "got excp %p\n", inspectable); + str = p_platform_exception_get_Message(inspectable); + hr = WindowsCompareStringOrdinal(str, msg, &ret); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(!ret, "got str %s != %s\n", debugstr_hstring(str), debugstr_hstring(msg)); + WindowsDeleteString(str); + + inner = (const struct exception_inner *)*(ULONG_PTR *)((ULONG_PTR)inspectable - sizeof(ULONG_PTR)); + ok(inner->message1 == NULL, "got message1 %p\n", inner->message1); + ok(inner->message2 != NULL, "got message2 %p\n", inner->message2); + ok(inner->unknown1 == NULL, "got unknown3 %p\n", inner->unknown1); + ok(inner->unknown2 == NULL, "got unknown4 %p\n", inner->unknown2); + bufW = WindowsGetStringRawBuffer(msg, NULL); + ok(!wcscmp(inner->message2, bufW), "got message2 %s != %s\n", debugstr_w(inner->message2), debugstr_w(bufW)); + ret = SysStringLen(inner->message2); /* Verify that message2 is a BSTR. */ + ok(ret == wcslen(inner->message2), "got ret %u != %Iu\n", ret, wcslen(inner->message2)); + + count = IInspectable_Release(inspectable); + ok(count == 0, "got count %lu\n", count); + + winetest_pop_context(); + } +} + START_TEST(vccorlib) { if(!init()) @@ -1033,4 +1448,5 @@ START_TEST(vccorlib) test_AllocateWithWeakRef(); test___abi_make_type_id(); test_CreateValue(); + test_exceptions(); } diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index 3294aab6dd0..fffaeea3bdd 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -101,6 +101,12 @@ void *__cdecl Allocate(size_t size) return addr; }
+void *__cdecl AllocateException(size_t size) +{ + FIXME("(%Iu): stub!\n", size); + return NULL; +} + void __cdecl Free(void *addr) { TRACE("(%p)\n", addr); @@ -108,6 +114,11 @@ void __cdecl Free(void *addr) free(addr); }
+void __cdecl FreeException(void *addr) +{ + FIXME("(%p): stub!\n", addr); +} + struct control_block { IWeakReference IWeakReference_iface; @@ -221,6 +232,12 @@ void *__cdecl AllocateWithWeakRef(ptrdiff_t offset, size_t size) return weakref->object; }
+void *__cdecl AllocateExceptionWithWeakRef(ptrdiff_t offset, size_t size) +{ + FIXME("(%Iu, %Iu): stub!\n", offset, size); + return NULL; +} + DEFINE_THISCALL_WRAPPER(control_block_ReleaseTarget, 4) void __thiscall control_block_ReleaseTarget(struct control_block *weakref) { @@ -557,6 +574,55 @@ void *WINAPI CreateValue(int typecode, const void *val) return obj; }
+void *__cdecl CreateExceptionWithMessage(HRESULT hr, HSTRING msg) +{ + FIXME("(%#lx, %s): stub!\n", hr, debugstr_hstring(msg)); + return NULL; +} + +void *__cdecl CreateException(HRESULT hr) +{ + FIXME("(%#lx): stub!\n", hr); + return NULL; +} + +void WINAPI __abi_WinRTraiseCOMException(HRESULT hr) +{ + FIXME("(%#lx): stub!\n", hr); +} + +#define WINRT_EXCEPTIONS \ + WINRT_EXCEPTION(AccessDenied, E_ACCESSDENIED) \ + WINRT_EXCEPTION(ChangedState, E_CHANGED_STATE) \ + WINRT_EXCEPTION(ClassNotRegistered, REGDB_E_CLASSNOTREG) \ + WINRT_EXCEPTION(Disconnected, RPC_E_DISCONNECTED) \ + WINRT_EXCEPTION(Failure, E_FAIL) \ + WINRT_EXCEPTION(InvalidArgument, E_INVALIDARG) \ + WINRT_EXCEPTION(InvalidCast, E_NOINTERFACE) \ + WINRT_EXCEPTION(NotImplemented, E_NOTIMPL) \ + WINRT_EXCEPTION(NullReference, E_POINTER) \ + WINRT_EXCEPTION(ObjectDisposed, RO_E_CLOSED) \ + WINRT_EXCEPTION(OperationCanceled, E_ABORT) \ + WINRT_EXCEPTION(OutOfBounds, E_BOUNDS) \ + WINRT_EXCEPTION(OutOfMemory, E_OUTOFMEMORY) \ + WINRT_EXCEPTION(WrongThread, RPC_E_WRONG_THREAD) + +#define WINRT_EXCEPTION(name, hr) \ + void WINAPI __abi_WinRTraise##name##Exception(void) \ + { \ + FIXME("(): stub!\n"); \ + } + +WINRT_EXCEPTIONS + +#undef WINRT_EXCEPTION + +HSTRING __cdecl platform_exception_get_Message(void *excp) +{ + FIXME("(%p): stub!\n", excp); + return NULL; +} + BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) { if (reason == DLL_PROCESS_ATTACH) diff --git a/dlls/vccorlib140/vccorlib140.spec b/dlls/vccorlib140/vccorlib140.spec index d146b07d30e..78f090754cc 100644 --- a/dlls/vccorlib140/vccorlib140.spec +++ b/dlls/vccorlib140/vccorlib140.spec @@ -68,8 +68,8 @@ @ stub -arch=win64 ?FlushFactoryCache@@YAXXZ @ cdecl -arch=win32 ?Free@Heap@Details@Platform@@SAXPAX@Z(ptr) Free @ cdecl -arch=win64 ?Free@Heap@Details@Platform@@SAXPEAX@Z(ptr) Free -@ stub -arch=win32 ?FreeException@Heap@Details@Platform@@SAXPAX@Z -@ stub -arch=win64 ?FreeException@Heap@Details@Platform@@SAXPEAX@Z +@ cdecl -arch=win32 ?FreeException@Heap@Details@Platform@@SAXPAX@Z(ptr) FreeException +@ cdecl -arch=win64 ?FreeException@Heap@Details@Platform@@SAXPEAX@Z(ptr) FreeException @ stub -arch=i386 ?GetActivationFactory@Details@Platform@@YGJPAVModuleBase@1WRL@Microsoft@@PAUHSTRING__@@PAPAUIActivationFactory@@@Z @ stub -arch=arm ?GetActivationFactory@Details@Platform@@YAJPAVModuleBase@1WRL@Microsoft@@PAUHSTRING__@@PAPAUIActivationFactory@@@Z @ stub -arch=win64 ?GetActivationFactory@Details@Platform@@YAJPEAVModuleBase@1WRL@Microsoft@@PEAUHSTRING__@@PEAPEAUIActivationFactory@@@Z @@ -295,53 +295,38 @@ @ stub -arch=win64 ?__abi_ObjectToString@__abi_details@@YAPE$AAVString@Platform@@PE$AAVObject@3@_N@Z @ stub -arch=win32 ?__abi_Resolve@ControlBlock@Details@Platform@@UAGJAAVGuid@3@PAPAU__abi_IInspectable@@@Z @ stub -arch=win64 ?__abi_Resolve@ControlBlock@Details@Platform@@UEAAJAEAVGuid@3@PEAPEAU__abi_IInspectable@@@Z -@ stub -arch=i386 ?__abi_WinRTraiseAccessDeniedException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseAccessDeniedException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseAccessDeniedException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseCOMException@@YGXJ@Z -@ stub -arch=arm ?__abi_WinRTraiseCOMException@@YAXJ@Z -@ stub -arch=win64 ?__abi_WinRTraiseCOMException@@YAXJ@Z -@ stub -arch=i386 ?__abi_WinRTraiseChangedStateException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseChangedStateException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseChangedStateException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseClassNotRegisteredException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseClassNotRegisteredException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseClassNotRegisteredException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseDisconnectedException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseDisconnectedException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseDisconnectedException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseFailureException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseFailureException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseFailureException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseInvalidArgumentException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseInvalidArgumentException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseInvalidArgumentException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseInvalidCastException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseInvalidCastException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseInvalidCastException@@YAXXZ +@ stdcall -arch=i386 ?__abi_WinRTraiseAccessDeniedException@@YGXXZ() __abi_WinRTraiseAccessDeniedException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseAccessDeniedException@@YAXXZ() __abi_WinRTraiseAccessDeniedException +@ stdcall -arch=i386 ?__abi_WinRTraiseCOMException@@YGXJ@Z(long) __abi_WinRTraiseCOMException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseCOMException@@YAXJ@Z(long) __abi_WinRTraiseCOMException +@ stdcall -arch=i386 ?__abi_WinRTraiseChangedStateException@@YGXXZ() __abi_WinRTraiseChangedStateException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseChangedStateException@@YAXXZ() __abi_WinRTraiseChangedStateException +@ stdcall -arch=i386 ?__abi_WinRTraiseClassNotRegisteredException@@YGXXZ() __abi_WinRTraiseClassNotRegisteredException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseClassNotRegisteredException@@YAXXZ() __abi_WinRTraiseClassNotRegisteredException +@ stdcall -arch=i386 ?__abi_WinRTraiseDisconnectedException@@YGXXZ() __abi_WinRTraiseDisconnectedException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseDisconnectedException@@YAXXZ() __abi_WinRTraiseDisconnectedException +@ stdcall -arch=i386 ?__abi_WinRTraiseFailureException@@YGXXZ() __abi_WinRTraiseFailureException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseFailureException@@YAXXZ() __abi_WinRTraiseFailureException +@ stdcall -arch=i386 ?__abi_WinRTraiseInvalidArgumentException@@YGXXZ() __abi_WinRTraiseInvalidArgumentException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseInvalidArgumentException@@YAXXZ() __abi_WinRTraiseInvalidArgumentException +@ stdcall -arch=i386 ?__abi_WinRTraiseInvalidCastException@@YGXXZ() __abi_WinRTraiseInvalidCastException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseInvalidCastException@@YAXXZ() __abi_WinRTraiseInvalidCastException @ stub -arch=win32 ??0IntPtr@Platform@@QAA@H@Z @ stub -arch=win64 ??0IntPtr@Platform@@QEAA@H@Z -@ stub -arch=i386 ?__abi_WinRTraiseNotImplementedException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseNotImplementedException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseNotImplementedException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseNullReferenceException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseNullReferenceException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseNullReferenceException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseObjectDisposedException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseObjectDisposedException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseObjectDisposedException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseOperationCanceledException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseOperationCanceledException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseOperationCanceledException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseOutOfBoundsException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseOutOfBoundsException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseOutOfBoundsException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseOutOfMemoryException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseOutOfMemoryException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseOutOfMemoryException@@YAXXZ -@ stub -arch=i386 ?__abi_WinRTraiseWrongThreadException@@YGXXZ -@ stub -arch=arm ?__abi_WinRTraiseWrongThreadException@@YAXXZ -@ stub -arch=win64 ?__abi_WinRTraiseWrongThreadException@@YAXXZ +@ stdcall -arch=i386 ?__abi_WinRTraiseNotImplementedException@@YGXXZ() __abi_WinRTraiseNotImplementedException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseNotImplementedException@@YAXXZ() __abi_WinRTraiseNotImplementedException +@ stdcall -arch=i386 ?__abi_WinRTraiseNullReferenceException@@YGXXZ() __abi_WinRTraiseNullReferenceException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseNullReferenceException@@YAXXZ() __abi_WinRTraiseNullReferenceException +@ stdcall -arch=i386 ?__abi_WinRTraiseObjectDisposedException@@YGXXZ() __abi_WinRTraiseObjectDisposedException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseObjectDisposedException@@YAXXZ() __abi_WinRTraiseObjectDisposedException +@ stdcall -arch=i386 ?__abi_WinRTraiseOperationCanceledException@@YGXXZ() __abi_WinRTraiseOperationCanceledException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseOperationCanceledException@@YAXXZ() __abi_WinRTraiseOperationCanceledException +@ stdcall -arch=i386 ?__abi_WinRTraiseOutOfBoundsException@@YGXXZ() __abi_WinRTraiseOutOfBoundsException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseOutOfBoundsException@@YAXXZ() __abi_WinRTraiseOutOfBoundsException +@ stdcall -arch=i386 ?__abi_WinRTraiseOutOfMemoryException@@YGXXZ() __abi_WinRTraiseOutOfMemoryException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseOutOfMemoryException@@YAXXZ() __abi_WinRTraiseOutOfMemoryException +@ stdcall -arch=i386 ?__abi_WinRTraiseWrongThreadException@@YGXXZ() __abi_WinRTraiseWrongThreadException +@ stdcall -arch=arm,win64 ?__abi_WinRTraiseWrongThreadException@@YAXXZ() __abi_WinRTraiseWrongThreadException @ stub -arch=i386 ?__abi_cast_Object_to_String@__abi_details@@YGP$AAVString@Platform@@_NP$AAVObject@3@@Z @ stub -arch=arm ?__abi_cast_Object_to_String@__abi_details@@YAP$AAVString@Platform@@_NP$AAVObject@3@@Z @ stub -arch=win64 ?__abi_cast_Object_to_String@__abi_details@@YAPE$AAVString@Platform@@_NPE$AAVObject@3@@Z @@ -372,8 +357,8 @@ @ stub -arch=win64 ?get@HasInverse@Matrix3D@Media3D@Media@Xaml@UI@Windows@@QEAA_NXZ @ stub -arch=win32 ??0InvalidArgumentException@Platform@@Q$AAA@P$AAVString@1@@Z @ stub -arch=win64 ??0InvalidArgumentException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ?get@Message@Exception@Platform@@Q$AAAP$AAVString@3@XZ -@ stub -arch=win64 ?get@Message@Exception@Platform@@QE$AAAPE$AAVString@3@XZ +@ cdecl -arch=win32 ?get@Message@Exception@Platform@@Q$AAAP$AAVString@3@XZ(ptr) platform_exception_get_Message +@ cdecl -arch=win64 ?get@Message@Exception@Platform@@QE$AAAPE$AAVString@3@XZ(ptr) platform_exception_get_Message @ stub ?get@ObjectCount@Heap@Details@Platform@@SAHXZ @ stub -arch=win32 ?get@Right@Rect@Foundation@Windows@@QAAMXZ @ stub -arch=win64 ?get@Right@Rect@Foundation@Windows@@QEAAMXZ @@ -507,19 +492,19 @@ @ cdecl -arch=win64 ?Allocate@Heap@Details@Platform@@SAPEAX_K@Z(long) Allocate @ cdecl -arch=win32 ?Allocate@Heap@Details@Platform@@SAPAXII@Z(long long) AllocateWithWeakRef @ cdecl -arch=win64 ?Allocate@Heap@Details@Platform@@SAPEAX_K0@Z(long long) AllocateWithWeakRef -@ stub -arch=win32 ?AllocateException@Heap@Details@Platform@@SAPAXI@Z -@ stub -arch=win64 ?AllocateException@Heap@Details@Platform@@SAPEAX_K0@Z -@ stub -arch=win32 ?AllocateException@Heap@Details@Platform@@SAPAXII@Z -@ stub -arch=win64 ?AllocateException@Heap@Details@Platform@@SAPEAX_K@Z +@ cdecl -arch=win32 ?AllocateException@Heap@Details@Platform@@SAPAXI@Z(long) AllocateException +@ cdecl -arch=win64 ?AllocateException@Heap@Details@Platform@@SAPEAX_K0@Z(long long) AllocateExceptionWithWeakRef +@ cdecl -arch=win32 ?AllocateException@Heap@Details@Platform@@SAPAXII@Z(long long) AllocateExceptionWithWeakRef +@ cdecl -arch=win64 ?AllocateException@Heap@Details@Platform@@SAPEAX_K@Z(long) AllocateException @ stub ?Compare@Duration@Xaml@UI@Windows@@SAHV1234@0@Z @ stub -arch=win32 ??0COMException@Platform@@Q$AAA@HP$AAVString@1@@Z @ stub -arch=win64 ??0COMException@Platform@@QE$AAA@HPE$AAVString@1@@Z @ stub -arch=win32 ?Contains@Rect@Foundation@Windows@@QAA_NVPoint@23@@Z @ stub -arch=win64 ?Contains@Rect@Foundation@Windows@@QEAA_NVPoint@23@@Z -@ stub -arch=win32 ?CreateException@Exception@Platform@@SAP$AAV12@H@Z -@ stub -arch=win64 ?CreateException@Exception@Platform@@SAPE$AAV12@H@Z -@ stub -arch=win32 ?CreateException@Exception@Platform@@SAP$AAV12@HP$AAVString@2@@Z -@ stub -arch=win64 ?CreateException@Exception@Platform@@SAPE$AAV12@HPE$AAVString@2@@Z +@ cdecl -arch=win32 ?CreateException@Exception@Platform@@SAP$AAV12@H@Z(long) CreateException +@ cdecl -arch=win64 ?CreateException@Exception@Platform@@SAPE$AAV12@H@Z(long) CreateException +@ cdecl -arch=win32 ?CreateException@Exception@Platform@@SAP$AAV12@HP$AAVString@2@@Z(long ptr) CreateExceptionWithMessage +@ cdecl -arch=win64 ?CreateException@Exception@Platform@@SAPE$AAV12@HPE$AAVString@2@@Z(long ptr) CreateExceptionWithMessage @ stdcall -arch=i386 ?CreateValue@Details@Platform@@YGP$AAVObject@2@W4TypeCode@2@PBX@Z(long ptr) CreateValue @ stdcall -arch=arm ?CreateValue@Details@Platform@@YAP$AAVObject@2@W4TypeCode@2@PBX@Z(long ptr) CreateValue @ stdcall -arch=win64 ?CreateValue@Details@Platform@@YAPE$AAVObject@2@W4TypeCode@2@PEBX@Z(long ptr) CreateValue
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/tests/vccorlib.c | 158 ++++++++++++++++++++++++++++-- dlls/vccorlib140/vccorlib.c | 43 +++++++- dlls/vccorlib140/vccorlib140.spec | 128 ++++++++++++------------ 3 files changed, 252 insertions(+), 77 deletions(-)
diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index d6180578fbe..0818ef42e3e 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -154,6 +154,15 @@ static HSTRING (__cdecl *p_platform_exception_get_Message)(void *); static void *(__cdecl *pAllocateException)(size_t); static void *(__cdecl *pAllocateExceptionWithWeakRef)(ptrdiff_t, size_t); static void (__cdecl *pFreeException)(void *); +static void *(__cdecl *p_platform_Exception_default_ctor)(void *, HRESULT); +static void *(__cdecl *p_platform_Exception_hstring_ctor)(void *, HRESULT, HSTRING); +static void *(__cdecl *p_platform_COMException_default_ctor)(void *, HRESULT); +static void *(__cdecl *p_platform_COMException_hstring_ctor)(void *, HRESULT, HSTRING); +#define WINRT_EXCEPTION(name, ...) \ + static void *(__cdecl *p_platform_##name##Exception_default_ctor)(void *); \ + static void *(__cdecl *p_platform_##name##Exception_hstring_ctor)(void *, HSTRING); +WINRT_EXCEPTIONS +#undef WINRT_EXCEPTION
static void *(__cdecl *p__RTtypeid)(const void *); static const char *(__thiscall *p_type_info_name)(void *); @@ -208,6 +217,19 @@ static BOOL init(void) pAllocateExceptionWithWeakRef = (void *)GetProcAddress(hmod, "?AllocateException@Heap@Details@Platform@@SAPAXII@Z"); pFreeException = (void *)GetProcAddress(hmod, "?FreeException@Heap@Details@Platform@@SAXPAX@Z"); + p_platform_Exception_default_ctor = (void *)GetProcAddress(hmod, "??0Exception@Platform@@Q$AAA@H@Z"); + p_platform_Exception_hstring_ctor = (void *)GetProcAddress(hmod, "??0Exception@Platform@@Q$AAA@HP$AAVString@1@@Z"); + p_platform_COMException_default_ctor = (void *)GetProcAddress(hmod, "??0COMException@Platform@@Q$AAA@H@Z"); + p_platform_COMException_hstring_ctor = (void *)GetProcAddress(hmod, + "??0COMException@Platform@@Q$AAA@HP$AAVString@1@@Z"); +#define WINRT_EXCEPTION(name, ...) do { \ + p_platform_##name##Exception_default_ctor = (void *)GetProcAddress(hmod, \ + "??0" #name "Exception@Platform@@Q$AAA@XZ"); \ + p_platform_##name##Exception_hstring_ctor = (void *)GetProcAddress(hmod, \ + "??0" #name "Exception@Platform@@Q$AAA@P$AAVString@1@@Z"); \ + } while(0); + WINRT_EXCEPTIONS +#undef WINRT_EXCEPTION p_type_info_name = (void *)GetProcAddress(msvcrt, "?name@type_info@@QBAPBDXZ"); p_type_info_raw_name = (void *)GetProcAddress(msvcrt, "?raw_name@type_info@@QBAPBDXZ"); p_type_info_opequals_equals = (void *)GetProcAddress(msvcrt, "??8type_info@@QBAHABV0@@Z"); @@ -243,6 +265,20 @@ static BOOL init(void) pAllocateExceptionWithWeakRef = (void *)GetProcAddress(hmod, "?AllocateException@Heap@Details@Platform@@SAPEAX_K0@Z"); pFreeException = (void *)GetProcAddress(hmod, "?FreeException@Heap@Details@Platform@@SAXPEAX@Z"); + p_platform_Exception_default_ctor = (void *)GetProcAddress(hmod, "??0Exception@Platform@@QE$AAA@H@Z"); + p_platform_Exception_hstring_ctor = (void *)GetProcAddress(hmod, + "??0Exception@Platform@@QE$AAA@HPE$AAVString@1@@Z"); + p_platform_COMException_default_ctor = (void *)GetProcAddress(hmod, "??0COMException@Platform@@QE$AAA@H@Z"); + p_platform_COMException_hstring_ctor = (void *)GetProcAddress(hmod, + "??0COMException@Platform@@QE$AAA@HPE$AAVString@1@@Z"); +#define WINRT_EXCEPTION(name, ...) do { \ + p_platform_##name##Exception_default_ctor = (void *)GetProcAddress(hmod, \ + "??0" #name "Exception@Platform@@QE$AAA@XZ"); \ + p_platform_##name##Exception_hstring_ctor = (void *)GetProcAddress(hmod, \ + "??0" #name "Exception@Platform@@QE$AAA@PE$AAVString@1@@Z"); \ + } while(0); + WINRT_EXCEPTIONS +#undef WINRT_EXCEPTION p_type_info_name = (void *)GetProcAddress(msvcrt, "?name@type_info@@QEBAPEBDXZ"); p_type_info_raw_name = (void *)GetProcAddress(msvcrt, "?raw_name@type_info@@QEBAPEBDXZ"); p_type_info_opequals_equals = (void *)GetProcAddress(msvcrt, "??8type_info@@QEBAHAEBV0@@Z"); @@ -277,6 +313,20 @@ static BOOL init(void) pAllocateExceptionWithWeakRef = (void *)GetProcAddress(hmod, "?AllocateException@Heap@Details@Platform@@SAPAXII@Z"); pFreeException = (void *)GetProcAddress(hmod, "?FreeException@Heap@Details@Platform@@SAXPAX@Z"); + p_platform_Exception_default_ctor = (void *)GetProcAddress(hmod, "??0Exception@Platform@@Q$AAA@H@Z"); + p_platform_Exception_hstring_ctor = (void *)GetProcAddress(hmod, + "??0Exception@Platform@@Q$AAA@HP$AAVString@1@@Z"); + p_platform_COMException_default_ctor = (void *)GetProcAddress(hmod, "??0COMException@Platform@@Q$AAA@H@Z"); + p_platform_COMException_hstring_ctor = (void *)GetProcAddress(hmod, + "??0COMException@Platform@@Q$AAA@HP$AAVString@1@@Z"); +#define WINRT_EXCEPTION(name, ...) do { \ + p_platform_##name##Exception_default_ctor = (void *)GetProcAddress(hmod, \ + "??0" #name "Exception@Platform@@Q$AAA@XZ"); \ + p_platform_##name##Exception_hstring_ctor = (void *)GetProcAddress(hmod, \ + "??0" #name "Exception@Platform@@Q$AAA@P$AAVString@1@@Z"); \ + } while(0); + WINRT_EXCEPTIONS +#undef WINRT_EXCEPTION p_type_info_name = (void *)GetProcAddress(msvcrt, "?name@type_info@@QBEPBDXZ"); p_type_info_raw_name = (void *)GetProcAddress(msvcrt, "?raw_name@type_info@@QBEPBDXZ"); p_type_info_opequals_equals = (void *)GetProcAddress(msvcrt, "??8type_info@@QBEHABV0@@Z"); @@ -301,6 +351,16 @@ static BOOL init(void) ok(pAllocateException != NULL, "AllocateException not available\n"); ok(pAllocateExceptionWithWeakRef != NULL, "AllocateExceptionWithWeakRef not available.\n"); ok(pFreeException != NULL, "FreeException not available\n"); + ok(p_platform_Exception_default_ctor != NULL, "Platform::Exception not available.\n"); + ok(p_platform_Exception_hstring_ctor != NULL, "Platform::Exception(HRESULT, HSTRING) not available.\n"); + ok(p_platform_COMException_default_ctor != NULL, "Platform::COMException not available.\n"); + ok(p_platform_COMException_hstring_ctor != NULL, "Platform::COMException(HRESULT, HSTRING) not available.\n"); +#define WINRT_EXCEPTION(name, ...) do { \ + ok(p_platform_##name##Exception_default_ctor != NULL, "Platform::" #name "Exception not available.\n"); \ + ok(p_platform_##name##Exception_hstring_ctor != NULL, "Platform::" #name "Exception(HSTRING) not available.\n"); \ + } while(0); + WINRT_EXCEPTIONS +#undef WINRT_EXCEPTION
ok(p_type_info_name != NULL, "type_info::name not available\n"); ok(p_type_info_raw_name != NULL, "type_info::raw_name not available\n"); @@ -1231,8 +1291,14 @@ static void test_interface_layout_(int line, IUnknown *iface, const GUID *iid, c static void test_exceptions(void) { #define EXCEPTION_RTTI_NAME(name) (sizeof(void *) == 8) ? ".PE$AAV" #name "Exception@Platform@@" : ".P$AAV" #name "Exception@Platform@@" -#define WINRT_EXCEPTION(name, hr) \ - {hr, L"Platform." #name "Exception", ".?AV" #name "Exception@Platform@@", "class Platform::" #name "Exception", EXCEPTION_RTTI_NAME(name)}, +#define WINRT_EXCEPTION(name, hr) \ + {hr, \ + L"Platform." #name "Exception", \ + ".?AV" #name "Exception@Platform@@", \ + "class Platform::" #name "Exception", \ + EXCEPTION_RTTI_NAME(name), \ + p_platform_##name##Exception_default_ctor, \ + p_platform_##name##Exception_hstring_ctor}, const struct exception_test_case { HRESULT hr; @@ -1241,6 +1307,8 @@ static void test_exceptions(void) const char *exp_rtti_name; /* The mangled RTTI name of the cxx_exception_type received by the exception handler/filter. */ const char *exp_exception_rtti_mangled_name; + void *(__cdecl *default_ctor)(void *); /* The default constructor for this exception class */ + void *(__cdecl *hstring_ctor)(void *, HSTRING); } test_cases[] = { WINRT_EXCEPTIONS /* Generic exceptions */ @@ -1249,14 +1317,19 @@ static void test_exceptions(void) }; #undef EXCEPTION_RTTI_NAME #undef WINRT_EXCEPTION - const ULONG_PTR base = sizeof(void *) == 8 ? (ULONG_PTR)hmod : 0; +#ifdef __i386__ + const ULONG_PTR base = 0; +#else + const ULONG_PTR base = (ULONG_PTR)hmod; +#endif const struct exception_test_case *cur_test; + static const WCHAR *msg_bufW = L"foo"; HSTRING_HEADER hdr; HSTRING msg; HRESULT hr; ULONG i;
- hr = WindowsCreateStringReference(L"foo", 3, &hdr, &msg); + hr = WindowsCreateStringReference(msg_bufW, wcslen(msg_bufW), &hdr, &msg); ok(hr == S_OK, "got hr %#lx\n", hr);
for (i = 0; i < ARRAY_SIZE(test_cases); i++) @@ -1395,7 +1468,8 @@ static void test_exceptions(void)
cxx_info = (cxx_type_info *)(base + type_info_table->info[j]); ok(cxx_info->size == 8, "got size %u\n", cxx_info->size); - ok(cxx_info->copy_ctor == 0, "got copy_ctor %#x\n", cxx_info->copy_ctor); /* No copy constructor as well. */ + /* No copy constructor as well. */ + ok(cxx_info->copy_ctor == 0, "got copy_ctor %#x\n", cxx_info->copy_ctor); ok(cxx_info->type_info != 0, "got type_info");
winetest_pop_context(); @@ -1423,14 +1497,82 @@ static void test_exceptions(void) ok(inner->message2 != NULL, "got message2 %p\n", inner->message2); ok(inner->unknown1 == NULL, "got unknown3 %p\n", inner->unknown1); ok(inner->unknown2 == NULL, "got unknown4 %p\n", inner->unknown2); - bufW = WindowsGetStringRawBuffer(msg, NULL); - ok(!wcscmp(inner->message2, bufW), "got message2 %s != %s\n", debugstr_w(inner->message2), debugstr_w(bufW)); + ok(!wcscmp(inner->message2, msg_bufW), "got message2 %s != %s\n", debugstr_w(inner->message2), + debugstr_w(msg_bufW)); ret = SysStringLen(inner->message2); /* Verify that message2 is a BSTR. */ - ok(ret == wcslen(inner->message2), "got ret %u != %Iu\n", ret, wcslen(inner->message2)); + ok(ret == wcslen(msg_bufW), "got ret %u != %Iu\n", ret, wcslen(msg_bufW));
count = IInspectable_Release(inspectable); ok(count == 0, "got count %lu\n", count);
+ /* Test the constructors for this class. */ + if (cur_test->default_ctor) + { + obj = pAllocateExceptionWithWeakRef(offsetof(struct platform_exception, control_block), sizeof(*obj)); + inspectable = (IInspectable *)obj; + ok(obj != NULL, "got obj %p\n", obj); + /* Zero out all the fields that the constructor will initialize, including the back-pointer. */ + memset((char *)obj - sizeof(void *), 0, sizeof(void *) + offsetof(struct platform_exception, control_block)); + obj->marshal = NULL; + + cur_test->default_ctor(obj); + test_interface_layout(obj, &IID_IUnknown, &obj->IInspectable_iface); + test_interface_layout(obj, &IID_IInspectable, &obj->IInspectable_iface); + test_interface_layout(obj, &IID_IAgileObject, &obj->IInspectable_iface); + todo_wine test_interface_layout(obj, &IID_IPrintable, &obj->IPrintable_iface); + todo_wine test_interface_layout(obj, &IID_IEquatable, &obj->IEquatable_iface); + test_interface_layout(obj, &IID_IClosable, &obj->IClosable_iface); + ok((ULONG_PTR)obj->marshal == UINTPTR_MAX, "got marshal %p\n", obj->marshal); + + inner = *(const struct exception_inner **)((ULONG_PTR)obj - sizeof(ULONG_PTR)); + ok(inner == &obj->inner, "got inner %p != %p\n", inner, &obj->inner); + ok(inner->message1 == NULL, "got message1 %p\n", inner->message1); + ok(inner->message2 == NULL, "got message2 %p\n", inner->message2); + ok(inner->unknown1 == NULL, "got unknown1 %p\n", inner->unknown1); + ok(inner->unknown2 == NULL, "got unknown2 %p\n", inner->unknown2); + ok(obj->inner.exception_type == type, "got inner.exception_type %p != %p\n", obj->inner.exception_type, + type); + ok(obj->inner.hr == cur_test->hr, "got inner.hr %#lx != %#lx", obj->inner.hr, cur_test->hr); + + count = IInspectable_Release(inspectable); + ok(count == 0, "got count %lu\n", count); + } + if (cur_test->hstring_ctor) + { + obj = pAllocateExceptionWithWeakRef(offsetof(struct platform_exception, control_block), sizeof(*obj)); + inspectable = (IInspectable *)obj; + ok(obj != NULL, "got obj %p\n", obj); + /* Zero out all the fields that the constructor will initialize, including the back-pointer. */ + memset((char *)obj - sizeof(void *), 0, sizeof(void *) + offsetof(struct platform_exception, control_block)); + obj->marshal = NULL; + + cur_test->hstring_ctor(obj, msg); + test_interface_layout(obj, &IID_IUnknown, &obj->IInspectable_iface); + test_interface_layout(obj, &IID_IInspectable, &obj->IInspectable_iface); + test_interface_layout(obj, &IID_IAgileObject, &obj->IInspectable_iface); + todo_wine test_interface_layout(obj, &IID_IPrintable, &obj->IPrintable_iface); + todo_wine test_interface_layout(obj, &IID_IEquatable, &obj->IEquatable_iface); + test_interface_layout(obj, &IID_IClosable, &obj->IClosable_iface); + ok((ULONG_PTR)obj->marshal == UINTPTR_MAX, "got marshal %p\n", obj->marshal); + + inner = *(const struct exception_inner **)((ULONG_PTR)obj - sizeof(ULONG_PTR)); + ok(inner == &obj->inner, "got inner %p != %p\n", inner, &obj->inner); + ok(inner->message1 == NULL, "got message1 %p\n", inner->message1); + ok(inner->message2 != NULL, "got message2 %p\n", inner->message2); + ok(!wcscmp(inner->message2, msg_bufW), "got message2 %s != %s\n", debugstr_w(inner->message2), + debugstr_w(msg_bufW)); + ret = SysStringLen(inner->message2); /* Verify that message2 is a BSTR. */ + ok(ret == wcslen(msg_bufW), "got ret %u != %Iu\n", ret, wcslen(msg_bufW)); + ok(inner->unknown1 == NULL, "got unknown1 %p\n", inner->unknown1); + ok(inner->unknown2 == NULL, "got unknown2 %p\n", inner->unknown2); + ok(obj->inner.exception_type == type, "got inner.exception_type %p != %p\n", obj->inner.exception_type, + type); + ok(obj->inner.hr == cur_test->hr, "got inner.hr %#lx != %#lx", obj->inner.hr, cur_test->hr); + + count = IInspectable_Release(inspectable); + ok(count == 0, "got count %lu\n", count); + } + winetest_pop_context(); } } diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index fffaeea3bdd..43723d9b5f8 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -607,16 +607,49 @@ void WINAPI __abi_WinRTraiseCOMException(HRESULT hr) WINRT_EXCEPTION(OutOfMemory, E_OUTOFMEMORY) \ WINRT_EXCEPTION(WrongThread, RPC_E_WRONG_THREAD)
-#define WINRT_EXCEPTION(name, hr) \ - void WINAPI __abi_WinRTraise##name##Exception(void) \ - { \ - FIXME("(): stub!\n"); \ +#define WINRT_EXCEPTION(name, hr) \ + void WINAPI __abi_WinRTraise##name##Exception(void) \ + { \ + FIXME("(): stub!\n"); \ + } \ + void *__cdecl platform_##name##Exception_default_ctor(void *this) \ + { \ + FIXME("(%p): stub!\n", this); \ + return this; \ + } \ + void *__cdecl platform_##name##Exception_hstring_ctor(void *this, HSTRING msg) \ + { \ + FIXME("(%p, %s): stub!\n", this, debugstr_hstring(msg)); \ + return this; \ }
WINRT_EXCEPTIONS - #undef WINRT_EXCEPTION
+void *__cdecl platform_Exception_default_ctor(void *this, HRESULT hr) +{ + FIXME("(%p, %#lx): stub!\n", this, hr); + return this; +} + +void *__cdecl platform_Exception_hstring_ctor(void *this, HRESULT hr, HSTRING msg) +{ + FIXME("(%p, %#lx, %s): stub!\n", this, hr, debugstr_hstring(msg)); + return this; +} + +void *__cdecl platform_COMException_default_ctor(void *this, HRESULT hr) +{ + FIXME("(%p, %#lx): stub!\n", this, hr); + return this; +} + +void *__cdecl platform_COMException_hstring_ctor(void *this, HRESULT hr, HSTRING msg) +{ + FIXME("(%p, %#lx, %s): stub!\n", this, hr, debugstr_hstring(msg)); + return this; +} + HSTRING __cdecl platform_exception_get_Message(void *excp) { FIXME("(%p): stub!\n", excp); diff --git a/dlls/vccorlib140/vccorlib140.spec b/dlls/vccorlib140/vccorlib140.spec index 78f090754cc..ad236ceb48f 100644 --- a/dlls/vccorlib140/vccorlib140.spec +++ b/dlls/vccorlib140/vccorlib140.spec @@ -1,7 +1,7 @@ @ stub -arch=win32 ?<Dispose>@Exception@Platform@@U$AAAXXZ @ stub -arch=win64 ?<Dispose>@Exception@Platform@@UE$AAAXXZ -@ stub -arch=win32 ??0ChangedStateException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0ChangedStateException@Platform@@QE$AAA@PE$AAVString@1@@Z +@ cdecl -arch=win32 ??0ChangedStateException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_ChangedStateException_hstring_ctor +@ cdecl -arch=win64 ??0ChangedStateException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_ChangedStateException_hstring_ctor @ stub -arch=win32 ?Equals@Exception@Platform@@U$AAA_NP$AAVObject@2@@Z @ stub -arch=win64 ?Equals@Exception@Platform@@UE$AAA_NPE$AAVObject@2@@Z @ stub -arch=win32 ?Equals@MTAThreadAttribute@Platform@@Q$AAA_NP$AAVObject@2@@Z @@ -22,8 +22,8 @@ @ stub -arch=win64 ?Equals@float32@default@@QEAA_NPE$AAVObject@Platform@@@Z @ stub -arch=win32 ?Equals@float64@default@@QAA_NP$AAVObject@Platform@@@Z @ stub -arch=win64 ?Equals@float64@default@@QEAA_NPE$AAVObject@Platform@@@Z -@ stub -arch=win32 ??0ChangedStateException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0ChangedStateException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0ChangedStateException@Platform@@Q$AAA@XZ(ptr) platform_ChangedStateException_default_ctor +@ cdecl -arch=win64 ??0ChangedStateException@Platform@@QE$AAA@XZ(ptr) platform_ChangedStateException_default_ctor @ stub -arch=win32 ?Equals@int16@default@@QAA_NP$AAVObject@Platform@@@Z @ stub -arch=win64 ?Equals@int16@default@@QEAA_NPE$AAVObject@Platform@@@Z @ stub -arch=win32 ?Equals@int32@default@@QAA_NP$AAVObject@Platform@@@Z @@ -46,8 +46,8 @@ @ stub -arch=i386 ?EventSourceGetTargetArray@Details@Platform@@YGPAXPAXPAUEventLock@12@@Z @ stub -arch=arm ?EventSourceGetTargetArray@Details@Platform@@YAPAXPAXPAUEventLock@12@@Z @ stub -arch=win64 ?EventSourceGetTargetArray@Details@Platform@@YAPEAXPEAXPEAUEventLock@12@@Z -@ stub -arch=win32 ??0ClassNotRegisteredException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0ClassNotRegisteredException@Platform@@QE$AAA@PE$AAVString@1@@Z +@ cdecl -arch=win32 ??0ClassNotRegisteredException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_ClassNotRegisteredException_hstring_ctor +@ cdecl -arch=win64 ??0ClassNotRegisteredException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_ClassNotRegisteredException_hstring_ctor @ stub -arch=i386 ?EventSourceGetTargetArrayEvent@Details@Platform@@YGPAXPAXIPBXPA_J@Z @ stub -arch=arm ?EventSourceGetTargetArrayEvent@Details@Platform@@YAPAXPAXIPBXPA_J@Z @ stub -arch=win64 ?EventSourceGetTargetArrayEvent@Details@Platform@@YAPEAXPEAXIPEBXPEA_J@Z @@ -76,8 +76,8 @@ @ stdcall -arch=i386 ?GetActivationFactoryByPCWSTR@@YGJPAXAAVGuid@Platform@@PAPAX@Z(wstr ptr ptr) GetActivationFactoryByPCWSTR @ stdcall -arch=arm ?GetActivationFactoryByPCWSTR@@YAJPAXAAVGuid@Platform@@PAPAX@Z(wstr ptr ptr) GetActivationFactoryByPCWSTR @ stdcall -arch=win64 ?GetActivationFactoryByPCWSTR@@YAJPEAXAEAVGuid@Platform@@PEAPEAX@Z(wstr ptr ptr) GetActivationFactoryByPCWSTR -@ stub -arch=win32 ??0ClassNotRegisteredException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0ClassNotRegisteredException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0ClassNotRegisteredException@Platform@@Q$AAA@XZ(ptr) platform_ClassNotRegisteredException_default_ctor +@ cdecl -arch=win64 ??0ClassNotRegisteredException@Platform@@QE$AAA@XZ(ptr) platform_ClassNotRegisteredException_default_ctor @ stub -arch=win32 ?GetCmdArguments@Details@Platform@@YAPAPA_WPAH@Z @ stub -arch=win64 ?GetCmdArguments@Details@Platform@@YAPEAPEA_WPEAH@Z @ stub -arch=win32 ?GetHashCode@Attribute@Metadata@Platform@@Q$AAAHXZ @@ -120,8 +120,8 @@ @ stub -arch=win64 ?GetHashCode@int64@default@@QEAAHXZ @ stub -arch=win32 ?GetHashCode@int8@default@@QAAHXZ @ stub -arch=win64 ?GetHashCode@int8@default@@QEAAHXZ -@ stub -arch=win32 ??0DisconnectedException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0DisconnectedException@Platform@@QE$AAA@PE$AAVString@1@@Z +@ cdecl -arch=win32 ??0DisconnectedException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_DisconnectedException_hstring_ctor +@ cdecl -arch=win64 ??0DisconnectedException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_DisconnectedException_hstring_ctor @ stub -arch=win32 ?GetHashCode@uint16@default@@QAAHXZ @ stub -arch=win64 ?GetHashCode@uint16@default@@QEAAHXZ @ stub -arch=win32 ?GetHashCode@uint32@default@@QAAHXZ @@ -147,8 +147,8 @@ @ stub -arch=win64 ?GetProxyImpl@Details@Platform@@YAJPEAUIUnknown@@AEBU_GUID@@0PEAPEAU3@@Z @ stub -arch=win32 ?GetType@Boolean@Platform@@QAAP$AAVType@2@XZ @ stub -arch=win64 ?GetType@Boolean@Platform@@QEAAPE$AAVType@2@XZ -@ stub -arch=win32 ??0DisconnectedException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0DisconnectedException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0DisconnectedException@Platform@@Q$AAA@XZ(ptr) platform_DisconnectedException_default_ctor +@ cdecl -arch=win64 ??0DisconnectedException@Platform@@QE$AAA@XZ(ptr) platform_DisconnectedException_default_ctor @ stub -arch=win32 ?GetType@Guid@Platform@@QAAP$AAVType@2@XZ @ stub -arch=win64 ?GetType@Guid@Platform@@QEAAPE$AAVType@2@XZ @ stub -arch=win32 ?GetType@Object@Platform@@Q$AAAP$AAVType@2@XZ @@ -192,8 +192,8 @@ @ stub -arch=win64 ?IntersectsWith@Rect@Foundation@Windows@@QEAA_NV123@@Z @ stub -arch=win32 ?Invert@Matrix3D@Media3D@Media@Xaml@UI@Windows@@QAAXXZ @ stub -arch=win64 ?Invert@Matrix3D@Media3D@Media@Xaml@UI@Windows@@QEAAXXZ -@ stub -arch=win32 ??0Exception@Platform@@Q$AAA@H@Z -@ stub -arch=win64 ??0Exception@Platform@@QE$AAA@H@Z +@ cdecl -arch=win32 ??0Exception@Platform@@Q$AAA@H@Z(ptr long) platform_Exception_default_ctor +@ cdecl -arch=win64 ??0Exception@Platform@@QE$AAA@H@Z(ptr long) platform_Exception_default_ctor @ stub -arch=win32 ?ReCreateException@Exception@Platform@@SAP$AAV12@H@Z @ stub -arch=win64 ?ReCreateException@Exception@Platform@@SAPE$AAV12@H@Z @ stub -arch=win32 ?ReferenceEquals@Object@Platform@@SA_NP$AAV12@0@Z @@ -221,8 +221,8 @@ @ stub -arch=i386 ?TerminateModule@Details@Platform@@YG_NPAVModuleBase@1WRL@Microsoft@@@Z @ stub -arch=arm ?TerminateModule@Details@Platform@@YA_NPAVModuleBase@1WRL@Microsoft@@@Z @ stub -arch=win64 ?TerminateModule@Details@Platform@@YA_NPEAVModuleBase@1WRL@Microsoft@@@Z -@ stub -arch=win32 ??0Exception@Platform@@Q$AAA@HP$AAVString@1@@Z -@ stub -arch=win64 ??0Exception@Platform@@QE$AAA@HPE$AAVString@1@@Z +@ cdecl -arch=win32 ??0Exception@Platform@@Q$AAA@HP$AAVString@1@@Z(ptr long ptr) platform_Exception_hstring_ctor +@ cdecl -arch=win64 ??0Exception@Platform@@QE$AAA@HPE$AAVString@1@@Z(ptr long ptr) platform_Exception_hstring_ctor @ stub -arch=win32 ?ToInt32@IntPtr@Platform@@QAAHXZ @ stub -arch=win64 ?ToInt32@IntPtr@Platform@@QEAAHXZ @ stub -arch=win32 ?ToString@Attribute@Metadata@Platform@@Q$AAAP$AAVString@3@XZ @@ -245,8 +245,8 @@ @ stub -arch=win64 ?ToString@STAThreadAttribute@Platform@@QE$AAAPE$AAVString@2@XZ @ stub -arch=win32 ?<Dispose>@String@Platform@@U$AAAXXZ @ stub -arch=win64 ?<Dispose>@String@Platform@@UE$AAAXXZ -@ stub -arch=win32 ??0FailureException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0FailureException@Platform@@QE$AAA@PE$AAVString@1@@Z +@ cdecl -arch=win32 ??0FailureException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_FailureException_hstring_ctor +@ cdecl -arch=win64 ??0FailureException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_FailureException_hstring_ctor @ cdecl -arch=win32 ?ToString@Type@Platform@@U$AAAP$AAVString@2@XZ(ptr) platform_type_ToString @ cdecl -arch=win64 ?ToString@Type@Platform@@UE$AAAPE$AAVString@2@XZ(ptr) platform_type_ToString @ stub -arch=win32 ?ToString@ValueType@Platform@@Q$AAAP$AAVString@2@XZ @@ -267,8 +267,8 @@ @ stub -arch=win64 ?ToString@int8@default@@QEAAPE$AAVString@Platform@@XZ @ stub -arch=win32 ?ToString@uint16@default@@QAAP$AAVString@Platform@@XZ @ stub -arch=win64 ?ToString@uint16@default@@QEAAPE$AAVString@Platform@@XZ -@ stub -arch=win32 ??0FailureException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0FailureException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0FailureException@Platform@@Q$AAA@XZ(ptr) platform_FailureException_default_ctor +@ cdecl -arch=win64 ??0FailureException@Platform@@QE$AAA@XZ(ptr) platform_FailureException_default_ctor @ stub -arch=win32 ?ToString@uint32@default@@QAAP$AAVString@Platform@@XZ @ stub -arch=win64 ?ToString@uint32@default@@QEAAPE$AAVString@Platform@@XZ @ stub -arch=win32 ?ToString@uint64@default@@QAAP$AAVString@Platform@@XZ @@ -355,8 +355,8 @@ @ cdecl -arch=win64 ?get@FullName@Type@Platform@@QE$AAAPE$AAVString@3@XZ(ptr) platform_type_get_FullName @ stub -arch=win32 ?get@HasInverse@Matrix3D@Media3D@Media@Xaml@UI@Windows@@QAA_NXZ @ stub -arch=win64 ?get@HasInverse@Matrix3D@Media3D@Media@Xaml@UI@Windows@@QEAA_NXZ -@ stub -arch=win32 ??0InvalidArgumentException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0InvalidArgumentException@Platform@@QE$AAA@PE$AAVString@1@@Z +@ cdecl -arch=win32 ??0InvalidArgumentException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_InvalidArgumentException_hstring_ctor +@ cdecl -arch=win64 ??0InvalidArgumentException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_InvalidArgumentException_hstring_ctor @ cdecl -arch=win32 ?get@Message@Exception@Platform@@Q$AAAP$AAVString@3@XZ(ptr) platform_exception_get_Message @ cdecl -arch=win64 ?get@Message@Exception@Platform@@QE$AAAPE$AAVString@3@XZ(ptr) platform_exception_get_Message @ stub ?get@ObjectCount@Heap@Details@Platform@@SAHXZ @@ -366,46 +366,46 @@ @ stub ?set@BreakOnAllocationId@Heap@Details@Platform@@SAXH@Z @ stub ?set@BreakOnFreeId@Heap@Details@Platform@@SAXH@Z @ stub ?set@TrackingLevel@Heap@Details@Platform@@SAXW4HeapAllocationTrackingLevel@34@@Z -@ stub -arch=win32 ??0InvalidArgumentException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0InvalidArgumentException@Platform@@QE$AAA@XZ -@ stub -arch=win32 ??0InvalidCastException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0InvalidCastException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0InvalidCastException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0InvalidCastException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0InvalidArgumentException@Platform@@Q$AAA@XZ(ptr) platform_InvalidArgumentException_default_ctor +@ cdecl -arch=win64 ??0InvalidArgumentException@Platform@@QE$AAA@XZ(ptr) platform_InvalidArgumentException_default_ctor +@ cdecl -arch=win32 ??0InvalidCastException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_InvalidCastException_hstring_ctor +@ cdecl -arch=win64 ??0InvalidCastException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_InvalidCastException_hstring_ctor +@ cdecl -arch=win32 ??0InvalidCastException@Platform@@Q$AAA@XZ(ptr) platform_InvalidCastException_default_ctor +@ cdecl -arch=win64 ??0InvalidCastException@Platform@@QE$AAA@XZ(ptr) platform_InvalidCastException_default_ctor @ stub -arch=win32 ??0MTAThreadAttribute@Platform@@Q$AAA@XZ @ stub -arch=win64 ??0MTAThreadAttribute@Platform@@QE$AAA@XZ @ stub -arch=win32 ?<Dispose>@Type@Platform@@U$AAAXXZ @ stub -arch=win64 ?<Dispose>@Type@Platform@@UE$AAAXXZ -@ stub -arch=win32 ??0NotImplementedException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0NotImplementedException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0NotImplementedException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0NotImplementedException@Platform@@QE$AAA@XZ -@ stub -arch=win32 ??0NullReferenceException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0NullReferenceException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0NullReferenceException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0NullReferenceException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0NotImplementedException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_NotImplementedException_hstring_ctor +@ cdecl -arch=win64 ??0NotImplementedException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_NotImplementedException_hstring_ctor +@ cdecl -arch=win32 ??0NotImplementedException@Platform@@Q$AAA@XZ(ptr) platform_NotImplementedException_default_ctor +@ cdecl -arch=win64 ??0NotImplementedException@Platform@@QE$AAA@XZ(ptr) platform_NotImplementedException_default_ctor +@ cdecl -arch=win32 ??0NullReferenceException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_NullReferenceException_hstring_ctor +@ cdecl -arch=win64 ??0NullReferenceException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_NullReferenceException_hstring_ctor +@ cdecl -arch=win32 ??0NullReferenceException@Platform@@Q$AAA@XZ(ptr) platform_NullReferenceException_default_ctor +@ cdecl -arch=win64 ??0NullReferenceException@Platform@@QE$AAA@XZ(ptr) platform_NullReferenceException_default_ctor @ stub -arch=win32 ??0Object@Platform@@Q$AAA@XZ @ stub -arch=win64 ??0Object@Platform@@QE$AAA@XZ -@ stub -arch=win32 ??0ObjectDisposedException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0ObjectDisposedException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0ObjectDisposedException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0ObjectDisposedException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0ObjectDisposedException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_ObjectDisposedException_hstring_ctor +@ cdecl -arch=win64 ??0ObjectDisposedException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_ObjectDisposedException_hstring_ctor +@ cdecl -arch=win32 ??0ObjectDisposedException@Platform@@Q$AAA@XZ(ptr) platform_ObjectDisposedException_default_ctor +@ cdecl -arch=win64 ??0ObjectDisposedException@Platform@@QE$AAA@XZ(ptr) platform_ObjectDisposedException_default_ctor @ stub -arch=win32 ??0OnePhaseConstructedAttribute@CompilerServices@Runtime@Platform@@Q$AAA@XZ @ stub -arch=win64 ??0OnePhaseConstructedAttribute@CompilerServices@Runtime@Platform@@QE$AAA@XZ -@ stub -arch=win32 ??0OperationCanceledException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0OperationCanceledException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0OperationCanceledException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0OperationCanceledException@Platform@@QE$AAA@XZ -@ stub -arch=win32 ??0AccessDeniedException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0AccessDeniedException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0OutOfBoundsException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0OutOfBoundsException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0OutOfBoundsException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0OutOfBoundsException@Platform@@QE$AAA@XZ -@ stub -arch=win32 ??0OutOfMemoryException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0OutOfMemoryException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0OutOfMemoryException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0OutOfMemoryException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0OperationCanceledException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_OperationCanceledException_hstring_ctor +@ cdecl -arch=win64 ??0OperationCanceledException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_OperationCanceledException_hstring_ctor +@ cdecl -arch=win32 ??0OperationCanceledException@Platform@@Q$AAA@XZ(ptr) platform_OperationCanceledException_default_ctor +@ cdecl -arch=win64 ??0OperationCanceledException@Platform@@QE$AAA@XZ(ptr) platform_OperationCanceledException_default_ctor +@ cdecl -arch=win32 ??0AccessDeniedException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_AccessDeniedException_hstring_ctor +@ cdecl -arch=win64 ??0AccessDeniedException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_AccessDeniedException_hstring_ctor +@ cdecl -arch=win32 ??0OutOfBoundsException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_OutOfBoundsException_hstring_ctor +@ cdecl -arch=win64 ??0OutOfBoundsException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_OutOfBoundsException_hstring_ctor +@ cdecl -arch=win32 ??0OutOfBoundsException@Platform@@Q$AAA@XZ(ptr) platform_OutOfBoundsException_default_ctor +@ cdecl -arch=win64 ??0OutOfBoundsException@Platform@@QE$AAA@XZ(ptr) platform_OutOfBoundsException_default_ctor +@ cdecl -arch=win32 ??0OutOfMemoryException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_OutOfMemoryException_hstring_ctor +@ cdecl -arch=win64 ??0OutOfMemoryException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_OutOfMemoryException_hstring_ctor +@ cdecl -arch=win32 ??0OutOfMemoryException@Platform@@Q$AAA@XZ(ptr) platform_OutOfMemoryException_default_ctor +@ cdecl -arch=win64 ??0OutOfMemoryException@Platform@@QE$AAA@XZ(ptr) platform_OutOfMemoryException_default_ctor @ stub -arch=win32 ??0Rect@Foundation@Windows@@QAA@VPoint@12@0@Z @ stub -arch=win64 ??0Rect@Foundation@Windows@@QEAA@VPoint@12@0@Z @ stub -arch=win32 ??0Rect@Foundation@Windows@@QAA@VPoint@12@VSize@12@@Z @@ -418,8 +418,8 @@ @ stub -arch=win64 ??0SizeT@Platform@@QEAA@H@Z @ stub -arch=win32 ??0SizeT@Platform@@QAA@PAX@Z @ stub -arch=win64 ??0SizeT@Platform@@QEAA@PEAX@Z -@ stub -arch=win32 ??0AccessDeniedException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0AccessDeniedException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0AccessDeniedException@Platform@@Q$AAA@XZ(ptr) platform_AccessDeniedException_default_ctor +@ cdecl -arch=win64 ??0AccessDeniedException@Platform@@QE$AAA@XZ(ptr) platform_AccessDeniedException_default_ctor @ stub -arch=win32 ??0Type@Platform@@Q$AAA@P$AAVObject@1@@Z @ stub -arch=win64 ??0Type@Platform@@QE$AAA@PE$AAVObject@1@@Z @ stub -arch=win32 ??0Type@Platform@@Q$AAA@VIntPtr@1@@Z @@ -428,10 +428,10 @@ @ stub -arch=win64 ??0Type@Platform@@QE$AAA@VTypeName@Interop@Xaml@UI@Windows@@@Z @ stub -arch=win32 ??0ValueType@Platform@@Q$AAA@XZ @ stub -arch=win64 ??0ValueType@Platform@@QE$AAA@XZ -@ stub -arch=win32 ??0WrongThreadException@Platform@@Q$AAA@P$AAVString@1@@Z -@ stub -arch=win64 ??0WrongThreadException@Platform@@QE$AAA@PE$AAVString@1@@Z -@ stub -arch=win32 ??0WrongThreadException@Platform@@Q$AAA@XZ -@ stub -arch=win64 ??0WrongThreadException@Platform@@QE$AAA@XZ +@ cdecl -arch=win32 ??0WrongThreadException@Platform@@Q$AAA@P$AAVString@1@@Z(ptr ptr) platform_WrongThreadException_hstring_ctor +@ cdecl -arch=win64 ??0WrongThreadException@Platform@@QE$AAA@PE$AAVString@1@@Z(ptr ptr) platform_WrongThreadException_hstring_ctor +@ cdecl -arch=win32 ??0WrongThreadException@Platform@@Q$AAA@XZ(ptr) platform_WrongThreadException_default_ctor +@ cdecl -arch=win64 ??0WrongThreadException@Platform@@QE$AAA@XZ(ptr) platform_WrongThreadException_default_ctor @ stub -arch=win32 ??0char16@default@@QAA@_W@Z @ stub -arch=win64 ??0char16@default@@QEAA@_W@Z @ stub -arch=win32 ??0float32@default@@QAA@M@Z @@ -476,8 +476,8 @@ @ stub ??PDuration@Xaml@UI@Windows@@SA_NV0123@0@Z @ stub -arch=win32 ?AlignedAllocate@Heap@Details@Platform@@SAPAXII@Z @ stub -arch=win64 ?AlignedAllocate@Heap@Details@Platform@@SAPEAX_K00@Z -@ stub -arch=win32 ??0COMException@Platform@@Q$AAA@H@Z -@ stub -arch=win64 ??0COMException@Platform@@QE$AAA@H@Z +@ cdecl -arch=win32 ??0COMException@Platform@@Q$AAA@H@Z(ptr long) platform_COMException_default_ctor +@ cdecl -arch=win64 ??0COMException@Platform@@QE$AAA@H@Z(ptr long) platform_COMException_default_ctor @ stub -arch=win32 ?AlignedAllocate@Heap@Details@Platform@@SAPAXIII@Z @ stub -arch=win64 ?AlignedAllocate@Heap@Details@Platform@@SAPEAX_K0@Z @ stub -arch=win32 ?AlignedAllocateException@Heap@Details@Platform@@SAPAXII@Z @@ -497,8 +497,8 @@ @ cdecl -arch=win32 ?AllocateException@Heap@Details@Platform@@SAPAXII@Z(long long) AllocateExceptionWithWeakRef @ cdecl -arch=win64 ?AllocateException@Heap@Details@Platform@@SAPEAX_K@Z(long) AllocateException @ stub ?Compare@Duration@Xaml@UI@Windows@@SAHV1234@0@Z -@ stub -arch=win32 ??0COMException@Platform@@Q$AAA@HP$AAVString@1@@Z -@ stub -arch=win64 ??0COMException@Platform@@QE$AAA@HPE$AAVString@1@@Z +@ cdecl -arch=win32 ??0COMException@Platform@@Q$AAA@HP$AAVString@1@@Z(ptr long ptr) platform_COMException_hstring_ctor +@ cdecl -arch=win64 ??0COMException@Platform@@QE$AAA@HPE$AAVString@1@@Z(ptr long ptr) platform_COMException_hstring_ctor @ stub -arch=win32 ?Contains@Rect@Foundation@Windows@@QAA_NVPoint@23@@Z @ stub -arch=win64 ?Contains@Rect@Foundation@Windows@@QEAA_NVPoint@23@@Z @ cdecl -arch=win32 ?CreateException@Exception@Platform@@SAP$AAV12@H@Z(long) CreateException
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/tests/vccorlib.c | 8 ++--- dlls/vccorlib140/vccorlib.c | 51 ++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index 0818ef42e3e..c2522abd434 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -579,8 +579,7 @@ static void test_Allocate(void) /* AllocateException allocates additional space for two pointer-width fields, with the second field used as the * back-pointer to the exception data. */ addr = pAllocateException(0); - todo_wine ok(!!addr, "got addr %p\n", addr); - if (!addr) return; + ok(!!addr, "got addr %p\n", addr); ptr = (void **)((ULONG_PTR)addr - sizeof(void *)); *ptr = NULL; /* The write should succeed. */ base = (void **)((ULONG_PTR)addr - 2 * sizeof(void *)); @@ -757,7 +756,7 @@ static void test_AllocateWithWeakRef_inline(void) ok(object->weakref->ref_strong == 1, "got ref_strong %lu\n", object->weakref->ref_strong); ok(object->weakref->object == &object->IUnknown_iface, "got object %p != %p\n", object->weakref->object, &object->IUnknown_iface); - todo_wine ok(object->weakref->unknown == 0, "got unknown %d\n", object->weakref->unknown); + ok(object->weakref->unknown == 0, "got unknown %d\n", object->weakref->unknown); ok(!object->weakref->is_exception, "got is_exception %d\n", object->weakref->is_exception); /* The object is allocate within the weakref. */ ok((char *)object->weakref == ((char *)object - sizeof(struct control_block)), "got %p != %p\n", object->weakref, @@ -844,8 +843,7 @@ static void test_AllocateWithWeakRef(void)
/* AllocateExceptionWithWeakRef will not store the control block inline, regardless of the size. */ object = pAllocateExceptionWithWeakRef(offsetof(struct unknown_impl, weakref), sizeof(struct unknown_impl)); - todo_wine ok(object != NULL, "got object %p\n", object); - if (!object) return; + ok(object != NULL, "got object %p\n", object);
object->strong_ref_free_val = -100; ok(object->weakref != NULL, "got weakref %p\n", object->weakref); diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index 43723d9b5f8..67a12cad72b 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -101,10 +101,21 @@ void *__cdecl Allocate(size_t size) return addr; }
+struct exception_alloc +{ + void *unknown; + void *exception_inner; + char data[0]; +}; + void *__cdecl AllocateException(size_t size) { - FIXME("(%Iu): stub!\n", size); - return NULL; + struct exception_alloc *base; + + TRACE("(%Iu)\n", size); + + base = Allocate(offsetof(struct exception_alloc, data[size])); + return &base->data; }
void __cdecl Free(void *addr) @@ -116,7 +127,11 @@ void __cdecl Free(void *addr)
void __cdecl FreeException(void *addr) { - FIXME("(%p): stub!\n", addr); + struct exception_alloc *base = CONTAINING_RECORD(addr, struct exception_alloc, data); + + TRACE("(%p)\n", addr); + + free(base); }
struct control_block @@ -126,7 +141,8 @@ struct control_block LONG ref_strong; IUnknown *object; bool is_inline; - UINT16 unknown; + UINT8 unknown; + bool is_exception; #ifdef _WIN32 char _padding[4]; #endif @@ -228,14 +244,30 @@ void *__cdecl AllocateWithWeakRef(ptrdiff_t offset, size_t size) weakref->object = object; weakref->ref_strong = weakref->ref_weak = 1; weakref->unknown = 0; + weakref->is_exception = FALSE;
return weakref->object; }
void *__cdecl AllocateExceptionWithWeakRef(ptrdiff_t offset, size_t size) { - FIXME("(%Iu, %Iu): stub!\n", offset, size); - return NULL; + struct control_block *weakref; + void *excp; + + TRACE("(%Iu, %Iu)\n", offset, size); + + /* AllocateExceptionWithWeakRef does not store the control block inline, regardless of size. */ + weakref = Allocate(sizeof(*weakref)); + excp = AllocateException(size); + *(struct control_block **)((char *)excp + offset) = weakref; + weakref->IWeakReference_iface.lpVtbl = &control_block_vtbl; + weakref->object = excp; + weakref->ref_strong = weakref->ref_weak = 1; + weakref->is_inline = FALSE; + weakref->unknown = 0; + weakref->is_exception = TRUE; + + return excp; }
DEFINE_THISCALL_WRAPPER(control_block_ReleaseTarget, 4) @@ -247,7 +279,12 @@ void __thiscall control_block_ReleaseTarget(struct control_block *weakref)
if (weakref->is_inline || ReadNoFence(&weakref->ref_strong) >= 0) return; if ((object = InterlockedCompareExchangePointer((void *)&weakref->object, NULL, weakref->object))) - Free(object); + { + if (weakref->is_exception) + FreeException(object); + else + Free(object); + } }
struct __abi_type_descriptor
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/Makefile.in | 2 +- dlls/vccorlib140/cxx.h | 23 +- dlls/vccorlib140/tests/vccorlib.c | 9 +- dlls/vccorlib140/vccorlib.c | 487 ++++++++++++++++++++++++++---- 4 files changed, 449 insertions(+), 72 deletions(-)
diff --git a/dlls/vccorlib140/Makefile.in b/dlls/vccorlib140/Makefile.in index 13d54aa369e..08fb0d7c679 100644 --- a/dlls/vccorlib140/Makefile.in +++ b/dlls/vccorlib140/Makefile.in @@ -1,5 +1,5 @@ MODULE = vccorlib140.dll -IMPORTS = combase +IMPORTS = combase oleaut32 vcruntime140
SOURCES = \ vccorlib.c diff --git a/dlls/vccorlib140/cxx.h b/dlls/vccorlib140/cxx.h index b803d35a283..0ce3275886c 100644 --- a/dlls/vccorlib140/cxx.h +++ b/dlls/vccorlib140/cxx.h @@ -139,21 +139,21 @@ static void init_ ## name ## _rtti(char *base) \
#ifndef CXX_USE_RVA
-#define DEFINE_CXX_TYPE(type, dtor, ...) \ +#define DEFINE_CXX_TYPE(type, ...) \ static const cxx_type_info type ## _cxx_type_info[1] = \ - { { 0, &type ##_type_info, { 0, -1, 0 }, sizeof(type), THISCALL(type ##_copy_ctor) } }; \ + { { 0, &type ##_type_info, { 0, -1, 0 }, sizeof(type), NULL } }; \ \ static const cxx_type_info_table type ## _cxx_type_table = \ { ARRAY_SIZE(((const void *[]){ NULL, __VA_ARGS__ })), { type ## _cxx_type_info, __VA_ARGS__ } }; \ \ static const cxx_exception_type type ## _exception_type = \ - { 0, THISCALL(dtor), NULL, & type ## _cxx_type_table }; + { 16, NULL, NULL, & type ## _cxx_type_table };
#define INIT_CXX_TYPE(name,base) (void)name ## _exception_type
#elif defined __WINE_PE_BUILD
-#define DEFINE_CXX_TYPE2(type, dtor, ...) \ +#define DEFINE_CXX_TYPE2(type, ...) \ extern const cxx_type_info type ## _cxx_type_info[1]; \ extern const cxx_exception_type type ## _exception_type; \ void __asm_dummy_ ## type ## _exception_type(void) \ @@ -163,25 +163,25 @@ void __asm_dummy_ ## type ## _exception_type(void) \ ".long 0\n\t" \ ".rva " #type "_type_info\n\t" \ ".long 0, -1, 0, %c0\n\t" \ - ".rva " #type "_copy_ctor\n" \ + ".long 0\n\t" \ #type "_type_table:\n\t" \ ".long %c1\n\t" \ ".rva " #__VA_ARGS__ "\n\t" \ __ASM_GLOBL(#type "_exception_type") "\n\t" \ + ".long 16\n\t" \ ".long 0\n\t" \ - ".rva " #dtor "\n\t" \ ".long 0\n\t" \ ".rva " #type "_type_table\n\t" \ :: "i"(sizeof(type)), "i"(ARRAY_SIZE(((const void *[]){ &__VA_ARGS__ }))) ); \ } -#define DEFINE_CXX_TYPE(type, dtor, ...) \ - DEFINE_CXX_TYPE2(type, dtor, type ## _cxx_type_info, ##__VA_ARGS__) +#define DEFINE_CXX_TYPE(type, ...) \ + DEFINE_CXX_TYPE2(type, type ## _cxx_type_info, ##__VA_ARGS__)
#define INIT_CXX_TYPE(name,base) /* nothing to do */
#else /* CXX_USE_RVA */
-#define DEFINE_CXX_TYPE(type, dtor, ...) \ +#define DEFINE_CXX_TYPE(type, ...) \ static cxx_type_info type ## _cxx_type_info[1] = \ { { 0, 0xdeadbeef, { 0, -1, 0 }, sizeof(type), 0xdeadbeef } }; \ \ @@ -192,10 +192,11 @@ static cxx_exception_type type ##_exception_type; \ static void init_ ## type ## _cxx(char *base) \ { \ type ## _cxx_type_info[0].type_info = (char *)&type ## _type_info - base; \ - type ## _cxx_type_info[0].copy_ctor = (char *)type ## _copy_ctor - base; \ + type ## _cxx_type_info[0].copy_ctor = NULL; \ for (unsigned int i = 0; i < ARRAY_SIZE(type ## _cxx_type_classes); i++) \ type ## _cxx_type_table.info[i] = (char *)type ## _cxx_type_classes[i] - base; \ - type ## _exception_type.destructor = (char *)dtor - base; \ + type ## _exception_type.flags = 16; \ + type ## _exception_type.destructor = NULL; \ type ## _exception_type.type_info_table = (char *)&type ## _cxx_type_table - base; \ }
diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index c2522abd434..740b1c9565c 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -1354,17 +1354,12 @@ static void test_exceptions(void)
cur_test = &test_cases[i]; obj = pCreateException(cur_test->hr); - todo_wine ok(obj != NULL, "got obj %p\n", obj); - if (!obj) - { - winetest_pop_context(); - continue; - } + ok(obj != NULL, "got obj %p\n", obj);
inspectable = (IInspectable *)obj; /* Verify that the IMarshal field is lazily-initialized. */ ok((ULONG_PTR)obj->marshal == UINTPTR_MAX, "got marshal %p\n", obj->marshal); - todo_wine check_interface(inspectable, &IID_IMarshal); + check_interface(inspectable, &IID_IMarshal); ok(obj->marshal != NULL && (ULONG_PTR)obj->marshal != UINTPTR_MAX, "got marshal %p\n", obj->marshal);
test_interface_layout(obj, &IID_IUnknown, &obj->IInspectable_iface); diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index 67a12cad72b..9c71a36393e 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -20,11 +20,13 @@ #define COBJMACROS
#include <stdbool.h> +#include <stdint.h>
#include "initguid.h" #include "roapi.h" #include "weakreference.h" #include "winstring.h" +#include "roerrorapi.h" #define WIDL_using_Windows_Foundation #include "windows.foundation.h" #include "wine/asm.h" @@ -88,6 +90,10 @@ HRESULT WINAPI GetIidsFn(unsigned int count, unsigned int *copied, const GUID *s return S_OK; }
+void WINAPI DECLSPEC_NORETURN __abi_WinRTraiseCOMException(HRESULT); +void WINAPI DECLSPEC_NORETURN __abi_WinRTraiseOutOfMemoryException(void); +void WINAPI DECLSPEC_NORETURN __abi_WinRTraiseInvalidArgumentException(void); + void *__cdecl Allocate(size_t size) { void *addr; @@ -95,9 +101,8 @@ void *__cdecl Allocate(size_t size) TRACE("(%Iu)\n", size);
addr = malloc(size); - /* TODO: Throw a COMException on allocation failure. */ if (!addr) - FIXME("allocation failure\n"); + __abi_WinRTraiseOutOfMemoryException(); return addr; }
@@ -421,8 +426,7 @@ static const char *debugstr_abi_type_descriptor(const struct __abi_type_descript void *WINAPI __abi_make_type_id(const struct __abi_type_descriptor *desc) { /* TODO: - * Implement IEquatable and IPrintable. - * Throw a COMException if CoCreateFreeThreadedMarshaler fails. */ + * Implement IEquatable and IPrintable. */ struct platform_type *obj; HRESULT hr;
@@ -436,9 +440,8 @@ void *WINAPI __abi_make_type_id(const struct __abi_type_descriptor *desc) hr = CoCreateFreeThreadedMarshaler((IUnknown *)&obj->IInspectable_iface, &obj->marshal); if (FAILED(hr)) { - FIXME("CoCreateFreeThreadedMarshaler failed: %#lx\n", hr); Free(obj); - return NULL; + __abi_WinRTraiseCOMException(hr); } return &obj->IInspectable_iface; } @@ -604,30 +607,10 @@ void *WINAPI CreateValue(int typecode, const void *val)
IPropertyValueStatics_Release(statics); if (FAILED(hr)) - { - FIXME("Failed to create IPropertyValue object: %#lx\n", hr); - return NULL; - } + __abi_WinRTraiseCOMException(hr); return obj; }
-void *__cdecl CreateExceptionWithMessage(HRESULT hr, HSTRING msg) -{ - FIXME("(%#lx, %s): stub!\n", hr, debugstr_hstring(msg)); - return NULL; -} - -void *__cdecl CreateException(HRESULT hr) -{ - FIXME("(%#lx): stub!\n", hr); - return NULL; -} - -void WINAPI __abi_WinRTraiseCOMException(HRESULT hr) -{ - FIXME("(%#lx): stub!\n", hr); -} - #define WINRT_EXCEPTIONS \ WINRT_EXCEPTION(AccessDenied, E_ACCESSDENIED) \ WINRT_EXCEPTION(ChangedState, E_CHANGED_STATE) \ @@ -644,58 +627,456 @@ void WINAPI __abi_WinRTraiseCOMException(HRESULT hr) WINRT_EXCEPTION(OutOfMemory, E_OUTOFMEMORY) \ WINRT_EXCEPTION(WrongThread, RPC_E_WRONG_THREAD)
-#define WINRT_EXCEPTION(name, hr) \ - void WINAPI __abi_WinRTraise##name##Exception(void) \ - { \ - FIXME("(): stub!\n"); \ - } \ - void *__cdecl platform_##name##Exception_default_ctor(void *this) \ - { \ - FIXME("(%p): stub!\n", this); \ - return this; \ - } \ - void *__cdecl platform_##name##Exception_hstring_ctor(void *this, HSTRING msg) \ - { \ - FIXME("(%p, %s): stub!\n", this, debugstr_hstring(msg)); \ - return this; \ +/* 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 + * should use that once it has been implemented. */ +struct exception_inner +{ + /* This only gets set when the exception is thrown. */ + BSTR message1; + /* Likewise, but can also be set by CreateExceptionWithMessage. */ + BSTR message2; + void *unknown1; + void *unknown2; + HRESULT hr; + /* Only gets set when the exception is thrown. */ + IRestrictedErrorInfo *error_info; + const cxx_exception_type *exception_type; + /* Set to 32 and 64 on 32 and 64-bit platforms respectively, not sure what the purpose is. */ + UINT32 unknown3; + void *unknown4; +}; +struct platform_exception +{ + IInspectable IInspectable_iface; + const void *IPrintable_iface; + const void *IEquatable_iface; + IClosable IClosable_iface; + struct exception_inner inner; + /* Exceptions use the weakref control block for reference counting, even though they don't implement + * IWeakReferenceSource. */ + struct control_block *control_block; + /* This is lazily initialized, i.e, only when QueryInterface(IID_IMarshal) gets called. The default value is + * UINTPTR_MAX/-1 */ + IUnknown *marshal; +}; + +static inline struct platform_exception *impl_platform_exception_from_IInspectable(IInspectable *iface) +{ + return CONTAINING_RECORD(iface, struct platform_exception, IInspectable_iface); +} + +static HRESULT WINAPI platform_exception_QueryInterface(IInspectable *iface, const GUID *iid, void **out) +{ + struct platform_exception *impl = impl_platform_exception_from_IInspectable(iface); + + TRACE("(%p, %s, %p)\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IInspectable) || + IsEqualGUID(iid, &IID_IAgileObject)) + { + IInspectable_AddRef((*out = &impl->IInspectable_iface)); + return S_OK; + } + if (IsEqualGUID(iid, &IID_IClosable)) + { + IClosable_AddRef((*out = &impl->IClosable_iface)); + return S_OK; + } + if (IsEqualGUID(iid, &IID_IMarshal)) + { + IUnknown *marshal, *old; + HRESULT hr; + + if ((ULONG_PTR)impl->marshal != UINTPTR_MAX) + return IUnknown_QueryInterface(impl->marshal, iid, out); + /* Try initializing impl->marshal. */ + if (FAILED(hr = CoCreateFreeThreadedMarshaler((IUnknown *)&impl->IInspectable_iface, &marshal))) + return hr; + old = InterlockedCompareExchangePointer((void *)&impl->marshal, marshal, (void *)UINTPTR_MAX); + if ((ULONG_PTR)old != UINTPTR_MAX) /* Someone else has already set impl->marshal, use it. */ + IUnknown_Release(marshal); + return IUnknown_QueryInterface(impl->marshal, iid, out); }
-WINRT_EXCEPTIONS + ERR("%s not implemented, returning E_NOTINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI platform_exception_AddRef(IInspectable *iface) +{ + struct platform_exception *impl = impl_platform_exception_from_IInspectable(iface); + TRACE("(%p)\n", iface); + return InterlockedIncrement(&impl->control_block->ref_strong); +} + +static ULONG WINAPI platform_exception_Release(IInspectable *iface) +{ + struct platform_exception *impl = impl_platform_exception_from_IInspectable(iface); + ULONG ref = InterlockedDecrement(&impl->control_block->ref_strong); + + TRACE("(%p)\n", iface); + + if (!ref) + { + SysFreeString(impl->inner.message1); + SysFreeString(impl->inner.message2); + if ((ULONG_PTR)impl->marshal != UINTPTR_MAX) + IUnknown_Release((IUnknown *)impl->marshal); + /* Because Exception objects are never allocated inline, we don't need to use ReleaseTarget. */ + IWeakReference_Release(&impl->control_block->IWeakReference_iface); + FreeException(impl); + } + return ref; +} + +static HRESULT WINAPI platform_exception_GetRuntimeClassName(IInspectable *iface, HSTRING *class_name) +{ + struct platform_exception *impl = impl_platform_exception_from_IInspectable(iface); + const WCHAR *buf; + + TRACE("(%p, %p)\n", iface, class_name); + +#define WINRT_EXCEPTION(name, hr) case (hr): buf = L"Platform." #name "Exception"; break; + switch (impl->inner.hr) + { + WINRT_EXCEPTIONS #undef WINRT_EXCEPTION + default: + buf = L"Platform.COMException"; + break; + } + return WindowsCreateString(buf, wcslen(buf), class_name); +} + +static HRESULT WINAPI platform_exception_GetIids(IInspectable *iface, ULONG *count, IID **iids) +{ + TRACE("(%p, %p, %p)\n", iface, count, iids); + + *count = 0; + *iids = NULL; + return S_OK; +} + +static HRESULT WINAPI platform_exception_GetTrustLevel(IInspectable *iface, TrustLevel *level) +{ + FIXME("(%p, %p)\n", iface, level); + return S_OK; +}
-void *__cdecl platform_Exception_default_ctor(void *this, HRESULT hr) +DEFINE_IINSPECTABLE_(platform_exception_closable, IClosable, struct platform_exception, impl_exception_from_IClosable, + IClosable_iface, &impl->IInspectable_iface); + +static HRESULT WINAPI platform_exception_closable_Close(IClosable *iface) { - FIXME("(%p, %#lx): stub!\n", this, hr); + FIXME("(%p)\n", iface); + return E_NOTIMPL; +} + +#ifdef _WIN64 +#define EXCEPTION_RTTI_NAME(name) ".PE$AAV" #name "Exception@Platform@@" +#else +#define EXCEPTION_RTTI_NAME(name) ".P$AAV" #name "Exception@Platform@@" +#endif + +#ifdef _WIN64 +DEFINE_RTTI_DATA(Exception, 0, ".PE$AAVException@Platform@@"); +#else +DEFINE_RTTI_DATA(Exception, 0, ".P$AAVException@Platform@@"); +#endif +typedef IInspectable Exception; +DEFINE_CXX_TYPE(Exception); + +DEFINE_RTTI_DATA(platform_Exception, 0, "?.AVException@Platform@@"); +COM_VTABLE_RTTI_START(IInspectable, platform_Exception) +COM_VTABLE_ENTRY(platform_exception_QueryInterface) +COM_VTABLE_ENTRY(platform_exception_AddRef) +COM_VTABLE_ENTRY(platform_exception_Release) +COM_VTABLE_ENTRY(platform_exception_GetIids) +COM_VTABLE_ENTRY(platform_exception_GetRuntimeClassName) +COM_VTABLE_ENTRY(platform_exception_GetTrustLevel) +COM_VTABLE_RTTI_END; + +DEFINE_RTTI_DATA(platform_Exception_closable, offsetof(struct platform_exception, IClosable_iface), + "?.AVException@Platform@@") +COM_VTABLE_RTTI_START(IClosable, platform_Exception_closable) +COM_VTABLE_ENTRY(platform_exception_closable_QueryInterface) +COM_VTABLE_ENTRY(platform_exception_closable_AddRef) +COM_VTABLE_ENTRY(platform_exception_closable_Release) +COM_VTABLE_ENTRY(platform_exception_closable_GetIids) +COM_VTABLE_ENTRY(platform_exception_closable_GetRuntimeClassName) +COM_VTABLE_ENTRY(platform_exception_closable_GetTrustLevel) +COM_VTABLE_ENTRY(platform_exception_closable_Close) +COM_VTABLE_RTTI_END; + +DEFINE_RTTI_DATA(COMException, 0, EXCEPTION_RTTI_NAME(COM), Exception_rtti_base_descriptor); +typedef IInspectable COMException; +DEFINE_CXX_TYPE(COMException, Exception_cxx_type_info); + +DEFINE_RTTI_DATA(platform_COMException, 0, ".?AVCOMException@Platform@@"); +COM_VTABLE_RTTI_START(IInspectable, platform_COMException) +COM_VTABLE_ENTRY(platform_exception_QueryInterface) +COM_VTABLE_ENTRY(platform_exception_AddRef) +COM_VTABLE_ENTRY(platform_exception_Release) +COM_VTABLE_ENTRY(platform_exception_GetIids) +COM_VTABLE_ENTRY(platform_exception_GetRuntimeClassName) +COM_VTABLE_ENTRY(platform_exception_GetTrustLevel) +COM_VTABLE_RTTI_END; + +DEFINE_RTTI_DATA(platform_COMException_closable, offsetof(struct platform_exception, IClosable_iface), + ".?AVCOMException@Platform@@") +COM_VTABLE_RTTI_START(IClosable, platform_COMException_closable) +COM_VTABLE_ENTRY(platform_exception_closable_QueryInterface) +COM_VTABLE_ENTRY(platform_exception_closable_AddRef) +COM_VTABLE_ENTRY(platform_exception_closable_Release) +COM_VTABLE_ENTRY(platform_exception_closable_GetIids) +COM_VTABLE_ENTRY(platform_exception_closable_GetRuntimeClassName) +COM_VTABLE_ENTRY(platform_exception_closable_GetTrustLevel) +COM_VTABLE_ENTRY(platform_exception_closable_Close) +COM_VTABLE_RTTI_END; + +struct platform_exception *__cdecl platform_Exception_default_ctor(struct platform_exception *this, HRESULT hr) +{ + struct exception_alloc *base = CONTAINING_RECORD(this, struct exception_alloc, data); + + TRACE("(%p, %#lx)\n", this, hr); + + this->IInspectable_iface.lpVtbl = &platform_Exception_vtable.vtable; + this->IClosable_iface.lpVtbl = &platform_Exception_closable_vtable.vtable; + this->IEquatable_iface = this->IPrintable_iface = NULL; + + memset(&this->inner, 0, sizeof(this->inner)); + base->exception_inner = &this->inner; + this->inner.exception_type = &Exception_exception_type; + this->inner.hr = hr; + this->inner.unknown3 = sizeof(void *) == 8 ? 64 : 32; + + this->marshal = (IUnknown *)UINTPTR_MAX; + + /* Native throws InvalidArgumentException if hr is S_OK or S_FALSE. */ + if (SUCCEEDED(hr)) + __abi_WinRTraiseInvalidArgumentException(); return this; }
-void *__cdecl platform_Exception_hstring_ctor(void *this, HRESULT hr, HSTRING msg) +struct platform_exception *__cdecl platform_Exception_hstring_ctor(struct platform_exception *this, HRESULT hr, + HSTRING msg) { - FIXME("(%p, %#lx, %s): stub!\n", this, hr, debugstr_hstring(msg)); + const WCHAR *buf; + BOOL has_null; + UINT32 len; + + TRACE("(%p, %#lx, %s)\n", this, hr, debugstr_hstring(msg)); + + platform_Exception_default_ctor(this, hr); + if (WindowsIsStringEmpty(msg)) return this; + + /* Native throws InvalidArgumentException if msg has an embedded NUL byte. */ + if (FAILED(hr = WindowsStringHasEmbeddedNull(msg, &has_null))) + __abi_WinRTraiseCOMException(hr); + else if (has_null) + __abi_WinRTraiseInvalidArgumentException(); + + buf = WindowsGetStringRawBuffer(msg, &len); + if (len && !(this->inner.message2 = SysAllocStringLen(buf, len))) + __abi_WinRTraiseOutOfMemoryException(); return this; }
-void *__cdecl platform_COMException_default_ctor(void *this, HRESULT hr) +struct platform_exception *__cdecl platform_COMException_default_ctor(struct platform_exception *this, HRESULT hr) { - FIXME("(%p, %#lx): stub!\n", this, hr); + TRACE("(%p, %#lx)\n", this, hr); + + platform_Exception_default_ctor(this, hr); + + this->IInspectable_iface.lpVtbl = &platform_COMException_vtable.vtable; + this->IClosable_iface.lpVtbl = &platform_COMException_closable_vtable.vtable; + this->inner.exception_type = &COMException_exception_type; return this; }
-void *__cdecl platform_COMException_hstring_ctor(void *this, HRESULT hr, HSTRING msg) +struct platform_exception *__cdecl platform_COMException_hstring_ctor(struct platform_exception *this, HRESULT hr, + HSTRING msg) { - FIXME("(%p, %#lx, %s): stub!\n", this, hr, debugstr_hstring(msg)); + TRACE("(%p, %#lx, %s)\n", this, hr, debugstr_hstring(msg)); + + platform_Exception_hstring_ctor(this, hr, msg); + + this->IInspectable_iface.lpVtbl = &platform_COMException_vtable.vtable; + this->IClosable_iface.lpVtbl = &platform_COMException_closable_vtable.vtable; + this->inner.exception_type = &COMException_exception_type; return this; }
-HSTRING __cdecl platform_exception_get_Message(void *excp) +#define WINRT_EXCEPTION(name, hr) \ + DEFINE_RTTI_DATA(name##Exception, 0, EXCEPTION_RTTI_NAME(name), COMException_rtti_base_descriptor, \ + Exception_rtti_base_descriptor); \ + typedef COMException name##Exception; \ + DEFINE_CXX_TYPE(name##Exception, COMException_cxx_type_info, Exception_cxx_type_info); \ + \ + DEFINE_RTTI_DATA(platform_##name##Exception, 0, ".?AV" #name "Exception@Platform@@"); \ + COM_VTABLE_RTTI_START(IInspectable, platform_##name##Exception) \ + COM_VTABLE_ENTRY(platform_exception_QueryInterface) \ + COM_VTABLE_ENTRY(platform_exception_AddRef) \ + COM_VTABLE_ENTRY(platform_exception_Release) \ + COM_VTABLE_ENTRY(platform_exception_GetIids) \ + COM_VTABLE_ENTRY(platform_exception_GetRuntimeClassName) \ + COM_VTABLE_ENTRY(platform_exception_GetTrustLevel) \ + COM_VTABLE_RTTI_END; \ + \ + DEFINE_RTTI_DATA(platform_##name##Exception_closable, offsetof(struct platform_exception, IClosable_iface), \ + ".?AV" #name "Exception@Platform@@"); \ + COM_VTABLE_RTTI_START(IClosable, platform_##name##Exception_closable) \ + COM_VTABLE_ENTRY(platform_exception_closable_QueryInterface) \ + COM_VTABLE_ENTRY(platform_exception_closable_AddRef) \ + COM_VTABLE_ENTRY(platform_exception_closable_Release) \ + COM_VTABLE_ENTRY(platform_exception_closable_GetIids) \ + COM_VTABLE_ENTRY(platform_exception_closable_GetRuntimeClassName) \ + COM_VTABLE_ENTRY(platform_exception_closable_GetTrustLevel) \ + COM_VTABLE_ENTRY(platform_exception_closable_Close) \ + COM_VTABLE_RTTI_END; \ + \ + struct platform_exception *__cdecl platform_##name##Exception_default_ctor(struct platform_exception *this) \ + { \ + TRACE("(%p)\n", this); \ + platform_COMException_default_ctor(this, (hr)); \ + this->IInspectable_iface.lpVtbl = &platform_##name##Exception_vtable.vtable; \ + this->IClosable_iface.lpVtbl = &platform_##name##Exception_closable_vtable.vtable; \ + this->inner.exception_type = &name##Exception_exception_type; \ + return this; \ + } \ + \ + struct platform_exception *__cdecl platform_##name##Exception_hstring_ctor(struct platform_exception *this, \ + HSTRING msg) \ + { \ + TRACE("(%p, %s)\n", this, debugstr_hstring(msg)); \ + platform_COMException_hstring_ctor(this, (hr), msg); \ + this->IInspectable_iface.lpVtbl = &platform_##name##Exception_vtable.vtable; \ + this->IClosable_iface.lpVtbl = &platform_##name##Exception_closable_vtable.vtable; \ + this->inner.exception_type = &name##Exception_exception_type; \ + return this; \ + } +WINRT_EXCEPTIONS +#undef EXCEPTION_RTTI_NAME +#undef WINRT_EXCEPTION + +static void init_exception(void *base) +{ + INIT_RTTI(Exception, base); + INIT_RTTI(platform_Exception, base); + +#define WINRT_EXCEPTION(name, ...) \ + do \ + { \ + INIT_RTTI(name##Exception, base); \ + INIT_RTTI(platform_exception_##name, base); \ + } while(0); + WINRT_EXCEPTION(COM); + WINRT_EXCEPTIONS +#undef WINRT_EXCEPTION +} + +void *__cdecl CreateExceptionWithMessage(HRESULT code, HSTRING msg) +{ + struct platform_exception *impl; + + TRACE("(%#lx, %s)\n", code, debugstr_hstring(msg)); + + impl = AllocateExceptionWithWeakRef(offsetof(struct platform_exception, control_block), sizeof(*impl)); + + #define WINRT_EXCEPTION(name, h) \ + case (h): \ + platform_##name##Exception_hstring_ctor(impl, msg); \ + break; + + switch (code) + { + WINRT_EXCEPTIONS; +#undef WINRT_EXCEPTION + default: + platform_COMException_hstring_ctor(impl, code, msg); + break; + } + + return &impl->IInspectable_iface; +} + +void *__cdecl CreateException(HRESULT hr) { - FIXME("(%p): stub!\n", excp); - return NULL; + TRACE("(%#lx)\n", hr); + return CreateExceptionWithMessage(hr, NULL); +} + +HSTRING __cdecl platform_exception_get_Message(struct platform_exception *this) +{ + HSTRING msg = NULL; + HRESULT hr = S_OK; + + TRACE("(%p)\n", this); + + if (this->inner.message2) + hr = WindowsCreateString(this->inner.message2, wcslen(this->inner.message2), &msg); + else + { + WCHAR buf[256]; + + if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, this->inner.hr, 0, buf, ARRAY_SIZE(buf), NULL)) + hr = WindowsCreateString(buf, wcslen(buf), &msg); + else + ERR("FormatMessageW failed: %lu\n", GetLastError()); + } + + if (FAILED(hr)) + __abi_WinRTraiseCOMException(hr); + return msg; +} + +extern void WINAPI DECLSPEC_NORETURN _CxxThrowException(void *, const cxx_exception_type *); + +static void DECLSPEC_NORETURN throw_exception(struct platform_exception *excp, const cxx_exception_type *type) +{ + if (excp->inner.message2) + { + excp->inner.message1 = SysAllocStringLen(excp->inner.message1, SysStringLen(excp->inner.message1)); + if (!excp->inner.message1) + __abi_WinRTraiseOutOfMemoryException(); + } + /* Thrown exceptions have a refcount of 2. */ + IInspectable_AddRef(&excp->IInspectable_iface); + _CxxThrowException(&excp, type); +} + +#define WINRT_EXCEPTION(name, hr) \ + void WINAPI DECLSPEC_NORETURN __abi_WinRTraise##name##Exception(void) \ + { \ + FIXME("(): semi-stub!\n"); \ + throw_exception(CreateException((hr)), &name##Exception_exception_type); \ + } +WINRT_EXCEPTIONS +#undef WINRT_EXCEPTION + +void WINAPI DECLSPEC_NORETURN __abi_WinRTraiseCOMException(HRESULT hr) +{ + FIXME("(%#lx): semi-stub!\n", hr); + + switch (hr) + { +#define WINRT_EXCEPTION(name, code) case (code): __abi_WinRTraise##name##Exception(); + WINRT_EXCEPTIONS; +#undef WINRT_EXCEPTION + default: + throw_exception(CreateException(hr), &COMException_exception_type); + } }
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) { if (reason == DLL_PROCESS_ATTACH) + { init_platform_type(inst); + init_exception(inst); + } return TRUE; }
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/cxx.h | 1 + dlls/vccorlib140/vccorlib.c | 23 +++++++++++++++++++++++ dlls/vccorlib140/vccorlib140.spec | 6 +++--- 3 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/dlls/vccorlib140/cxx.h b/dlls/vccorlib140/cxx.h index 0ce3275886c..f8f8fe08984 100644 --- a/dlls/vccorlib140/cxx.h +++ b/dlls/vccorlib140/cxx.h @@ -168,6 +168,7 @@ void __asm_dummy_ ## type ## _exception_type(void) \ ".long %c1\n\t" \ ".rva " #__VA_ARGS__ "\n\t" \ __ASM_GLOBL(#type "_exception_type") "\n\t" \ + /* All C++/CX exceptions set this field to 16, presumably for __abi__translateCurrentException? */ \ ".long 16\n\t" \ ".long 0\n\t" \ ".long 0\n\t" \ diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index 9c71a36393e..584ac5c03f5 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -1071,6 +1071,29 @@ void WINAPI DECLSPEC_NORETURN __abi_WinRTraiseCOMException(HRESULT hr) } }
+#define TYPE_FLAG_CPPCX 16 +extern const void **__cdecl __current_exception(void); + +HRESULT WINAPI __abi_translateCurrentException(bool unknown) +{ + const struct platform_exception *excp; + const EXCEPTION_RECORD *record; + const cxx_exception_type *type; + + FIXME("(%d): semi-stub!\n", unknown); + + record = *__current_exception(); + /* Native aborts if: + * There is no exception being currently handled. + * There is no associated exception object (_CxxThrowException(NULL, ...) was called). + * There is no associated cxx_exception_type param (_CxxThrowException(..., NULL) was called). + * A non C++/CX exception has been thrown. */ + if (!record || !(excp = (struct platform_exception *)record->ExceptionInformation[1]) || + !(type = (cxx_exception_type *)record->ExceptionInformation[2]) || !(type->flags & TYPE_FLAG_CPPCX)) + abort(); + return excp->inner.hr; +} + BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved) { if (reason == DLL_PROCESS_ATTACH) diff --git a/dlls/vccorlib140/vccorlib140.spec b/dlls/vccorlib140/vccorlib140.spec index ad236ceb48f..396c69b74ce 100644 --- a/dlls/vccorlib140/vccorlib140.spec +++ b/dlls/vccorlib140/vccorlib140.spec @@ -338,9 +338,9 @@ @ stdcall -arch=win64 ?__abi_make_type_id@@YAPE$AAVType@Platform@@AEBU__abi_type_descriptor@@@Z(ptr) __abi_make_type_id @ stub -arch=win32 ??0IntPtr@Platform@@QAA@PAX@Z @ stub -arch=win64 ??0IntPtr@Platform@@QEAA@PEAX@Z -@ stub -arch=i386 ?__abi_translateCurrentException@@YGJ_N@Z -@ stub -arch=arm ?__abi_translateCurrentException@@YAJ_N@Z -@ stub -arch=win64 ?__abi_translateCurrentException@@YAJ_N@Z +@ stdcall -arch=i386 ?__abi_translateCurrentException@@YGJ_N@Z(long) __abi_translateCurrentException +@ stdcall -arch=arm ?__abi_translateCurrentException@@YAJ_N@Z(long) __abi_translateCurrentException +@ stdcall -arch=win64 ?__abi_translateCurrentException@@YAJ_N@Z(long) __abi_translateCurrentException @ stub -arch=i386 ?__getActivationFactoryByHSTRING@@YGJPAUHSTRING__@@AAVGuid@Platform@@PAPAX@Z @ stub -arch=arm ?__getActivationFactoryByHSTRING@@YAJPAUHSTRING__@@AAVGuid@Platform@@PAPAX@Z @ stub -arch=win64 ?__getActivationFactoryByHSTRING@@YAJPEAUHSTRING__@@AEAVGuid@Platform@@PEAPEAX@Z