Sync to trunk head (r42241)
[reactos.git] / reactos / lib / sdk / crt / include / internal / wine / cppexcept.h
1 /*
2 * msvcrt C++ exception handling
3 *
4 * Copyright 2002 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifndef __MSVCRT_CPPEXCEPT_H
22 #define __MSVCRT_CPPEXCEPT_H
23
24 #include <pseh/pseh2.h>
25
26 /* Macros to define assembler functions somewhat portably */
27
28 #define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"
29 #define __ASM_NAME(name) "_" name
30
31 #ifdef __GNUC__
32 # define __ASM_GLOBAL_FUNC(name,code) \
33 __asm__( ".align 4\n\t" \
34 ".globl " __ASM_NAME(#name) "\n\t" \
35 __ASM_FUNC(#name) "\n" \
36 __ASM_NAME(#name) ":\n\t" \
37 code );
38 #else /* __GNUC__ */
39 # define __ASM_GLOBAL_FUNC(name,code) \
40 void __asm_dummy_##name(void) { \
41 asm( ".align 4\n\t" \
42 ".globl " __ASM_NAME(#name) "\n\t" \
43 __ASM_FUNC(#name) "\n" \
44 __ASM_NAME(#name) ":\n\t" \
45 code ); \
46 }
47 #endif /* __GNUC__ */
48
49 #define EH_NONCONTINUABLE 0x01
50 #define EH_UNWINDING 0x02
51 #define EH_EXIT_UNWIND 0x04
52 #define EH_STACK_INVALID 0x08
53 #define EH_NESTED_CALL 0x10
54
55 #ifndef _M_ARM
56 static inline EXCEPTION_REGISTRATION_RECORD *__wine_push_frame( EXCEPTION_REGISTRATION_RECORD *frame )
57 {
58 #if defined(__i386__)
59 frame->Next = (struct _EXCEPTION_REGISTRATION_RECORD *)__readfsdword(0);
60 __writefsdword(0, (unsigned long)frame);
61 return frame->Next;
62 #else
63 NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
64 frame->Next = teb->ExceptionList;
65 teb->ExceptionList = frame;
66 return frame->Next;
67 #endif
68 }
69
70 static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTRATION_RECORD *frame )
71 {
72 #if defined(__i386__)
73 __writefsdword(0, (unsigned long)frame->Next);
74 return frame->Next;
75 #else
76 NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
77 teb->ExceptionList = frame->Next;
78 return frame->Next;
79 #endif
80 }
81 #endif
82
83 #define __TRY _SEH2_TRY
84 #define __EXCEPT(func) _SEH2_EXCEPT(func(_SEH2_GetExceptionInformation()))
85 #define __EXCEPT_PAGE_FAULT _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_ACCESS_VIOLATION)
86 #define __EXCEPT_ALL _SEH2_EXCEPT(_SEH_EXECUTE_HANDLER)
87 #define __ENDTRY _SEH2_END
88 #define __FINALLY(func) _SEH2_FINALLY { func(!_SEH2_AbnormalTermination()); }
89
90 #define CXX_FRAME_MAGIC 0x19930520
91 #define CXX_EXCEPTION 0xe06d7363
92
93 typedef void (*vtable_ptr)();
94
95 /* type_info object, see cpp.c for inplementation */
96 typedef struct __type_info
97 {
98 const vtable_ptr *vtable;
99 char *name; /* Unmangled name, allocated lazily */
100 char mangled[32]; /* Variable length, but we declare it large enough for static RTTI */
101 } type_info;
102
103 /* exception object */
104 typedef struct __exception
105 {
106 const vtable_ptr *vtable;
107 char *name; /* Name of this exception, always a new copy for each object */
108 int do_free; /* Whether to free 'name' in our dtor */
109 } exception;
110
111 /* the exception frame used by CxxFrameHandler */
112 typedef struct __cxx_exception_frame
113 {
114 EXCEPTION_REGISTRATION_RECORD frame; /* the standard exception frame */
115 int trylevel;
116 DWORD ebp;
117 } cxx_exception_frame;
118
119 /* info about a single catch {} block */
120 typedef struct __catchblock_info
121 {
122 UINT flags; /* flags (see below) */
123 type_info *type_info; /* C++ type caught by this block */
124 int offset; /* stack offset to copy exception object to */
125 void (*handler)(); /* catch block handler code */
126 } catchblock_info;
127 #define TYPE_FLAG_CONST 1
128 #define TYPE_FLAG_VOLATILE 2
129 #define TYPE_FLAG_REFERENCE 8
130
131 /* info about a single try {} block */
132 typedef struct __tryblock_info
133 {
134 int start_level; /* start trylevel of that block */
135 int end_level; /* end trylevel of that block */
136 int catch_level; /* initial trylevel of the catch block */
137 int catchblock_count; /* count of catch blocks in array */
138 catchblock_info *catchblock; /* array of catch blocks */
139 } tryblock_info;
140
141 /* info about the unwind handler for a given trylevel */
142 typedef struct __unwind_info
143 {
144 int prev; /* prev trylevel unwind handler, to run after this one */
145 void (*handler)(); /* unwind handler */
146 } unwind_info;
147
148 /* descriptor of all try blocks of a given function */
149 typedef struct __cxx_function_descr
150 {
151 UINT magic; /* must be CXX_FRAME_MAGIC */
152 UINT unwind_count; /* number of unwind handlers */
153 unwind_info *unwind_table; /* array of unwind handlers */
154 UINT tryblock_count; /* number of try blocks */
155 tryblock_info *tryblock; /* array of try blocks */
156 UINT unknown[3];
157 } cxx_function_descr;
158
159 typedef void (*cxx_copy_ctor)(void);
160
161 /* offsets for computing the this pointer */
162 typedef struct
163 {
164 int this_offset; /* offset of base class this pointer from start of object */
165 int vbase_descr; /* offset of virtual base class descriptor */
166 int vbase_offset; /* offset of this pointer offset in virtual base class descriptor */
167 } this_ptr_offsets;
168
169 /* complete information about a C++ type */
170 typedef struct __cxx_type_info
171 {
172 UINT flags; /* flags (see CLASS_* flags below) */
173 const type_info *type_info; /* C++ type info */
174 this_ptr_offsets offsets; /* offsets for computing the this pointer */
175 unsigned int size; /* object size */
176 cxx_copy_ctor copy_ctor; /* copy constructor */
177 } cxx_type_info;
178 #define CLASS_IS_SIMPLE_TYPE 1
179 #define CLASS_HAS_VIRTUAL_BASE_CLASS 4
180
181 /* table of C++ types that apply for a given object */
182 typedef struct __cxx_type_info_table
183 {
184 UINT count; /* number of types */
185 const cxx_type_info *info[3]; /* variable length, we declare it large enough for static RTTI */
186 } cxx_type_info_table;
187
188 typedef DWORD (*cxx_exc_custom_handler)( PEXCEPTION_RECORD, cxx_exception_frame*,
189 PCONTEXT, EXCEPTION_REGISTRATION_RECORD**,
190 const cxx_function_descr*, int nested_trylevel,
191 EXCEPTION_REGISTRATION_RECORD *nested_frame, DWORD unknown3 );
192
193 /* type information for an exception object */
194 typedef struct __cxx_exception_type
195 {
196 UINT flags; /* TYPE_FLAG flags */
197 void (*destructor)(); /* exception object destructor */
198 cxx_exc_custom_handler custom_handler; /* custom handler for this exception */
199 const cxx_type_info_table *type_info_table; /* list of types for this exception object */
200 } cxx_exception_type;
201
202 void _CxxThrowException(exception*,const cxx_exception_type*);
203
204 static inline const char *dbgstr_type_info( const type_info *info )
205 {
206 if (!info) return "{}";
207 return "{}";/*sprintf( "{vtable=%p name=%s (%s)}",
208 info->vtable, info->mangled, info->name ? info->name : "" );*/
209 }
210
211 /* compute the this pointer for a base class of a given type */
212 static inline void *get_this_pointer( const this_ptr_offsets *off, void *object )
213 {
214 void *this_ptr;
215 int *offset_ptr;
216
217 if (!object) return NULL;
218 this_ptr = (char *)object + off->this_offset;
219 if (off->vbase_descr >= 0)
220 {
221 /* move this ptr to vbase descriptor */
222 this_ptr = (char *)this_ptr + off->vbase_descr;
223 /* and fetch additional offset from vbase descriptor */
224 offset_ptr = (int *)(*(char **)this_ptr + off->vbase_offset);
225 this_ptr = (char *)this_ptr + *offset_ptr;
226 }
227 return this_ptr;
228 }
229
230 #endif /* __MSVCRT_CPPEXCEPT_H */