-
Notifications
You must be signed in to change notification settings - Fork 10.3k
/
Copy pathexceptions.h
275 lines (232 loc) · 11.6 KB
/
exceptions.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
#pragma once
#include <exception>
#include <system_error>
#include "debugutil.h"
#include "StringHelpers.h"
#include "InvalidOperationException.h"
#include "ntassert.h"
#include "NonCopyable.h"
#include "EventTracing.h"
#define LOCATION_INFO_ENABLED TRUE
#if LOCATION_INFO_ENABLED
#define LOCATION_FORMAT "%s:%d "
#define LOCATION_ARGUMENTS_ONLY _In_opt_ PCSTR fileName, unsigned int lineNumber
#define LOCATION_ARGUMENTS LOCATION_ARGUMENTS_ONLY,
#define LOCATION_CALL_ONLY fileName, lineNumber
#define LOCATION_CALL LOCATION_CALL_ONLY,
#define LOCATION_INFO __FILE__, __LINE__
#else
#define LOCATION_FORMAT
#define LOCATION_ARGUMENTS_ONLY
#define LOCATION_ARGUMENTS
#define LOCATION_CALL_ONLY
#define LOCATION_CALL
#define LOCATION_INFO
#endif
#define OBSERVE_CAUGHT_EXCEPTION() CaughtExceptionHResult(LOCATION_INFO);
#define RETURN_CAUGHT_EXCEPTION() return CaughtExceptionHResult(LOCATION_INFO);
#define _CHECK_FAILED(expr) __pragma(warning(push)) \
__pragma(warning(suppress:4127)) /*disable condition is const warning*/ \
FAILED(expr)
#define _HR_RET(hr) __pragma(warning(push)) \
__pragma(warning(suppress:26498 26814)) /*disable constexpr warning */ \
const HRESULT __hrRet = hr;
#define RETURN_HR(hr) do { _HR_RET(hr); if (_CHECK_FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); } return __hrRet; } while (0, 0)
#define RETURN_LAST_ERROR() do { return LogLastError(LOCATION_INFO); } while (0, 0)
#define RETURN_IF_FAILED(hr) do { _HR_RET(hr); if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); return __hrRet; }} while (0, 0)
#define RETURN_LAST_ERROR_IF(condition) do { if (condition) { return LogLastError(LOCATION_INFO); }} while (0, 0)
#define RETURN_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { return LogLastError(LOCATION_INFO); }} while (0, 0)
#define _GOTO_FINISHED() __pragma(warning(push)) \
__pragma(warning(disable:26438)) /*disable avoid goto warning*/ \
goto Finished \
__pragma(warning(pop))
#define _GOTO_FAILURE() __pragma(warning(push)) \
__pragma(warning(disable:26438)) /*disable avoid goto warning*/ \
goto Failure \
__pragma(warning(pop))
#define FINISHED(hrr) do { _HR_RET(hrr); if (_CHECK_FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); } hr = __hrRet; _GOTO_FINISHED(); } while (0, 0)
#define FINISHED_IF_FAILED(hrr) do { _HR_RET(hrr); if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); hr = __hrRet; _GOTO_FINISHED(); }} while (0, 0)
#define FINISHED_IF_NULL_ALLOC(ptr) do { if ((ptr) == nullptr) { hr = LogHResultFailed(LOCATION_INFO, E_OUTOFMEMORY); _GOTO_FINISHED(); }} while (0, 0)
#define FINISHED_LAST_ERROR_IF(condition) do { if (condition) { hr = LogLastError(LOCATION_INFO); _GOTO_FINISHED(); }} while (0, 0)
#define FINISHED_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { hr = LogLastError(LOCATION_INFO); _GOTO_FINISHED(); }} while (0, 0)
#define FAILURE(hrr) do { _HR_RET(hrr); if (_CHECK_FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); } hr = __hrRet; _GOTO_FAILURE(); } while (0, 0)
#define FAILURE_IF_FAILED(hrr) do { _HR_RET(hrr); if (FAILED(__hrRet)) { LogHResultFailed(LOCATION_INFO, __hrRet); hr = __hrRet; _GOTO_FAILURE(); }} while (0, 0)
#define FAILURE_IF_NULL_ALLOC(ptr) do { if ((ptr) == nullptr) { hr = LogHResultFailed(LOCATION_INFO, E_OUTOFMEMORY); _GOTO_FAILURE(); }} while (0, 0)
#define FAILURE_LAST_ERROR_IF(condition) do { if (condition) { hr = LogLastError(LOCATION_INFO); _GOTO_FAILURE(); }} while (0, 0)
#define FAILURE_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { hr = LogLastError(LOCATION_INFO); _GOTO_FAILURE(); }} while (0, 0)
#define THROW_HR(hr) do { _HR_RET(hr); ThrowResultException(LOCATION_INFO, LogHResultFailed(LOCATION_INFO, __hrRet)); } while (0, 0)
#define THROW_LAST_ERROR() do { ThrowResultException(LOCATION_INFO, LogLastError(LOCATION_INFO)); } while (0, 0)
#define THROW_IF_FAILED(hr) do { _HR_RET(hr); if (FAILED(__hrRet)) { ThrowResultException(LOCATION_INFO, __hrRet); }} while (0, 0)
#define THROW_LAST_ERROR_IF(condition) do { if (condition) { ThrowResultException(LOCATION_INFO, LogLastError(LOCATION_INFO)); }} while (0, 0)
#define THROW_LAST_ERROR_IF_NULL(ptr) do { if ((ptr) == nullptr) { ThrowResultException(LOCATION_INFO, LogLastError(LOCATION_INFO)); }} while (0, 0)
#define THROW_IF_NULL_ALLOC(ptr) Throw_IfNullAlloc(ptr)
#define CATCH_RETURN() catch (...) { RETURN_CAUGHT_EXCEPTION(); }
#define LOG_IF_FAILED(hr) LogHResultFailed(LOCATION_INFO, hr)
#define LOG_LAST_ERROR() LogLastErrorIf(LOCATION_INFO, true)
#define LOG_LAST_ERROR_IF(condition) LogLastErrorIf(LOCATION_INFO, condition)
#define SUCCEEDED_LOG(hr) SUCCEEDED(LOG_IF_FAILED(hr))
#define FAILED_LOG(hr) FAILED(LOG_IF_FAILED(hr))
#define RETURN_INT_IF_NOT_ZERO(val) do { if ((val) != 0) { return val; }} while (0, 0)
#define RETURN_IF_NOT_ZERO(val) do { if ((val) != 0) { return; }} while (0, 0)
inline thread_local IHttpTraceContext* g_traceContext;
__declspec(noinline) inline VOID TraceHRESULT(LOCATION_ARGUMENTS HRESULT hr)
{
::RaiseEvent<ANCMEvents::ANCM_HRESULT_FAILED>(g_traceContext, nullptr, fileName, lineNumber, hr);
}
__declspec(noinline) inline VOID TraceException(LOCATION_ARGUMENTS const std::exception& exception)
{
::RaiseEvent<ANCMEvents::ANCM_EXCEPTION_CAUGHT>(g_traceContext, nullptr, fileName, lineNumber, exception.what());
}
class ResultException: public std::runtime_error
{
public:
ResultException(HRESULT hr, LOCATION_ARGUMENTS_ONLY) :
runtime_error(format("HRESULT 0x%x returned at " LOCATION_FORMAT, hr, LOCATION_CALL_ONLY)),
m_hr(hr)
{
}
HRESULT GetResult() const noexcept { return m_hr; }
private:
#pragma warning( push )
#pragma warning ( disable : 26495 ) // bug in CA: m_hr is reported as uninitialized
const HRESULT m_hr = S_OK;
};
#pragma warning( pop )
__declspec(noinline) inline VOID ReportUntypedException(LOCATION_ARGUMENTS_ONLY)
{
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, LOCATION_FORMAT "Unhandled non-standard exception", LOCATION_CALL_ONLY);
}
__declspec(noinline) inline HRESULT LogLastError(LOCATION_ARGUMENTS_ONLY)
{
const auto lastError = GetLastError();
const auto hr = HRESULT_FROM_WIN32(lastError);
TraceHRESULT(LOCATION_CALL hr);
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, LOCATION_FORMAT "Operation failed with LastError: %d HR: 0x%x", LOCATION_CALL lastError, hr);
return hr;
}
__declspec(noinline) inline bool LogLastErrorIf(LOCATION_ARGUMENTS_ONLY, bool condition)
{
if (condition)
{
LogLastError(LOCATION_CALL_ONLY);
}
return condition;
}
__declspec(noinline) inline VOID ReportException(LOCATION_ARGUMENTS const InvalidOperationException& exception)
{
TraceException(LOCATION_CALL exception);
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "InvalidOperationException '%ls' caught at " LOCATION_FORMAT, exception.as_wstring().c_str(), LOCATION_CALL_ONLY);
}
__declspec(noinline) inline VOID ReportException(LOCATION_ARGUMENTS const std::exception& exception)
{
TraceException(LOCATION_CALL exception);
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "Exception '%s' caught at " LOCATION_FORMAT, exception.what(), LOCATION_CALL_ONLY);
}
__declspec(noinline) inline HRESULT LogHResultFailed(LOCATION_ARGUMENTS HRESULT hr)
{
if (FAILED(hr))
{
TraceHRESULT(LOCATION_CALL hr);
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "Failed HRESULT returned: 0x%x at " LOCATION_FORMAT, hr, LOCATION_CALL_ONLY);
}
return hr;
}
__declspec(noinline) inline HRESULT LogHResultFailed(LOCATION_ARGUMENTS const std::error_code& error_code)
{
if (error_code)
{
TraceHRESULT(LOCATION_CALL error_code.value());
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "Failed error_code returned: 0x%x 0xs at " LOCATION_FORMAT, error_code.value(), error_code.message().c_str(), LOCATION_CALL_ONLY);
return E_FAIL;
}
return ERROR_SUCCESS;
}
__declspec(noinline) inline HRESULT CaughtExceptionHResult(LOCATION_ARGUMENTS_ONLY)
{
try
{
throw;
}
catch (const std::bad_alloc&)
{
return E_OUTOFMEMORY;
}
catch (const ResultException& exception)
{
ReportException(LOCATION_CALL exception);
return exception.GetResult();
}
catch (const InvalidOperationException& exception)
{
ReportException(LOCATION_CALL exception);
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
}
catch (const std::exception& exception)
{
ReportException(LOCATION_CALL exception);
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
}
catch (...)
{
ReportUntypedException(LOCATION_CALL_ONLY);
return HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION);
}
}
__declspec(noinline) inline std::wstring CaughtExceptionToString()
{
try
{
throw;
}
catch (const InvalidOperationException& exception)
{
return exception.as_wstring();
}
catch (const std::system_error& exception)
{
return to_wide_string(exception.what(), CP_ACP);
}
catch (const std::exception& exception)
{
return to_wide_string(exception.what(), CP_ACP);
}
catch (...)
{
return L"Unknown exception type";
}
}
[[noreturn]]
__declspec(noinline) inline void ThrowResultException(LOCATION_ARGUMENTS HRESULT hr)
{
DebugPrintf(ASPNETCORE_DEBUG_FLAG_ERROR, "Throwing ResultException for HRESULT 0x%x at " LOCATION_FORMAT, hr, LOCATION_CALL_ONLY);
throw ResultException(hr, LOCATION_CALL_ONLY);
}
template <typename PointerT> auto Throw_IfNullAlloc(PointerT pointer)
{
if (pointer == nullptr)
{
throw std::bad_alloc();
}
return pointer;
}
__declspec(noinline) inline std::wstring GetUnexpectedExceptionMessage(const std::runtime_error& ex)
{
return format(L"Unexpected exception: %S", ex.what());
}
class TraceContextScope: NonCopyable
{
public:
TraceContextScope(IHttpTraceContext* pTraceContext) noexcept
{
m_pPreviousTraceContext = g_traceContext;
g_traceContext = pTraceContext;
}
~TraceContextScope()
{
g_traceContext = m_pPreviousTraceContext;
}
private:
IHttpTraceContext* m_pPreviousTraceContext;
};