Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include "winrt/Windows.Foundation.h"
#include "catch.hpp"

#ifdef WINRT_WINDOWS_ABI
#error WINRT_WINDOWS_ABI must not be defined for this test.
#ifdef __IUnknown_INTERFACE_DEFINED__
#error __IUnknown_INTERFACE_DEFINED__ must not be defined for this test.
#endif

using namespace winrt;
Expand All @@ -11,7 +11,7 @@ using namespace Windows::Foundation;
namespace
{
// This is a variation of conditional_implements.cpp that builds without the Windows headers
// and validates that the conditional logic still works when WINRT_WINDOWS_ABI is not defined
// and validates that the conditional logic still works when __IUnknown_INTERFACE_DEFINED__ is not defined
// is_interface is defined more simply.

struct Base : implements<Base, IActivationFactory>
Expand Down
44 changes: 26 additions & 18 deletions src/tool/cppwinrt/strings/base_implements.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace winrt::impl
template <template <typename> typename Condition, typename T>
using tuple_if = typename tuple_if_base<Condition, T>::type;

#ifdef WINRT_WINDOWS_ABI
#ifdef __IUnknown_INTERFACE_DEFINED__

template <typename T>
struct is_interface : std::disjunction<std::is_base_of<Windows::Foundation::IInspectable, T>, std::conjunction<std::is_base_of<::IUnknown, T>, std::negation<is_implements<T>>>> {};
Expand Down Expand Up @@ -455,7 +455,7 @@ namespace winrt::impl

int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept override
{
return shim().GetIids(count, array);
return shim().GetIids(reinterpret_cast<count_type*>(count), reinterpret_cast<guid_type**>(array));
}

int32_t __stdcall GetRuntimeClassName(void** name) noexcept override
Expand All @@ -469,7 +469,7 @@ namespace winrt::impl
}
};

#ifdef WINRT_WINDOWS_ABI
#ifdef __IUnknown_INTERFACE_DEFINED__

template <typename D, typename I>
struct producer<D, I, std::enable_if_t<std::is_base_of_v< ::IUnknown, I> && !is_implements_v<I>>> : I
Expand Down Expand Up @@ -1037,6 +1037,11 @@ namespace winrt::impl
return result;
}

virtual Windows::Foundation::TrustLevel GetTrustLevel() const noexcept
{
return Windows::Foundation::TrustLevel::BaseTrust;
}

using is_factory = std::disjunction<std::is_same<Windows::Foundation::IActivationFactory, I>...>;

private:
Expand Down Expand Up @@ -1177,11 +1182,6 @@ namespace winrt::impl
virtual void* find_interface(guid const&) const noexcept = 0;
virtual inspectable_abi* find_inspectable() const noexcept = 0;

virtual Windows::Foundation::TrustLevel GetTrustLevel() const noexcept
{
return Windows::Foundation::TrustLevel::BaseTrust;
}

template <typename, typename, typename>
friend struct impl::produce_base;

Expand Down Expand Up @@ -1342,28 +1342,36 @@ WINRT_EXPORT namespace winrt
return result;
}

impl::hresult_type __stdcall QueryInterface(guid const& id, void** object) noexcept
impl::hresult_type __stdcall QueryInterface(impl::guid_type const& id, void** object) noexcept
{
return root_implements_type::QueryInterface(id, object);
return root_implements_type::QueryInterface(reinterpret_cast<guid const&>(id), object);
}

#ifdef WINRT_WINDOWS_ABI
impl::count_type __stdcall AddRef() noexcept
{
return root_implements_type::AddRef();
}

impl::hresult_type __stdcall QueryInterface(GUID const& id, void** object) noexcept
impl::count_type __stdcall Release() noexcept
{
return root_implements_type::QueryInterface(reinterpret_cast<guid const&>(id), object);
return root_implements_type::Release();
}

#endif
impl::hresult_type __stdcall GetIids(impl::count_type* count, impl::guid_type** iids) noexcept
{
return root_implements_type::GetIids(reinterpret_cast<uint32_t*>(count), reinterpret_cast<guid**>(iids));
}

impl::ref_count_type __stdcall AddRef() noexcept
impl::hresult_type __stdcall GetRuntimeClassName(impl::hstring_type* value) noexcept
{
return root_implements_type::AddRef();
return root_implements_type::abi_GetRuntimeClassName(reinterpret_cast<void**>(value));
}

impl::ref_count_type __stdcall Release() noexcept
using root_implements_type::GetTrustLevel;

impl::hresult_type __stdcall GetTrustLevel(impl::trust_level_type* value) noexcept
{
return root_implements_type::Release();
return root_implements_type::abi_GetTrustLevel(reinterpret_cast<Windows::Foundation::TrustLevel*>(value));
}

void* find_interface(guid const& id) const noexcept override
Expand Down
2 changes: 1 addition & 1 deletion src/tool/cppwinrt/strings/base_meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ namespace winrt::impl
static_assert(missing_guid_of<T>::value, "Support for non-WinRT interfaces is disabled. To enable, simply #include <unknwn.h> before any C++/WinRT headers.");
};

