-- v2: vccorlib140: Implement {Get, Resolve}WeakReference.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/tests/vccorlib.c | 137 ++++++++++++++++++++++++++++++ dlls/vccorlib140/vccorlib.c | 12 +++ dlls/vccorlib140/vccorlib140.spec | 12 +-- 3 files changed, 155 insertions(+), 6 deletions(-)
diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index c4f669d8190..bda38adfbc6 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -163,6 +163,8 @@ static void *(__cdecl *p_platform_COMException_hstring_ctor)(void *, HRESULT, HS static void *(__cdecl *p_platform_##name##Exception_hstring_ctor)(void *, HSTRING); WINRT_EXCEPTIONS #undef WINRT_EXCEPTION +static IWeakReference *(WINAPI *p_GetWeakReference)(IUnknown *); +static IUnknown *(WINAPI *p_ResolveWeakReference)(const GUID *, IWeakReference **);
static void *(__cdecl *p__RTtypeid)(const void *); static const char *(__thiscall *p_type_info_name)(void *); @@ -230,6 +232,11 @@ static BOOL init(void) } while(0); WINRT_EXCEPTIONS #undef WINRT_EXCEPTION + p_GetWeakReference = (void *)GetProcAddress(hmod, + "?GetWeakReference@Details@Platform@@YAPAU__abi_IUnknown@@Q$ADVObject@2@@Z"); + p_ResolveWeakReference = (void *)GetProcAddress(hmod, + "?ResolveWeakReference@Details@Platform@@YAP$AAVObject@2@ABU_GUID@@PAPAU__abi_IUnknown@@@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"); @@ -279,6 +286,11 @@ static BOOL init(void) } while(0); WINRT_EXCEPTIONS #undef WINRT_EXCEPTION + p_GetWeakReference = (void *)GetProcAddress(hmod, + "?GetWeakReference@Details@Platform@@YAPEAU__abi_IUnknown@@QE$ADVObject@2@@Z"); + p_ResolveWeakReference = (void *)GetProcAddress(hmod, + "?ResolveWeakReference@Details@Platform@@YAPE$AAVObject@2@AEBU_GUID@@PEAPEAU__abi_IUnknown@@@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"); @@ -327,6 +339,11 @@ static BOOL init(void) } while(0); WINRT_EXCEPTIONS #undef WINRT_EXCEPTION + p_GetWeakReference = (void *)GetProcAddress(hmod, + "?GetWeakReference@Details@Platform@@YGPAU__abi_IUnknown@@Q$ADVObject@2@@Z"); + p_ResolveWeakReference = (void *)GetProcAddress(hmod, + "?ResolveWeakReference@Details@Platform@@YGP$AAVObject@2@ABU_GUID@@PAPAU__abi_IUnknown@@@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"); @@ -361,6 +378,8 @@ static BOOL init(void) } while(0); WINRT_EXCEPTIONS #undef WINRT_EXCEPTION + ok(p_GetWeakReference != NULL, "GetWeakReference not available.\n"); + ok(p_ResolveWeakReference != NULL, "ResolveWeakReference is 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"); @@ -883,6 +902,123 @@ static void test_AllocateWithWeakRef(void) ok(count == 0, "got count %lu\n", count); }
+struct weakref_src_impl +{ + IWeakReferenceSource IWeakReferenceSource_iface; + struct control_block *block; +}; + +static inline struct weakref_src_impl *impl_from_IWeakReferenceSource(IWeakReferenceSource *iface) +{ + return CONTAINING_RECORD(iface, struct weakref_src_impl, IWeakReferenceSource_iface); +} + +static HRESULT WINAPI weakref_src_QueryInterface(IWeakReferenceSource *iface, const GUID *iid, void **out) +{ + struct weakref_src_impl *impl = impl_from_IWeakReferenceSource(iface); + + if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IWeakReferenceSource)) + { + IWeakReferenceSource_AddRef((*out = &impl->IWeakReferenceSource_iface)); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI weakref_src_AddRef(IWeakReferenceSource *iface) +{ + struct weakref_src_impl *impl = impl_from_IWeakReferenceSource(iface); + return InterlockedIncrement(&impl->block->ref_strong); +} + +static ULONG WINAPI weakref_src_Release(IWeakReferenceSource *iface) +{ + struct weakref_src_impl *impl = impl_from_IWeakReferenceSource(iface); + ULONG ref = InterlockedDecrement(&impl->block->ref_strong); + + if (!ref) + { + struct control_block *block = impl->block; + /* ReleaseTarget only frees the object if ref_strong < 0. */ + WriteNoFence(&impl->block->ref_strong, -1); + call_func1(pReleaseTarget, block); + IWeakReference_Release(&block->IWeakReference_iface); + } + return ref; +} + +static HRESULT WINAPI weakref_src_GetWeakReference(IWeakReferenceSource *iface, IWeakReference **out) +{ + struct weakref_src_impl *impl = impl_from_IWeakReferenceSource(iface); + IWeakReference_AddRef((*out = &impl->block->IWeakReference_iface)); + return S_OK; +} + +static const IWeakReferenceSourceVtbl weakref_src_vtbl = +{ + weakref_src_QueryInterface, + weakref_src_AddRef, + weakref_src_Release, + weakref_src_GetWeakReference, +}; + +static void test_GetWeakReference(void) +{ + struct weakref_src_impl *obj; + struct control_block *block; + IWeakReference *weakref; + IUnknown *unk; + ULONG count; + HRESULT hr; + + obj = pAllocateWithWeakRef(offsetof(struct weakref_src_impl, block), sizeof(*obj)); + ok(obj != NULL, "got impl %p\n", obj); + obj->IWeakReferenceSource_iface.lpVtbl = &weakref_src_vtbl; + block = obj->block; + + /* This is just a wrapper around QueryInterface(IID_IWeakReferenceSource) + IWeakReferenceSource::GetWeakReference. */ + weakref = p_GetWeakReference((IUnknown *)&obj->IWeakReferenceSource_iface); + todo_wine ok(weakref == &obj->block->IWeakReference_iface, "got weakref %p != %p\n", weakref, + &obj->block->IWeakReference_iface); + todo_wine ok(obj->block->ref_weak == 2, "got ref_weak %lu\n", obj->block->ref_weak); + ok(obj->block->ref_strong == 1, "got ref_strong %lu\n", obj->block->ref_strong); + if (!weakref) + { + skip("GetWeakReference failed.\n"); + IWeakReferenceSource_Release(&obj->IWeakReferenceSource_iface); + return; + } + + hr = IWeakReference_Resolve(weakref, &IID_IUnknown, (IInspectable **)&unk); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(unk != NULL, "got unk %p\n", unk); + count = IUnknown_Release(unk); + ok(count == 1, "got count %lu\n", count); + + /* Wrapper around IWeakReference_Resolve(*weakref, ...). */ + unk = p_ResolveWeakReference(&IID_IUnknown, &weakref); + ok(unk != NULL, "got unk %p\n", unk); + IUnknown_Release(unk); + count = IUnknown_Release(unk); + ok(count == 0, "got count %lu\n", count); + ok(block->ref_weak == 1, "got ref_weak %lu\n", block->ref_weak); + + unk = NULL; + hr = IWeakReference_Resolve(weakref, &IID_IUnknown, (IInspectable **)&unk); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(unk == NULL, "got unk %p\n", unk); + + count = IWeakReference_Release(weakref); + ok(count == 0, "got count %lu\n", count); + + /* ResolveWeakReference returns NULL if *weakref is NULL. */ + weakref = NULL; + unk = p_ResolveWeakReference(&IID_IUnknown, &weakref); + ok(unk == NULL, "got unk %p.\n", unk); +} + #define check_interface(o, i) check_interface_(__LINE__, (o), (i)) static void check_interface_(int line, void *obj, const GUID *iid) { @@ -1694,4 +1830,5 @@ START_TEST(vccorlib) test___abi_make_type_id(); test_CreateValue(); test_exceptions(); + test_GetWeakReference(); } diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index ca3a8ee42bc..4c5a027cf35 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -262,6 +262,18 @@ void __thiscall control_block_ReleaseTarget(struct control_block *weakref) } }
+IWeakReference *WINAPI GetWeakReference(IUnknown *obj) +{ + FIXME("(%p): stub!\n", obj); + return NULL; +} + +IUnknown *WINAPI ResolveWeakReference(const GUID *iid, IWeakReference **weakref) +{ + FIXME("(%s, %p): stub!\n", debugstr_guid(iid), weakref); + return NULL; +} + struct __abi_type_descriptor { const WCHAR *name; diff --git a/dlls/vccorlib140/vccorlib140.spec b/dlls/vccorlib140/vccorlib140.spec index 99b32fd1571..a34054a7994 100644 --- a/dlls/vccorlib140/vccorlib140.spec +++ b/dlls/vccorlib140/vccorlib140.spec @@ -179,9 +179,9 @@ @ stub -arch=win64 ?GetType@uint8@default@@QEAAPE$AAVType@Platform@@XZ @ cdecl -arch=win32 ?GetTypeCode@Type@Platform@@SA?AW4TypeCode@2@P$AAV12@@Z(ptr) platform_type_GetTypeCode @ cdecl -arch=win64 ?GetTypeCode@Type@Platform@@SA?AW4TypeCode@2@PE$AAV12@@Z(ptr) platform_type_GetTypeCode -@ stub -arch=i386 ?GetWeakReference@Details@Platform@@YGPAU__abi_IUnknown@@Q$ADVObject@2@@Z -@ stub -arch=arm ?GetWeakReference@Details@Platform@@YAPAU__abi_IUnknown@@Q$ADVObject@2@@Z -@ stub -arch=win64 ?GetWeakReference@Details@Platform@@YAPEAU__abi_IUnknown@@QE$ADVObject@2@@Z +@ stdcall -arch=i386 ?GetWeakReference@Details@Platform@@YGPAU__abi_IUnknown@@Q$ADVObject@2@@Z(ptr) GetWeakReference +@ stdcall -arch=arm ?GetWeakReference@Details@Platform@@YAPAU__abi_IUnknown@@Q$ADVObject@2@@Z(ptr) GetWeakReference +@ stdcall -arch=win64 ?GetWeakReference@Details@Platform@@YAPEAU__abi_IUnknown@@QE$ADVObject@2@@Z(ptr) GetWeakReference @ stub -arch=i386 ?InitControlBlock@ControlBlock@Details@Platform@@AAEXPAX_N11@Z @ stub -arch=arm ?InitControlBlock@ControlBlock@Details@Platform@@AAAXPAX_N11@Z @ stub -arch=win64 ?InitControlBlock@ControlBlock@Details@Platform@@AEAAXPEAX_N11@Z @@ -209,9 +209,9 @@ @ thiscall -arch=i386 ?ReleaseTarget@ControlBlock@Details@Platform@@AAEXXZ(ptr) control_block_ReleaseTarget @ cdecl -arch=arm ?ReleaseTarget@ControlBlock@Details@Platform@@AAAXXZ(ptr) control_block_ReleaseTarget @ cdecl -arch=win64 ?ReleaseTarget@ControlBlock@Details@Platform@@AEAAXXZ(ptr) control_block_ReleaseTarget -@ stub -arch=i386 ?ResolveWeakReference@Details@Platform@@YGP$AAVObject@2@ABU_GUID@@PAPAU__abi_IUnknown@@@Z -@ stub -arch=arm ?ResolveWeakReference@Details@Platform@@YAP$AAVObject@2@ABU_GUID@@PAPAU__abi_IUnknown@@@Z -@ stub -arch=win64 ?ResolveWeakReference@Details@Platform@@YAPE$AAVObject@2@AEBU_GUID@@PEAPEAU__abi_IUnknown@@@Z +@ stdcall -arch=i386 ?ResolveWeakReference@Details@Platform@@YGP$AAVObject@2@ABU_GUID@@PAPAU__abi_IUnknown@@@Z(ptr ptr) ResolveWeakReference +@ stdcall -arch=arm ?ResolveWeakReference@Details@Platform@@YAP$AAVObject@2@ABU_GUID@@PAPAU__abi_IUnknown@@@Z(ptr ptr) ResolveWeakReference +@ stdcall -arch=win64 ?ResolveWeakReference@Details@Platform@@YAPE$AAVObject@2@AEBU_GUID@@PEAPEAU__abi_IUnknown@@@Z(ptr ptr) ResolveWeakReference @ stub -arch=i386 ?RunApplicationServer@Details@Platform@@YGXPAPAVModuleBase@1WRL@Microsoft@@PAPAU__abi_Module@@PB_W@Z @ stub -arch=arm ?RunApplicationServer@Details@Platform@@YAXPAPAVModuleBase@1WRL@Microsoft@@PAPAU__abi_Module@@PB_W@Z @ stub -arch=win64 ?RunApplicationServer@Details@Platform@@YAXPEAPEAVModuleBase@1WRL@Microsoft@@PEAPEAU__abi_Module@@PEB_W@Z
From: Vibhav Pant vibhavp@gmail.com
--- dlls/vccorlib140/tests/vccorlib.c | 10 ++-------- dlls/vccorlib140/vccorlib.c | 30 ++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/dlls/vccorlib140/tests/vccorlib.c b/dlls/vccorlib140/tests/vccorlib.c index bda38adfbc6..b901f5365d0 100644 --- a/dlls/vccorlib140/tests/vccorlib.c +++ b/dlls/vccorlib140/tests/vccorlib.c @@ -980,16 +980,10 @@ static void test_GetWeakReference(void)
/* This is just a wrapper around QueryInterface(IID_IWeakReferenceSource) + IWeakReferenceSource::GetWeakReference. */ weakref = p_GetWeakReference((IUnknown *)&obj->IWeakReferenceSource_iface); - todo_wine ok(weakref == &obj->block->IWeakReference_iface, "got weakref %p != %p\n", weakref, + ok(weakref == &obj->block->IWeakReference_iface, "got weakref %p != %p\n", weakref, &obj->block->IWeakReference_iface); - todo_wine ok(obj->block->ref_weak == 2, "got ref_weak %lu\n", obj->block->ref_weak); + ok(obj->block->ref_weak == 2, "got ref_weak %lu\n", obj->block->ref_weak); ok(obj->block->ref_strong == 1, "got ref_strong %lu\n", obj->block->ref_strong); - if (!weakref) - { - skip("GetWeakReference failed.\n"); - IWeakReferenceSource_Release(&obj->IWeakReferenceSource_iface); - return; - }
hr = IWeakReference_Resolve(weakref, &IID_IUnknown, (IInspectable **)&unk); ok(hr == S_OK, "got hr %#lx\n", hr); diff --git a/dlls/vccorlib140/vccorlib.c b/dlls/vccorlib140/vccorlib.c index 4c5a027cf35..baa825ef186 100644 --- a/dlls/vccorlib140/vccorlib.c +++ b/dlls/vccorlib140/vccorlib.c @@ -264,14 +264,36 @@ void __thiscall control_block_ReleaseTarget(struct control_block *weakref)
IWeakReference *WINAPI GetWeakReference(IUnknown *obj) { - FIXME("(%p): stub!\n", obj); - return NULL; + IWeakReferenceSource *src; + IWeakReference *ref; + HRESULT hr; + + TRACE("(%p)\n", obj); + + if (!obj) + __abi_WinRTraiseInvalidArgumentException(); + if (SUCCEEDED((hr = IUnknown_QueryInterface(obj, &IID_IWeakReferenceSource, (void **)&src)))) + { + hr = IWeakReferenceSource_GetWeakReference(src, &ref); + IWeakReferenceSource_Release(src); + } + if (FAILED(hr)) + __abi_WinRTraiseCOMException(hr); + + return ref; }
IUnknown *WINAPI ResolveWeakReference(const GUID *iid, IWeakReference **weakref) { - FIXME("(%s, %p): stub!\n", debugstr_guid(iid), weakref); - return NULL; + IUnknown *obj = NULL; + HRESULT hr; + + TRACE("(%s, %p)\n", debugstr_guid(iid), weakref); + + if (*weakref && FAILED((hr = IWeakReference_Resolve(*weakref, iid, (IInspectable **)&obj)))) + __abi_WinRTraiseCOMException(hr); + + return obj; }
struct __abi_type_descriptor
v2: * Throw InvalidArgumentException if GetWeakReference(NULL) is called.
This merge request was approved by Piotr Caban.