forked from WinMerge/winmerge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathExceptions.h
128 lines (118 loc) · 3.88 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
/////////////////////////////////////////////////////////////////////////////
// WinMerge: an interactive diff/merge utility
// Copyright (C) 1997-2000 Thingamahoochie Software
// Author: Dean Grimm
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
/////////////////////////////////////////////////////////////////////////////
/**
* @file Exceptions.h
*
* @brief Exceptions handlers (currently, only SE handler for try/catch)
*/
#pragma once
#ifdef _MSC_VER
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#endif
/**
* @brief C exception "wrapper" class for C++ try/catch
*
* @note : for the original idea, see MSDN help about _set_se_translator
* derive from CException::CException
* creator needs a flag bAutoDelete
* (when flag is set, exception is reserved on heap, avoid to use the stack as it may be wrecked)
* one single interface to catch SE_Exception and CException
* GetErrorMessage : avoid using CString during exception processing
*/
class SE_Exception
{
private:
unsigned long nSE;
public:
explicit SE_Exception(unsigned long n) : nSE(n) {}
~SE_Exception() {};
unsigned long getSeNumber() { return nSE; }
#ifdef _MSC_VER
const TCHAR *getSeMessage()
{
// known exceptions (from WINNT.H)
#define EXCEPTION( x ) case EXCEPTION_##x: return _T(#x);
switch ( nSE )
{
EXCEPTION( ACCESS_VIOLATION )
EXCEPTION( DATATYPE_MISALIGNMENT )
EXCEPTION( BREAKPOINT )
EXCEPTION( SINGLE_STEP )
EXCEPTION( ARRAY_BOUNDS_EXCEEDED )
EXCEPTION( FLT_DENORMAL_OPERAND )
EXCEPTION( FLT_DIVIDE_BY_ZERO )
EXCEPTION( FLT_INEXACT_RESULT )
EXCEPTION( FLT_INVALID_OPERATION )
EXCEPTION( FLT_OVERFLOW )
EXCEPTION( FLT_STACK_CHECK )
EXCEPTION( FLT_UNDERFLOW )
EXCEPTION( INT_DIVIDE_BY_ZERO )
EXCEPTION( INT_OVERFLOW )
EXCEPTION( PRIV_INSTRUCTION )
EXCEPTION( IN_PAGE_ERROR )
EXCEPTION( ILLEGAL_INSTRUCTION )
EXCEPTION( NONCONTINUABLE_EXCEPTION )
EXCEPTION( STACK_OVERFLOW )
EXCEPTION( INVALID_DISPOSITION )
EXCEPTION( GUARD_PAGE )
EXCEPTION( INVALID_HANDLE )
}
// don't localize this as we do not localize the known exceptions
return _T("Unknown structured exception");
}
virtual bool GetErrorMessage( TCHAR *lpszError, unsigned nMaxError, unsigned *pnHelpContext = nullptr )
{
StringCchPrintf(lpszError, nMaxError, _T("Exception %s (0x%.8x)"), getSeMessage(), static_cast<unsigned>(getSeNumber()));
return true;
}
#else
virtual bool GetErrorMessage( TCHAR *lpszError, unsigned nMaxError, unsigned *pnHelpContext = nullptr )
{
return true;
}
#endif
};
/**
* @brief Set the structured exception translator during the life of the object.
* Just add 'SE_Handler seh;' at the beginning of the function.
*
* @note May be created as a global variable. In fact, you need one instance
* for each thread.
*/
class SE_Handler {
#ifdef _MSC_VER
private:
_se_translator_function fnOld;
static void seh_trans_func(unsigned u, EXCEPTION_POINTERS* pExp)
{
unsigned dwCode = (pExp && pExp->ExceptionRecord) ? pExp->ExceptionRecord->ExceptionCode : 0;
throw SE_Exception((long)dwCode);
}
public:
SE_Handler() { fnOld = _set_se_translator(seh_trans_func); }
~SE_Handler() { _set_se_translator(fnOld); }
#else
public:
SE_Handler() {}
#endif
};