Skip to content

Commit b722907

Browse files
authored
Accurate error propagation from RoGetActivationFactory (#559)
1 parent f007201 commit b722907

File tree

8 files changed

+59
-19
lines changed

8 files changed

+59
-19
lines changed

strings/base_activation.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ namespace winrt::impl
5555
return 0;
5656
}
5757

58+
com_ptr<IErrorInfo> error_info;
59+
WINRT_IMPL_GetErrorInfo(0, error_info.put_void());
60+
5861
std::wstring path{ static_cast<hstring const&>(name) };
5962
std::size_t count{};
6063

@@ -97,7 +100,8 @@ namespace winrt::impl
97100
}
98101
}
99102

100-
return error_class_not_available;
103+
WINRT_IMPL_SetErrorInfo(0, error_info.get());
104+
return hr;
101105
}
102106
}
103107

strings/base_error.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,13 @@ WINRT_EXPORT namespace winrt
376376
hresult_class_not_available(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi) {}
377377
};
378378

379+
struct hresult_class_not_registered : hresult_error
380+
{
381+
hresult_class_not_registered() noexcept : hresult_error(impl::error_class_not_registered) {}
382+
hresult_class_not_registered(param::hstring const& message) noexcept : hresult_error(impl::error_class_not_registered, message) {}
383+
hresult_class_not_registered(take_ownership_from_abi_t) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi) {}
384+
};
385+
379386
struct hresult_changed_state : hresult_error
380387
{
381388
hresult_changed_state() noexcept : hresult_error(impl::error_changed_state) {}
@@ -453,6 +460,11 @@ WINRT_EXPORT namespace winrt
453460
throw hresult_class_not_available(take_ownership_from_abi);
454461
}
455462

463+
if (result == impl::error_class_not_registered)
464+
{
465+
throw hresult_class_not_registered(take_ownership_from_abi);
466+
}
467+
456468
if (result == impl::error_changed_state)
457469
{
458470
throw hresult_changed_state(take_ownership_from_abi);

strings/base_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ namespace winrt::impl
139139
constexpr hresult error_out_of_bounds{ static_cast<hresult>(0x8000000B) }; // E_BOUNDS
140140
constexpr hresult error_no_interface{ static_cast<hresult>(0x80004002) }; // E_NOINTERFACE
141141
constexpr hresult error_class_not_available{ static_cast<hresult>(0x80040111) }; // CLASS_E_CLASSNOTAVAILABLE
142+
constexpr hresult error_class_not_registered{ static_cast<hresult>(0x80040154) }; // REGDB_E_CLASSNOTREG
142143
constexpr hresult error_changed_state{ static_cast<hresult>(0x8000000C) }; // E_CHANGED_STATE
143144
constexpr hresult error_illegal_method_call{ static_cast<hresult>(0x8000000E) }; // E_ILLEGAL_METHOD_CALL
144145
constexpr hresult error_illegal_state_change{ static_cast<hresult>(0x8000000D) }; // E_ILLEGAL_STATE_CHANGE

test/old_tests/UnitTests/get_activation_factory.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,7 @@ TEST_CASE("get_activation_factory")
2323
}
2424

2525
// Calling get_activation_factory with an invalid class name
26-
try
27-
{
28-
get_activation_factory(L"Composable.DoesNotExist");
29-
REQUIRE(false);
30-
}
31-
catch (hresult_class_not_available const& e)
32-
{
33-
REQUIRE(e.message() == L"Composable.DoesNotExist");
34-
}
26+
REQUIRE_THROWS_AS(get_activation_factory(L"Composable.DoesNotExist"), hresult_class_not_registered);
3527
}
3628

