diff --git a/strings/base_activation.h b/strings/base_activation.h index bb6be5ca1..b0a0cad52 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -18,6 +18,10 @@ namespace winrt::impl using library_handle = handle_type; + // This function pointer will be null unless one or more translation units in a binary define WINRT_REG_FREE before + // including winrt/base.h. If that is defined then the overall binary will support regfree COM activation. + inline hresult(*reg_free_factory_getter)(param::hstring const&, bool, guid const&, void**) = nullptr; + template WINRT_IMPL_NOINLINE hresult get_runtime_activation_factory_impl(param::hstring const& name, winrt::guid const& guid, void** result) noexcept { @@ -30,15 +34,8 @@ namespace winrt::impl if (hr == impl::error_not_initialized) { - auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); - - if (!usage) - { - return hr; - } - void* cookie; - usage(&cookie); + WINRT_IMPL_CoIncrementMTAUsage(&cookie); hr = WINRT_IMPL_RoGetActivationFactory(*(void**)(&name), guid, result); } @@ -47,6 +44,17 @@ namespace winrt::impl return 0; } + if (reg_free_factory_getter) + { + return reg_free_factory_getter(name, isSameInterfaceAsIActivationFactory, guid, result); + } + + return hr; + } + +#ifdef WINRT_REG_FREE + WINRT_IMPL_NOINLINE hresult reg_free_get_activation_factory(param::hstring const& name, bool isSameInterfaceAsIActivationFactory, winrt::guid const& guid, void** result) noexcept + { com_ptr error_info; WINRT_IMPL_GetErrorInfo(0, error_info.put_void()); @@ -79,7 +87,7 @@ namespace winrt::impl continue; } - if constexpr (isSameInterfaceAsIActivationFactory) + if (isSameInterfaceAsIActivationFactory) { *result = library_factory.detach(); library.detach(); @@ -93,9 +101,18 @@ namespace winrt::impl } WINRT_IMPL_SetErrorInfo(0, error_info.get()); - return hr; + return error_class_not_registered; } + // This file has been compiled by a translation unit with WINRT_REG_FREE defined. Fill in the reg_free_factory_getter function + // pointer so that regfree behavior is activated. + inline unsigned int reg_free_init = []() { + reg_free_factory_getter = reg_free_get_activation_factory; + return 0U; + }(); + +#endif // WINRT_REG_FREE + template hresult get_runtime_activation_factory(param::hstring const& name, void** result) noexcept { diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index b85cb7e61..0dc8bfcb3 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -71,10 +71,12 @@ namespace winrt::impl using update_module_lock = module_lock_updater; +#ifdef WINRT_REG_FREE inline void* load_library(wchar_t const* library) noexcept { return WINRT_IMPL_LoadLibraryExW(library, nullptr, 0x00001000 /* LOAD_LIBRARY_SEARCH_DEFAULT_DIRS */); } +#endif // WINRT_REG_FREE inline hresult get_agile_reference(winrt::guid const& iid, void* object, void** reference) noexcept { diff --git a/strings/base_extern.h b/strings/base_extern.h index c0e83e75a..9fc8827da 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -35,7 +35,9 @@ extern "C" int32_t __stdcall WINRT_IMPL_GetRestrictedErrorInfo(void**) noexcept WINRT_IMPL_LINK(GetRestrictedErrorInfo, 4); int32_t __stdcall WINRT_IMPL_SetRestrictedErrorInfo(void*) noexcept WINRT_IMPL_LINK(SetRestrictedErrorInfo, 4); +#ifdef WINRT_REG_FREE void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); +#endif // WINRT_REG_FREE int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8); @@ -43,6 +45,7 @@ extern "C" int32_t __stdcall WINRT_IMPL_GetErrorInfo(uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); void __stdcall WINRT_IMPL_CoUninitialize() noexcept WINRT_IMPL_LINK(CoUninitialize, 0); + int32_t __stdcall WINRT_IMPL_CoIncrementMTAUsage(void** cookie) noexcept WINRT_IMPL_LINK(CoIncrementMTAUsage, 4); int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); diff --git a/test/old_tests/UnitTests/pch.h b/test/old_tests/UnitTests/pch.h index 4b940b552..6b146a3bc 100644 --- a/test/old_tests/UnitTests/pch.h +++ b/test/old_tests/UnitTests/pch.h @@ -1,6 +1,7 @@ #pragma once -#define WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#define WINRT_REG_FREE #define WINRT_NATVIS #define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING diff --git a/test/test/pch.h b/test/test/pch.h index 24d65c225..b2392e14a 100644 --- a/test/test/pch.h +++ b/test/test/pch.h @@ -5,6 +5,7 @@ #include "mingw_com_support.h" #define WINRT_LEAN_AND_MEAN +#define WINRT_REG_FREE #include #include "winrt/Windows.Foundation.Collections.h" #include "winrt/Windows.Foundation.Numerics.h" diff --git a/test/test_fast/pch.h b/test/test_fast/pch.h index 97769b358..11dbff990 100644 --- a/test/test_fast/pch.h +++ b/test/test_fast/pch.h @@ -1,5 +1,6 @@ #pragma once +#define WINRT_REG_FREE #include "catch.hpp" #include "winrt/Windows.Foundation.Collections.h" diff --git a/test/test_slow/pch.h b/test/test_slow/pch.h index 97769b358..11dbff990 100644 --- a/test/test_slow/pch.h +++ b/test/test_slow/pch.h @@ -1,5 +1,6 @@ #pragma once +#define WINRT_REG_FREE #include "catch.hpp" #include "winrt/Windows.Foundation.Collections.h"