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
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
//----------------------------------------------------------
// ErrorHandling.h - Helpers & whatnot for using SEH for errors
//----------------------------------------------------------
#ifndef _ErrorHandling
#define _ErrorHandling
#include "logging.h"
// EXCEPTIONCODE_DebugBreakorAV is just the base exception number; calls to DebugBreakorAV()
// pass a unique number to add to this. EXCEPTIONCODE_DebugBreakorAV_MAX is the maximum number
// of this exception range.
#define EXCEPTIONCODE_DebugBreakorAV 0xe0421000
#define EXCEPTIONCODE_DebugBreakorAV_MAX 0xe0422000
#define EXCEPTIONCODE_MC 0xe0422000
#define EXCEPTIONCODE_LWM 0xe0423000
#define EXCEPTIONCODE_CALLUTILS 0xe0426000
#define EXCEPTIONCODE_TYPEUTILS 0xe0427000
#define EXCEPTIONCODE_ASSERT 0xe0440000
// RaiseException wrappers
void MSC_ONLY(__declspec(noreturn)) ThrowException(DWORD exceptionCode);
void MSC_ONLY(__declspec(noreturn)) ThrowException(DWORD exceptionCode, const char* message, ...);
// Assert stuff
#define AssertCodeMsg(expr, exCode, msg, ...) \
do \
{ \
if (!(expr)) \
LogException(exCode, "SuperPMI assertion '%s' failed (" #msg ")", #expr, ##__VA_ARGS__); \
} while (0)
#define AssertCode(expr, exCode) \
do \
{ \
if (!(expr)) \
LogException(exCode, "SuperPMI assertion '%s' failed", #expr); \
} while (0)
#define AssertMapExists(map, keymsg, ...) \
do \
{ \
if (map == nullptr) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing map " #map ")" keymsg, ##__VA_ARGS__); \
} while (0)
#define AssertKeyExists(map, key, keymsg, ...) \
do \
{ \
if (map->GetIndex(key) == -1) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing key \"" #key "\" in map " #map ")" keymsg, ##__VA_ARGS__); \
} while (0)
#define AssertMapAndKeyExist(map, key, keymsg, ...) \
do \
{ \
if (map == nullptr) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing map " #map ")" keymsg, ##__VA_ARGS__); \
if (map->GetIndex(key) == -1) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing key \"" #key "\" in map " #map ")" keymsg, ##__VA_ARGS__); \
} while (0)
// clang doesn't allow for an empty __VA_ARGS__, so we need to pass something non-empty to `LogException`, below.
#define AssertMapExistsNoMessage(map) \
do \
{ \
if (map == nullptr) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing map " #map ")", ""); \
} while (0)
#define AssertKeyExistsNoMessage(map, key) \
do \
{ \
if (map->GetIndex(key) == -1) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing key \"" #key "\" in map " #map ")", "");\
} while (0)
#define AssertMapAndKeyExistNoMessage(map, key) \
do \
{ \
if (map == nullptr) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing map " #map ")", ""); \
if (map->GetIndex(key) == -1) \
LogException(EXCEPTIONCODE_MC, "SuperPMI assertion failed (missing key \"" #key "\" in map " #map ")", "");\
} while (0)
#define AssertMsg(expr, msg, ...) AssertCodeMsg(expr, EXCEPTIONCODE_ASSERT, msg, ##__VA_ARGS__)
#define Assert(expr) AssertCode(expr, EXCEPTIONCODE_ASSERT)
//
// Functions and types used by PAL_TRY-related macros.
//
extern LONG FilterSuperPMIExceptions_CatchMC(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
struct FilterSuperPMIExceptionsParam_CaptureException
{
DWORD exceptionCode;
char* exceptionMessage; // 'new' memory passed from ThrowException()
FilterSuperPMIExceptionsParam_CaptureException()
: exceptionCode(0)
, exceptionMessage(nullptr)
{
}
// Note: this is called during an SEH filter; the data pointed to by PEXCEPTION_POINTERS is not valid after
// calling this function, so anything we want to safe must be copied.
// The exception message string is 'new' memory, allocated in the ThrowException() function.
void Initialize(PEXCEPTION_POINTERS pExceptionPointers)
{
exceptionCode = pExceptionPointers->ExceptionRecord->ExceptionCode;
exceptionMessage = (pExceptionPointers->ExceptionRecord->NumberParameters != 1) ? nullptr : (char*)pExceptionPointers->ExceptionRecord->ExceptionInformation[0];
}
};
extern LONG FilterSuperPMIExceptions_CaptureExceptionAndContinue(PEXCEPTION_POINTERS pExceptionPointers,
LPVOID lpvParam);
extern LONG FilterSuperPMIExceptions_CaptureExceptionAndStop(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
extern bool RunWithErrorTrap(void (*function)(void*), void* param);
class SpmiException
{
private:
DWORD exCode;
char* exMessage;
public:
SpmiException(FilterSuperPMIExceptionsParam_CaptureException* e);
#if 0
~SpmiException();
#endif
char* GetExceptionMessage();
DWORD GetCode();
void ShowAndDeleteMessage();
void DeleteMessage();
};
#endif
|