#ifdef WINRT_WINDOWS_ABI
#ifdef __IUnknown_INTERFACE_DEFINED__
template <typename T>
struct guid_storage
{
Expand Down
32 changes: 22 additions & 10 deletions src/tool/cppwinrt/strings/base_types.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,6 @@

namespace winrt::impl
{
#ifdef __IUnknown_INTERFACE_DEFINED__
#define WINRT_WINDOWS_ABI
using hresult_type = long;
using ref_count_type = unsigned long;
#else
using hresult_type = int32_t;
using ref_count_type = uint32_t;
#endif

using ptp_io = struct tp_io*;
using ptp_timer = struct tp_timer*;
using ptp_wait = struct tp_wait*;
Expand Down Expand Up @@ -54,7 +45,7 @@ WINRT_EXPORT namespace winrt
{
}

#ifdef WINRT_WINDOWS_ABI
#ifdef __IUnknown_INTERFACE_DEFINED__

constexpr guid(GUID const& value) noexcept :
Data1(value.Data1),
Expand Down Expand Up @@ -97,3 +88,24 @@ WINRT_EXPORT namespace winrt::Windows::Foundation
struct IInspectable;
struct IActivationFactory;
}

namespace winrt::impl
{
#ifdef __IUnknown_INTERFACE_DEFINED__
using hresult_type = long;
using count_type = unsigned long;
using guid_type = GUID;
#else
using hresult_type = int32_t;
using count_type = uint32_t;
using guid_type = guid;
#endif

#ifdef __IInspectable_INTERFACE_DEFINED__
using hstring_type = HSTRING;
using trust_level_type = ::TrustLevel;
#else
using hstring_type = void*;
using trust_level_type = Windows::Foundation::TrustLevel;
#endif
}
2 changes: 1 addition & 1 deletion src/tool/cppwinrt/strings/base_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ WINRT_EXPORT namespace winrt
}
}

#ifdef WINRT_WINDOWS_ABI
#ifdef __IUnknown_INTERFACE_DEFINED__

inline ::IUnknown* get_unknown(Windows::Foundation::IUnknown const& object) noexcept
{
Expand Down
64 changes: 64 additions & 0 deletions src/tool/cppwinrt/test/inspectable_interop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <inspectable.h>
#include "winrt/Windows.Foundation.h"
#include "catch.hpp"

using namespace winrt;

namespace
{
struct __declspec(uuid("ed0dd761-c31e-4803-8cf9-22a2cb20ec47")) IBadInterop : ::IInspectable
Copy link
Member

Choose a reason for hiding this comment

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

In practice, this IBadInterop definition would come from some ABI header file, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right.

{
virtual int32_t __stdcall JustSayNo() noexcept = 0;
};

struct Sample : implements<Sample, Windows::Foundation::IActivationFactory, IBadInterop>
{
Windows::Foundation::IInspectable ActivateInstance()
{
throw hresult_not_implemented();
}

hstring GetRuntimeClassName()
{
return L"Sample";
}

Windows::Foundation::TrustLevel GetTrustLevel()
{
return Windows::Foundation::TrustLevel::PartialTrust;
}

int32_t __stdcall JustSayNo() noexcept final
{
return 123;
}
};
}

TEST_CASE("inspectable_interop")
{
Windows::Foundation::IActivationFactory a = make<Sample>();
REQUIRE(a != nullptr);

Windows::Foundation::IActivationFactory b = a.as<Windows::Foundation::IActivationFactory>();
REQUIRE(b != nullptr);

com_ptr<IBadInterop> c = a.as<IBadInterop>();
REQUIRE(c != nullptr);
REQUIRE(c->JustSayNo() == 123);

Windows::Foundation::IActivationFactory d = c.as<Windows::Foundation::IActivationFactory>();
REQUIRE(a == d);

Windows::Foundation::IInspectable f = c.as<Windows::Foundation::IInspectable>();
REQUIRE(f != nullptr);

Windows::Foundation::IInspectable e(c.detach(), take_ownership_from_abi);

REQUIRE(winrt::get_class_name(e) == L"Sample");
REQUIRE(winrt::get_trust_level(e) == Windows::Foundation::TrustLevel::PartialTrust);

auto interfaces = winrt::get_interfaces(e);
REQUIRE(interfaces.size() == 1);
REQUIRE(interfaces[0] == guid_of<Windows::Foundation::IActivationFactory>());
}
6 changes: 6 additions & 0 deletions src/tool/cppwinrt/test/test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,12 @@
<ClCompile Include="GetMany.cpp" />
<ClCompile Include="get_activation_factory.cpp" />
<ClCompile Include="iid_ppv_args.cpp" />
<ClCompile Include="inspectable_interop.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="interop.cpp" />
<ClCompile Include="invalid_events.cpp" />
<ClCompile Include="in_params.cpp" />
Expand Down