Rpc.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #include "common.h"
  2. #include <wil/rpc_helpers.h>
  3. void RpcMethodReturnsVoid(ULONG toRaise)
  4. {
  5. if (toRaise)
  6. {
  7. RaiseException(toRaise, 0, 0, nullptr);
  8. }
  9. }
  10. struct FOO_CONTEXT_T {};
  11. using FOO_CONTEXT = FOO_CONTEXT_T*;
  12. using PFOO_CONTEXT = FOO_CONTEXT*;
  13. void CloseContextHandle(_Inout_ PFOO_CONTEXT)
  14. {
  15. }
  16. void CloseContextHandleRaise(_Inout_ PFOO_CONTEXT)
  17. {
  18. return RpcMethodReturnsVoid(RPC_X_BAD_STUB_DATA);
  19. }
  20. HRESULT AcquireContextHandle(_In_ handle_t binding, _Out_ PFOO_CONTEXT context)
  21. {
  22. *context = reinterpret_cast<FOO_CONTEXT>(binding);
  23. return S_OK;
  24. }
  25. HRESULT RpcMethodReturnsHResult(HRESULT toReturn, ULONG toRaise)
  26. {
  27. RpcMethodReturnsVoid(toRaise);
  28. return toReturn;
  29. }
  30. GUID RpcMethodReturnsGuid(ULONG toRaise)
  31. {
  32. RpcMethodReturnsVoid(toRaise);
  33. return __uuidof(IUnknown);
  34. }
  35. TEST_CASE("Rpc::NonThrowing", "[rpc]")
  36. {
  37. SECTION("Success paths")
  38. {
  39. REQUIRE_SUCCEEDED(wil::invoke_rpc_nothrow(RpcMethodReturnsVoid, 0UL));
  40. REQUIRE_SUCCEEDED(wil::invoke_rpc_nothrow(RpcMethodReturnsHResult, S_OK, 0UL));
  41. GUID tmp{};
  42. REQUIRE_SUCCEEDED(wil::invoke_rpc_result_nothrow(tmp, RpcMethodReturnsGuid, 0UL));
  43. REQUIRE(tmp == __uuidof(IUnknown));
  44. }
  45. SECTION("Failures in the method")
  46. {
  47. REQUIRE(wil::invoke_rpc_nothrow(RpcMethodReturnsHResult, E_CHANGED_STATE, 0) == E_CHANGED_STATE);
  48. }
  49. SECTION("Failures in the fabric")
  50. {
  51. REQUIRE(wil::invoke_rpc_nothrow(RpcMethodReturnsVoid, RPC_S_CALL_FAILED) == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED));
  52. REQUIRE(wil::invoke_rpc_nothrow(RpcMethodReturnsHResult, E_CHANGED_STATE, RPC_S_CALL_FAILED) == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED));
  53. GUID tmp{};
  54. REQUIRE(wil::invoke_rpc_result_nothrow(tmp, RpcMethodReturnsGuid, RPC_S_CALL_FAILED) == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED));
  55. }
  56. SECTION("Context Handles")
  57. {
  58. using foo_context_t = wil::unique_rpc_context_handle<FOO_CONTEXT, decltype(&CloseContextHandle), CloseContextHandle>;
  59. foo_context_t ctx;
  60. auto tempBinding = reinterpret_cast<handle_t>(-5);
  61. REQUIRE_SUCCEEDED(wil::invoke_rpc_nothrow(AcquireContextHandle, tempBinding, ctx.put()));
  62. REQUIRE(ctx.get() == reinterpret_cast<FOO_CONTEXT>(tempBinding));
  63. ctx.reset();
  64. }
  65. SECTION("Context Handles Close Raised")
  66. {
  67. using foo_context_t = wil::unique_rpc_context_handle<FOO_CONTEXT, decltype(&CloseContextHandleRaise), CloseContextHandleRaise>;
  68. foo_context_t ctx{ reinterpret_cast<FOO_CONTEXT>(42) };
  69. ctx.reset();
  70. }
  71. }
  72. #ifdef WIL_ENABLE_EXCEPTIONS
  73. #include <sstream>
  74. class WilExceptionMatcher : public Catch::MatcherBase<wil::ResultException>
  75. {
  76. HRESULT m_expected;
  77. public:
  78. WilExceptionMatcher(HRESULT ex) : m_expected(ex) { }
  79. bool match(wil::ResultException const& ex) const override {
  80. return ex.GetErrorCode() == m_expected;
  81. }
  82. std::string describe() const override {
  83. std::ostringstream ss;
  84. ss << "wil::ResultException expects code 0x%08lx" << std::hex << m_expected;
  85. return ss.str();
  86. }
  87. };
  88. #define REQUIRE_THROWS_WIL_HR(hr, expr) REQUIRE_THROWS_MATCHES(expr, wil::ResultException, WilExceptionMatcher(hr))
  89. TEST_CASE("Rpc::Throwing", "[rpc]")
  90. {
  91. SECTION("Success paths")
  92. {
  93. REQUIRE_NOTHROW(wil::invoke_rpc(RpcMethodReturnsVoid, 0UL));
  94. GUID tmp{};
  95. REQUIRE_NOTHROW(tmp = wil::invoke_rpc_result(RpcMethodReturnsGuid, 0UL));
  96. REQUIRE(tmp == __uuidof(IUnknown));
  97. }
  98. SECTION("Failures in the method")
  99. {
  100. REQUIRE_THROWS_WIL_HR(E_CHANGED_STATE, wil::invoke_rpc(RpcMethodReturnsHResult, E_CHANGED_STATE, 0UL));
  101. }
  102. SECTION("Failures in the fabric")
  103. {
  104. REQUIRE_THROWS_WIL_HR(HRESULT_FROM_WIN32(RPC_S_CALL_FAILED), wil::invoke_rpc(RpcMethodReturnsVoid, RPC_S_CALL_FAILED));
  105. REQUIRE_THROWS_WIL_HR(HRESULT_FROM_WIN32(RPC_S_CALL_FAILED), wil::invoke_rpc(RpcMethodReturnsHResult, E_CHANGED_STATE, RPC_S_CALL_FAILED));
  106. GUID tmp{};
  107. REQUIRE_THROWS_WIL_HR(HRESULT_FROM_WIN32(RPC_S_CALL_FAILED), tmp = wil::invoke_rpc_result(RpcMethodReturnsGuid, RPC_S_CALL_FAILED));
  108. REQUIRE(tmp == GUID{});
  109. }
  110. }
  111. #endif