Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions strings/base_activation.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ namespace winrt::impl
template <typename Interface>
hresult get_runtime_activation_factory(param::hstring const& name, void** result) noexcept
{
if (winrt_activation_handler)
{
return winrt_activation_handler(*(void**)(&name), guid_of<Interface>(), result);
}

Comment on lines +24 to +28

Choose a reason for hiding this comment

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

This requires the custom activation handler to deal with all possible activation scenarios. In certain kinds of tests that might be an overkill. It would be nice to have a way for the custom handler to return a magic value signifying that it cannot handle that specific activation and the default activation procedure should just continue, something like:

        if (winrt_activation_handler)
        {
            if (auto hr = winrt_activation_handler(*(void**)(&name), guid_of<Interface>(), result);
                hr != E_NOTIMPL) {
                    return hr;
                }
        }
        ...

Copy link
Member

Choose a reason for hiding this comment

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

I agree - I've had need for this flexibility myself

static int32_t(__stdcall * handler)(void* classId, guid const& iid, void** factory) noexcept;

impl::load_runtime_function("RoGetActivationFactory", handler,
Expand Down
1 change: 1 addition & 0 deletions strings/base_extern.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
__declspec(selectany) int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {};
__declspec(selectany) void(__stdcall* winrt_suspend_handler)(void const* token) noexcept {};
__declspec(selectany) void(__stdcall* winrt_resume_handler)(void const* token) noexcept {};
__declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {};

extern "C"
{
Expand Down
52 changes: 52 additions & 0 deletions test/test/custom_activation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "winrt/Windows.Foundation.Numerics.h"
#include "catch.hpp"

using namespace winrt;
using namespace Windows::Foundation;

namespace
{
struct custom_factory : implements<custom_factory, IUriRuntimeClassFactory>
{
inline static Uri mock_uri{ nullptr };

Uri CreateUri(hstring const& value) const
{
REQUIRE(value == L"http://ignored.com");
return mock_uri;
}

Uri CreateWithRelativeUri(hstring const&, hstring const&) const
{
throw hresult_not_implemented();
}
};

int32_t __stdcall handler(void* classId, winrt::guid const& iid, void** factory) noexcept
{
bool expected = reinterpret_cast<hstring const&>(classId) == L"Windows.Foundation.Uri";
REQUIRE(expected);
REQUIRE(iid == guid_of<IUriRuntimeClassFactory>());

*factory = detach_abi(make<custom_factory>());
return 0;
}
}

TEST_CASE("custom_activation")
{
custom_factory::mock_uri = Uri(L"http://actual.com");
clear_factory_cache();

// Set up global handler
REQUIRE(!winrt_activation_handler);
winrt_activation_handler = handler;

// Windows.Foundation.Uri activation factory now returns mock object
auto uri = Uri(L"http://ignored.com");
REQUIRE(uri.Domain() == L"actual.com");

// Remove global handler
winrt_activation_handler = nullptr;
clear_factory_cache();
}
10 changes: 10 additions & 0 deletions test/test/test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,16 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="custom_activation.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="custom_error.cpp" />
<ClCompile Include="delegate.cpp" />
<ClCompile Include="delegates.cpp" />
Expand Down