3729
TEST_CASE("try_get_activation_factory")
@@ -72,6 +64,6 @@ TEST_CASE("try_get_activation_factory")
7264
auto factory = try_get_activation_factory<Component::IErrors>(e);
7365
REQUIRE(factory == nullptr);
7466
REQUIRE(get_error_info() == nullptr);
75-
REQUIRE(e.code() == CLASS_E_CLASSNOTAVAILABLE);
67+
REQUIRE(e.code() == REGDB_E_CLASSNOTREG);
7668
}
7769
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include "pch.h"
2+
3+
using namespace winrt;
4+
using namespace Windows::Foundation;
5+
6+
namespace
7+
{
8+
IAsyncAction Async()
9+
{
10+
// This is just a simple way of testing all of the ABI and projection
11+
// error propagation in one go.
12+
throw hresult_class_not_registered(L"test message");
13+
}
14+
}
15+
TEST_CASE("hresult_class_not_registered")
16+
{
17+
REQUIRE(hresult_class_not_registered().message() == L"Class not registered");
18+
REQUIRE(hresult_class_not_registered().code() == REGDB_E_CLASSNOTREG);
19+
20+
try
21+
{
22+
Async().get();
23+
FAIL(L"Previous line should throw");
24+
}
25+
catch (hresult_class_not_registered const& e)
26+
{
27+
REQUIRE(e.message() == L"test message");
28+
REQUIRE(e.code() == REGDB_E_CLASSNOTREG);
29+
}
30+
}

test/test/test.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@
330330
<ClCompile Include="delegates.cpp" />
331331
<ClCompile Include="disconnected.cpp" />
332332
<ClCompile Include="enum.cpp" />
333+
<ClCompile Include="hresult_class_not_registered.cpp" />
333334
<ClCompile Include="error_info.cpp" />
334335
<ClCompile Include="event_deferral.cpp" />
335336
<ClCompile Include="async_local.cpp" />

test/test/velocity.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@ TEST_CASE("velocity")
1717
REQUIRE(b == nullptr);
1818

1919
// Class1 is always disabled and thus will not activate.
20-
REQUIRE_THROWS_AS(Class1(), hresult_class_not_available);
20+
REQUIRE_THROWS_AS(Class1(), hresult_class_not_registered);
2121

2222
// Class2 is always enabled so should activate just fine.
2323
Class2 c;
2424
c.Class2_Method();
2525

2626
// Class3 is always disabled and thus will not activate.
27-
REQUIRE_THROWS_AS(Class3(), hresult_class_not_available);
27+
REQUIRE_THROWS_AS(Class3(), hresult_class_not_registered);
2828

2929
// Class4 is not feature-controlled but uses feature interfaces.
3030
Class4 d;
3131
d.Class4_Method();
3232

3333
// The single argument constructor is always disabled.
34-
REQUIRE_THROWS_AS(Class4(1), hresult_class_not_available);
34+
REQUIRE_THROWS_AS(Class4(1), hresult_class_not_registered);
3535

3636
// The Class4_Static1 static is always disabled.
37-
REQUIRE_THROWS_AS(Class4::Class4_Static1(), hresult_class_not_available);
37+
REQUIRE_THROWS_AS(Class4::Class4_Static1(), hresult_class_not_registered);
3838

3939
// The two argument constructor is always enabled.
4040
Class4 e(1, 2);

test/test_win7/velocity.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,24 @@ TEST_CASE("velocity")
1717
REQUIRE(b == nullptr);
1818

1919
// Class1 is always disabled and thus will not activate.
20-
REQUIRE_THROWS_AS(Class1(), hresult_class_not_available);
20+
REQUIRE_THROWS_AS(Class1(), hresult_class_not_registered);
2121

2222
// Class2 is always enabled so should activate just fine.
2323
Class2 c;
2424
c.Class2_Method();
2525

2626
// Class3 is always disabled and thus will not activate.
27-
REQUIRE_THROWS_AS(Class3(), hresult_class_not_available);
27+
REQUIRE_THROWS_AS(Class3(), hresult_class_not_registered);
2828

2929
// Class4 is not feature-controlled but uses feature interfaces.
3030
Class4 d;
3131
d.Class4_Method();
3232

3333
// The single argument constructor is always disabled.
34-
REQUIRE_THROWS_AS(Class4(1), hresult_class_not_available);
34+
REQUIRE_THROWS_AS(Class4(1), hresult_class_not_registered);
3535

3636
// The Class4_Static1 static is always disabled.
37-
REQUIRE_THROWS_AS(Class4::Class4_Static1(), hresult_class_not_available);
37+
REQUIRE_THROWS_AS(Class4::Class4_Static1(), hresult_class_not_registered);
3838

3939
// The two argument constructor is always enabled.
4040
Class4 e(1, 2);

0 commit comments

Comments
 (0)