From eeb0a7224ac94ece0090c32ba8dda61c445069ba Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 28 Apr 2023 15:22:09 -0500 Subject: [PATCH 1/2] capture_decay --- strings/base_com_ptr.h | 17 +++++++++--- test/old_tests/UnitTests/capture.cpp | 39 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 66dd2c9e7..14a9a0851 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -7,16 +7,27 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { + struct capture_decay + { + void** result; + + template + operator T** () + { + return reinterpret_cast(result); + } + }; + template int32_t capture_to(void**result, F function, Args&& ...args) { - return function(args..., guid_of(), result); + return function(args..., guid_of(), capture_decay{ result }); } template || std::is_union_v, int> = 0> int32_t capture_to(void** result, O* object, M method, Args&& ...args) { - return (object->*method)(args..., guid_of(), result); + return (object->*method)(args..., guid_of(), capture_decay{ result }); } template @@ -343,7 +354,7 @@ namespace winrt::impl template int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) { - return (object.get()->*(method))(args..., guid_of(), result); + return (object.get()->*(method))(args..., guid_of(), capture_decay{ result }); } } diff --git a/test/old_tests/UnitTests/capture.cpp b/test/old_tests/UnitTests/capture.cpp index c72f1ecff..a5251ce80 100644 --- a/test/old_tests/UnitTests/capture.cpp +++ b/test/old_tests/UnitTests/capture.cpp @@ -8,6 +8,7 @@ struct DECLSPEC_UUID("5fb96f8d-409c-42a9-99a7-8a95c1459dbd") ICapture : ::IUnkno { virtual int32_t __stdcall GetValue() noexcept = 0; virtual int32_t __stdcall CreateMemberCapture(int32_t value, GUID const& iid, void** object) noexcept = 0; + virtual int32_t __stdcall CreateMemberCapture2(int32_t value, GUID const& iid, ::IUnknown** object) noexcept = 0; }; #ifdef __CRT_UUID_DECL @@ -33,6 +34,12 @@ struct Capture : implements auto capture = make(value); return capture->QueryInterface(iid, object); } + + int32_t __stdcall CreateMemberCapture2(int32_t value, GUID const& iid, ::IUnknown** object) noexcept override + { + auto capture = make(value); + return capture->QueryInterface(iid, reinterpret_cast(object)); + } }; HRESULT __stdcall CreateCapture(int value, GUID const& iid, void** object) noexcept @@ -41,6 +48,12 @@ HRESULT __stdcall CreateCapture(int value, GUID const& iid, void** object) noexc return capture->QueryInterface(iid, object); } +HRESULT __stdcall CreateCapture2(int value, GUID const& iid, ::IUnknown** object) noexcept +{ + auto capture = make(value); + return capture->QueryInterface(iid, reinterpret_cast(object)); +} + TEST_CASE("capture") { // Capture from global function. @@ -67,6 +80,19 @@ TEST_CASE("capture") com_ptr d; + // Capture with an unconventional result type. + auto e = capture(a, &ICapture::CreateMemberCapture2, 30); + REQUIRE(e->GetValue() == 30); + e = nullptr; + e.capture(a, &ICapture::CreateMemberCapture2, 40); + REQUIRE(e->GetValue() == 40); + + com_ptr f = capture(CreateCapture2, 10); + REQUIRE(f->GetValue() == 10); + f = nullptr; + f.capture(CreateCapture2, 20); + REQUIRE(a->GetValue() == 20); + REQUIRE_THROWS_AS(capture(CreateCapture, 0), hresult_no_interface); REQUIRE_THROWS_AS(d.capture(CreateCapture, 0), hresult_no_interface); REQUIRE_THROWS_AS(capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface); @@ -104,6 +130,19 @@ TEST_CASE("try_capture") com_ptr d; + // Capture with an unconventional result type. + auto e = try_capture(a, &ICapture::CreateMemberCapture2, 30); + REQUIRE(e->GetValue() == 30); + e = nullptr; + REQUIRE(e.try_capture(a, &ICapture::CreateMemberCapture2, 40)); + REQUIRE(e->GetValue() == 40); + + com_ptr f = try_capture(CreateCapture2, 10); + REQUIRE(f->GetValue() == 10); + f = nullptr; + REQUIRE(f.try_capture(CreateCapture2, 20)); + REQUIRE(f->GetValue() == 20); + REQUIRE(!try_capture(CreateCapture, 0)); REQUIRE(!d.try_capture(CreateCapture, 0)); REQUIRE(!try_capture(a, &ICapture::CreateMemberCapture, 0)); From 8c81b87f0a608e025028a6b2e0696e7ceb7533fa Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Sat, 29 Apr 2023 12:07:34 -0500 Subject: [PATCH 2/2] IInspectable --- test/old_tests/UnitTests/capture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/old_tests/UnitTests/capture.cpp b/test/old_tests/UnitTests/capture.cpp index a5251ce80..3cfa2a684 100644 --- a/test/old_tests/UnitTests/capture.cpp +++ b/test/old_tests/UnitTests/capture.cpp @@ -48,7 +48,7 @@ HRESULT __stdcall CreateCapture(int value, GUID const& iid, void** object) noexc return capture->QueryInterface(iid, object); } -HRESULT __stdcall CreateCapture2(int value, GUID const& iid, ::IUnknown** object) noexcept +HRESULT __stdcall CreateCapture2(int value, GUID const& iid, ::IInspectable** object) noexcept { auto capture = make(value); return capture->QueryInterface(iid, reinterpret_cast(object));