win32_result_macros.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. //*********************************************************
  2. //
  3. // Copyright (c) Microsoft. All rights reserved.
  4. // This code is licensed under the MIT License.
  5. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  6. // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  7. // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  8. // PARTICULAR PURPOSE AND NONINFRINGEMENT.
  9. //
  10. //*********************************************************
  11. #ifndef __WIL_WIN32_RESULTMACROS_INCLUDED
  12. #define __WIL_WIN32_RESULTMACROS_INCLUDED
  13. #include "result_macros.h"
  14. // Helpers for return macros
  15. #define __WIN32_RETURN_WIN32(error, str) __WI_SUPPRESS_4127_S do { const auto __error = (error); if (FAILED_WIN32(__error)) { __R_FN(Return_Win32)(__R_INFO(str) __error); } return __error; } __WI_SUPPRESS_4127_E while ((void)0, 0)
  16. #define __WIN32_RETURN_GLE_FAIL(str) return __R_FN(Win32_Return_GetLastError)(__R_INFO_ONLY(str))
  17. FORCEINLINE long __WIN32_FROM_HRESULT(HRESULT hr)
  18. {
  19. if (SUCCEEDED(hr))
  20. {
  21. return ERROR_SUCCESS;
  22. }
  23. return HRESULT_FACILITY(hr) == FACILITY_WIN32 ? HRESULT_CODE(hr) : hr;
  24. }
  25. //*****************************************************************************
  26. // Macros for returning failures as WIN32 error codes
  27. //*****************************************************************************
  28. // Always returns a known result (WIN32 error code) - always logs failures
  29. #define WIN32_RETURN_WIN32(error) __WIN32_RETURN_WIN32(wil::verify_win32(error), #error)
  30. #define WIN32_RETURN_LAST_ERROR() __WIN32_RETURN_GLE_FAIL(nullptr)
  31. // Conditionally returns failures (WIN32 error code) - always logs failures
  32. #define WIN32_RETURN_IF_WIN32_ERROR(error) __WI_SUPPRESS_4127_S do { const auto __errorRet = wil::verify_win32(error); if (FAILED_WIN32(__errorRet)) { __WIN32_RETURN_WIN32(__errorRet, #error); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  33. #define WIN32_RETURN_WIN32_IF(error, condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { __WIN32_RETURN_WIN32(wil::verify_win32(error), #condition); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  34. #define WIN32_RETURN_WIN32_IF_NULL(error, ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { __WIN32_RETURN_WIN32(wil::verify_win32(error), #ptr); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  35. #define WIN32_RETURN_LAST_ERROR_IF(condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { __WIN32_RETURN_GLE_FAIL(#condition); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  36. #define WIN32_RETURN_LAST_ERROR_IF_NULL(ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { __WIN32_RETURN_GLE_FAIL(#ptr); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  37. // Conditionally returns failures (WIN32 error code) - use for failures that are expected in common use - failures are not logged - macros are only for control flow pattern
  38. #define WIN32_RETURN_IF_WIN32_ERROR_EXPECTED(error) __WI_SUPPRESS_4127_S do { const auto __errorRet = wil::verify_win32(error); if (FAILED_WIN32(__errorRet)) { return __errorRet; }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  39. #define WIN32_RETURN_WIN32_IF_EXPECTED(error, condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { return wil::verify_win32(error); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  40. #define WIN32_RETURN_WIN32_IF_NULL_EXPECTED(error, ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { return wil::verify_win32(error); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  41. #define WIN32_RETURN_LAST_ERROR_IF_EXPECTED(condition) __WI_SUPPRESS_4127_S do { if (wil::verify_bool(condition)) { return wil::verify_win32(wil::details::GetLastErrorFail()); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  42. #define WIN32_RETURN_LAST_ERROR_IF_NULL_EXPECTED(ptr) __WI_SUPPRESS_4127_S do { if ((ptr) == nullptr) { return wil::verify_win32(wil::details::GetLastErrorFail()); }} __WI_SUPPRESS_4127_E while ((void)0, 0)
  43. //*****************************************************************************
  44. // Macros to catch and convert exceptions on failure
  45. //*****************************************************************************
  46. // Use these macros *within* a catch (...) block to handle exceptions
  47. #define WIN32_RETURN_CAUGHT_EXCEPTION() return __R_FN(Win32_Return_CaughtException)(__R_INFO_ONLY(nullptr))
  48. // Use these macros in place of a catch block to handle exceptions
  49. #define WIN32_CATCH_RETURN() catch (...) { WIN32_RETURN_CAUGHT_EXCEPTION(); }
  50. namespace wil
  51. {
  52. //*****************************************************************************
  53. // Public Helpers that catch -- mostly only enabled when exceptions are enabled
  54. //*****************************************************************************
  55. // Win32ErrorFromCaughtException is a function that is meant to be called from within a catch(...) block. Internally
  56. // it re-throws and catches the exception to convert it to a WIN32 error code. If an exception is of an unrecognized type
  57. // the function will fail fast.
  58. //
  59. // try
  60. // {
  61. // // Code
  62. // }
  63. // catch (...)
  64. // {
  65. // status = wil::Win32ErrorFromCaughtException();
  66. // }
  67. _Always_(_Post_satisfies_(return > 0))
  68. __declspec(noinline) inline long Win32ErrorFromCaughtException() WI_NOEXCEPT
  69. {
  70. return __WIN32_FROM_HRESULT(ResultFromCaughtException());
  71. }
  72. namespace details::__R_NS_NAME
  73. {
  74. #ifdef WIL_ENABLE_EXCEPTIONS
  75. __R_DIRECT_METHOD(long, Win32_Return_CaughtException)(__R_DIRECT_FN_PARAMS_ONLY) WI_NOEXCEPT
  76. {
  77. __R_FN_LOCALS;
  78. return __WIN32_FROM_HRESULT(wil::details::ReportFailure_CaughtException<FailureType::Return>(__R_DIRECT_FN_CALL_ONLY));
  79. }
  80. #endif
  81. __R_DIRECT_METHOD(long, Win32_Return_GetLastError)(__R_DIRECT_FN_PARAMS_ONLY) WI_NOEXCEPT
  82. {
  83. __R_FN_LOCALS;
  84. return __WIN32_FROM_HRESULT(wil::details::ReportFailure_GetLastErrorHr<FailureType::Return>(__R_DIRECT_FN_CALL_ONLY));
  85. }
  86. }
  87. }
  88. #endif // __WIL_WIN32_RESULTMACROS_INCLUDED