Skip to content

Commit

Permalink
cppwinrt should not call LoadLibrary anywhere unless new WINRT_REG_FR…
Browse files Browse the repository at this point in the history
…EE define is defined, re-activating regfree behavior
  • Loading branch information
dmachaj committed Nov 6, 2024
1 parent e53db0f commit a346936
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 11 deletions.
37 changes: 27 additions & 10 deletions strings/base_activation.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ namespace winrt::impl

using library_handle = handle_type<library_traits>;

// 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 <bool isSameInterfaceAsIActivationFactory>
WINRT_IMPL_NOINLINE hresult get_runtime_activation_factory_impl(param::hstring const& name, winrt::guid const& guid, void** result) noexcept
{
Expand All @@ -30,15 +34,8 @@ namespace winrt::impl

if (hr == impl::error_not_initialized)
{
auto usage = reinterpret_cast<int32_t(__stdcall*)(void** cookie) noexcept>(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);
}

Expand All @@ -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<IErrorInfo> error_info;
WINRT_IMPL_GetErrorInfo(0, error_info.put_void());

Expand Down Expand Up @@ -79,7 +87,7 @@ namespace winrt::impl
continue;
}

if constexpr (isSameInterfaceAsIActivationFactory)
if (isSameInterfaceAsIActivationFactory)
{
*result = library_factory.detach();
library.detach();
Expand All @@ -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 <typename Interface>
hresult get_runtime_activation_factory(param::hstring const& name, void** result) noexcept
{
Expand Down
2 changes: 2 additions & 0 deletions strings/base_agile_ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ namespace winrt::impl

using update_module_lock = module_lock_updater<true>;

#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
{
Expand Down
3 changes: 3 additions & 0 deletions strings/base_extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,17 @@ 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);

int32_t __stdcall WINRT_IMPL_SetErrorInfo(uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8);
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);
Expand Down
3 changes: 2 additions & 1 deletion test/old_tests/UnitTests/pch.h
Original file line number Diff line number Diff line change
@@ -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

Expand Down
1 change: 1 addition & 0 deletions test/test/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "mingw_com_support.h"

#define WINRT_LEAN_AND_MEAN
#define WINRT_REG_FREE
#include <unknwn.h>
#include "winrt/Windows.Foundation.Collections.h"
#include "winrt/Windows.Foundation.Numerics.h"
Expand Down
1 change: 1 addition & 0 deletions test/test_fast/pch.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#define WINRT_REG_FREE
#include "catch.hpp"
#include "winrt/Windows.Foundation.Collections.h"

Expand Down
1 change: 1 addition & 0 deletions test/test_slow/pch.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#define WINRT_REG_FREE
#include "catch.hpp"
#include "winrt/Windows.Foundation.Collections.h"

Expand Down

0 comments on commit a346936

Please sign in to comment.