Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cppwinrt should not call LoadLibrary anywhere unless new WINRT_REG_FREE define is defined, re-activating regfree behavior #1446

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 27 additions & 10 deletions strings/base_activation.h
Original file line number Diff line number Diff line change
@@ -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
{
@@ -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);
dmachaj marked this conversation as resolved.
Show resolved Hide resolved
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<IErrorInfo> error_info;
WINRT_IMPL_GetErrorInfo(0, error_info.put_void());

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

if constexpr (isSameInterfaceAsIActivationFactory)
if (isSameInterfaceAsIActivationFactory)
dmachaj marked this conversation as resolved.
Show resolved Hide resolved
{
*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 <typename Interface>
hresult get_runtime_activation_factory(param::hstring const& name, void** result) noexcept
{
2 changes: 2 additions & 0 deletions strings/base_agile_ref.h
Original file line number Diff line number Diff line change
@@ -71,10 +71,12 @@ namespace winrt::impl

using update_module_lock = module_lock_updater<true>;

#ifdef WINRT_REG_FREE
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ifdef makes it so that there is definitely no LoadLibrary usage when regfree is inactive.

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
{
3 changes: 3 additions & 0 deletions strings/base_extern.h
Original file line number Diff line number Diff line change
@@ -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);
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

1 change: 1 addition & 0 deletions test/test/pch.h
Original file line number Diff line number Diff line change
@@ -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"
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"

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"