diff --git a/strings/base_abi.h b/strings/base_abi.h index 1ad5e827e..6a88266b9 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -70,8 +70,8 @@ namespace winrt::impl virtual int32_t __stdcall unused2() noexcept = 0; virtual int32_t __stdcall unused3() noexcept = 0; virtual int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0; + virtual int32_t __stdcall Remove(void*) noexcept = 0; virtual int32_t __stdcall unused4() noexcept = 0; - virtual int32_t __stdcall unused5() noexcept = 0; }; struct __declspec(novtable) IWeakReference : unknown_abi diff --git a/strings/base_implements.h b/strings/base_implements.h index 2457b80b4..0722aec5f 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1198,6 +1198,14 @@ namespace winrt::impl }; #endif + inline com_ptr get_static_lifetime_map() + { + auto const lifetime_factory = get_activation_factory(L"Windows.ApplicationModel.Core.CoreApplication"); + Windows::Foundation::IUnknown collection; + check_hresult(lifetime_factory->GetCollection(put_abi(collection))); + return collection.as(); + } + template auto make_factory() -> typename impl::implements_default_interface::type { @@ -1209,10 +1217,7 @@ namespace winrt::impl } else { - auto const lifetime_factory = get_activation_factory(L"Windows.ApplicationModel.Core.CoreApplication"); - Windows::Foundation::IUnknown collection; - check_hresult(lifetime_factory->GetCollection(put_abi(collection))); - auto const map = collection.as(); + auto const map = get_static_lifetime_map(); param::hstring const name{ name_of() }; void* result{}; map->Lookup(get_abi(name), &result); @@ -1304,6 +1309,16 @@ WINRT_EXPORT namespace winrt } } + template + inline void clear_factory_static_lifetime() + { + auto unregister = [map = impl::get_static_lifetime_map()](param::hstring name) + { + map->Remove(get_abi(name)); + }; + ((unregister(name_of())), ...); + } + template struct implements : impl::producers, impl::base_implements::type { diff --git a/test/old_tests/Component/Events.cpp b/test/old_tests/Component/Events.cpp index 732569531..842f23556 100644 --- a/test/old_tests/Component/Events.cpp +++ b/test/old_tests/Component/Events.cpp @@ -74,25 +74,51 @@ namespace winrt::Component::factory_implementation bool Events::TestStaticLifetime() { + auto GetReferenceCount = [this]() + { + AddRef(); + return Release(); + }; + // Capture current reference count. - AddRef(); - auto refcount = Release(); + auto refcount = GetReferenceCount(); // Reset constructor count. s_constructorCount = 0; - auto self = make_self(); - if (self.get() != this) + // make_self should return a reference to ourselves + // since we are static_lifetime. + if (make_self().get() != this) { return false; } - self = nullptr; // Refcount should be unchanged. + if (refcount != GetReferenceCount()) + { + return false; + } + // Should not have been constructed spuriously. - AddRef(); - auto new_refcount = Release(); + if (s_constructorCount != 0) + { + return false; + } + + // Clear the static lifetime. That should drop the reference count. + clear_factory_static_lifetime(); + if (refcount == GetReferenceCount()) + { + return false; + } + + // Making a new object should put a different instance into + // the static lifetime. + if (make_self().get() == this) + { + return false; + } - return refcount == new_refcount && s_constructorCount == 0; + return true; } }