Skip to content

Commit 8c0832f

Browse files
authored
try_capture and try_create_instance (#663)
1 parent 26f1295 commit 8c0832f

File tree

4 files changed

+66
-0
lines changed

4 files changed

+66
-0
lines changed

strings/base_activation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,12 @@ WINRT_EXPORT namespace winrt
487487
impl::get_factory_cache().clear();
488488
}
489489

490+
template <typename Interface>
491+
auto try_create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr)
492+
{
493+
return try_capture<Interface>(WINRT_IMPL_CoCreateInstance, clsid, outer, context);
494+
}
495+
490496
template <typename Interface>
491497
auto create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr)
492498
{

strings/base_com_ptr.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,18 @@ WINRT_EXPORT namespace winrt
153153
*other = m_ptr;
154154
}
155155

156+
template <typename F, typename...Args>
157+
bool try_capture(F function, Args&&...args)
158+
{
159+
return function(args..., guid_of<T>(), put_void()) >= 0;
160+
}
161+
162+
template <typename O, typename M, typename...Args>
163+
bool try_capture(com_ptr<O> const& object, M method, Args&&...args)
164+
{
165+
return (object.get()->*(method))(args..., guid_of<T>(), put_void()) >= 0;
166+
}
167+
156168
template <typename F, typename...Args>
157169
void capture(F function, Args&&...args)
158170
{
@@ -204,6 +216,21 @@ WINRT_EXPORT namespace winrt
204216
type* m_ptr{};
205217
};
206218

219+
template <typename T, typename F, typename...Args>
220+
impl::com_ref<T> try_capture(F function, Args&& ...args)
221+
{
222+
void* result{};
223+
function(args..., guid_of<T>(), &result);
224+
return { result, take_ownership_from_abi };
225+
}
226+
227+
template <typename T, typename O, typename M, typename...Args>
228+
impl::com_ref<T> try_capture(com_ptr<O> const& object, M method, Args&& ...args)
229+
{
230+
void* result{};
231+
(object.get()->*(method))(args..., guid_of<T>(), &result);
232+
return { result, take_ownership_from_abi };
233+
}
207234
template <typename T, typename F, typename...Args>
208235
impl::com_ref<T> capture(F function, Args&& ...args)
209236
{

test/old_tests/UnitTests/capture.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,27 @@ TEST_CASE("capture")
5858
REQUIRE_THROWS_AS(capture<IDispatch>(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface);
5959
REQUIRE_THROWS_AS(d.capture(a, &ICapture::CreateMemberCapture, 0), hresult_no_interface);
6060
}
61+
62+
TEST_CASE("try_capture")
63+
{
64+
// Identical to the "capture" test above, just with different
65+
// error handling.
66+
com_ptr<ICapture> a = try_capture<ICapture>(CreateCapture, 10);
67+
REQUIRE(a->GetValue() == 10);
68+
a = nullptr;
69+
REQUIRE(a.try_capture(CreateCapture, 20));
70+
REQUIRE(a->GetValue() == 20);
71+
72+
auto b = try_capture<ICapture>(a, &ICapture::CreateMemberCapture, 30);
73+
REQUIRE(b->GetValue() == 30);
74+
b = nullptr;
75+
REQUIRE(b.try_capture(a, &ICapture::CreateMemberCapture, 40));
76+
REQUIRE(b->GetValue() == 40);
77+
78+
com_ptr<IDispatch> d;
79+
80+
REQUIRE(!try_capture<IDispatch>(CreateCapture, 0));
81+
REQUIRE(!d.try_capture(CreateCapture, 0));
82+
REQUIRE(!try_capture<IDispatch>(a, &ICapture::CreateMemberCapture, 0));
83+
REQUIRE(!d.try_capture(a, &ICapture::CreateMemberCapture, 0));
84+
}

test/old_tests/UnitTests/create_instance.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,12 @@ TEST_CASE("create_instance")
99
com_ptr<IFileOpenDialog> dialog = create_instance<IFileOpenDialog>(guid_of<FileOpenDialog>());
1010
REQUIRE(dialog);
1111
}
12+
13+
TEST_CASE("try_create_instance")
14+
{
15+
com_ptr<IFileOpenDialog> dialog = try_create_instance<IFileOpenDialog>(guid_of<FileOpenDialog>());
16+
REQUIRE(dialog);
17+
18+
dialog = try_create_instance<IFileOpenDialog>(CLSID_NULL);
19+
REQUIRE(!dialog);
20+
}

0 commit comments

Comments
 (0)