2 * std::exception_ptr helper functions
4 * Copyright 2022 Torge Matthies for CodeWeavers
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "wine/exception.h"
27 #include "wine/debug.h"
33 extern void call_copy_ctor( void *func
, void *this, void *src
, int has_vbase
);
35 __ASM_GLOBAL_FUNC( call_copy_ctor
,
37 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
38 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
40 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
42 "movl 12(%ebp), %ecx\n\t"
46 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
47 __ASM_CFI(".cfi_same_value %ebp\n\t")
50 #elif _MSVCR_VER >= 100
52 static inline void call_copy_ctor( void *func
, void *this, void *src
, int has_vbase
)
55 ((void (__cdecl
*)(void*, void*, BOOL
))func
)(this, src
, 1);
57 ((void (__cdecl
*)(void*, void*))func
)(this, src
);
64 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
66 /*********************************************************************
67 * ?__ExceptionPtrCreate@@YAXPAX@Z
68 * ?__ExceptionPtrCreate@@YAXPEAX@Z
70 void __cdecl
__ExceptionPtrCreate(exception_ptr
*ep
)
78 #ifdef __ASM_USE_THISCALL_WRAPPER
79 extern void call_dtor(const cxx_exception_type
*type
, void *func
, void *object
);
81 __ASM_GLOBAL_FUNC( call_dtor
,
82 "movl 12(%esp),%ecx\n\t"
86 static inline void call_dtor(const cxx_exception_type
*type
, unsigned int dtor
, void *object
)
88 char *base
= RtlPcToFileHeader((void*)type
, (void**)&base
);
89 void (__cdecl
*func
)(void*) = (void*)(base
+ dtor
);
93 #define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object)
96 /*********************************************************************
97 * ?__ExceptionPtrDestroy@@YAXPAX@Z
98 * ?__ExceptionPtrDestroy@@YAXPEAX@Z
100 void __cdecl
__ExceptionPtrDestroy(exception_ptr
*ep
)
107 if (!InterlockedDecrement(ep
->ref
))
109 if (ep
->rec
->ExceptionCode
== CXX_EXCEPTION
)
111 const cxx_exception_type
*type
= (void*)ep
->rec
->ExceptionInformation
[2];
112 void *obj
= (void*)ep
->rec
->ExceptionInformation
[1];
114 if (type
&& type
->destructor
) call_dtor(type
, type
->destructor
, obj
);
115 HeapFree(GetProcessHeap(), 0, obj
);
118 HeapFree(GetProcessHeap(), 0, ep
->rec
);
119 HeapFree(GetProcessHeap(), 0, ep
->ref
);
125 /*********************************************************************
126 * ?__ExceptionPtrCopy@@YAXPAXPBX@Z
127 * ?__ExceptionPtrCopy@@YAXPEAXPEBX@Z
129 void __cdecl
__ExceptionPtrCopy(exception_ptr
*ep
, const exception_ptr
*copy
)
131 TRACE("(%p %p)\n", ep
, copy
);
133 /* don't destroy object stored in ep */
136 InterlockedIncrement(copy
->ref
);
139 /*********************************************************************
140 * ?__ExceptionPtrAssign@@YAXPAXPBX@Z
141 * ?__ExceptionPtrAssign@@YAXPEAXPEBX@Z
143 void __cdecl
__ExceptionPtrAssign(exception_ptr
*ep
, const exception_ptr
*assign
)
145 TRACE("(%p %p)\n", ep
, assign
);
147 /* don't destroy object stored in ep */
149 InterlockedDecrement(ep
->ref
);
153 InterlockedIncrement(ep
->ref
);
158 /*********************************************************************
159 * ?__ExceptionPtrRethrow@@YAXPBX@Z
160 * ?__ExceptionPtrRethrow@@YAXPEBX@Z
162 void __cdecl
__ExceptionPtrRethrow(const exception_ptr
*ep
)
168 throw_exception("bad exception");
172 RaiseException(ep
->rec
->ExceptionCode
, ep
->rec
->ExceptionFlags
& (~EH_UNWINDING
),
173 ep
->rec
->NumberParameters
, ep
->rec
->ExceptionInformation
);
177 void exception_ptr_from_record(exception_ptr
*ep
, EXCEPTION_RECORD
*rec
)
188 ep
->rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD
));
189 ep
->ref
= HeapAlloc(GetProcessHeap(), 0, sizeof(int));
194 if (ep
->rec
->ExceptionCode
== CXX_EXCEPTION
)
196 const cxx_exception_type
*et
= (void*)ep
->rec
->ExceptionInformation
[2];
197 const cxx_type_info
*ti
;
200 ti
= et
->type_info_table
->info
[0];
201 data
= HeapAlloc(GetProcessHeap(), 0, ti
->size
);
203 obj
= (void*)ep
->rec
->ExceptionInformation
[1];
204 if (ti
->flags
& CLASS_IS_SIMPLE_TYPE
)
206 memcpy(data
, obj
, ti
->size
);
207 if (ti
->size
== sizeof(void *)) *data
= get_this_pointer(&ti
->offsets
, *data
);
209 else if (ti
->copy_ctor
)
211 call_copy_ctor(ti
->copy_ctor
, data
, get_this_pointer(&ti
->offsets
, obj
),
212 ti
->flags
& CLASS_HAS_VIRTUAL_BASE_CLASS
);
215 memcpy(data
, get_this_pointer(&ti
->offsets
, obj
), ti
->size
);
216 ep
->rec
->ExceptionInformation
[1] = (ULONG_PTR
)data
;
221 void exception_ptr_from_record(exception_ptr
*ep
, EXCEPTION_RECORD
*rec
)
232 ep
->rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD
));
233 ep
->ref
= HeapAlloc(GetProcessHeap(), 0, sizeof(int));
238 if (ep
->rec
->ExceptionCode
== CXX_EXCEPTION
)
240 const cxx_exception_type
*et
= (void*)ep
->rec
->ExceptionInformation
[2];
241 const cxx_type_info
*ti
;
243 char *base
= RtlPcToFileHeader((void*)et
, (void**)&base
);
245 ti
= (const cxx_type_info
*)(base
+ ((const cxx_type_info_table
*)(base
+ et
->type_info_table
))->info
[0]);
246 data
= HeapAlloc(GetProcessHeap(), 0, ti
->size
);
248 obj
= (void*)ep
->rec
->ExceptionInformation
[1];
249 if (ti
->flags
& CLASS_IS_SIMPLE_TYPE
)
251 memcpy(data
, obj
, ti
->size
);
252 if (ti
->size
== sizeof(void *)) *data
= get_this_pointer(&ti
->offsets
, *data
);
254 else if (ti
->copy_ctor
)
256 call_copy_ctor(base
+ ti
->copy_ctor
, data
, get_this_pointer(&ti
->offsets
, obj
),
257 ti
->flags
& CLASS_HAS_VIRTUAL_BASE_CLASS
);
260 memcpy(data
, get_this_pointer(&ti
->offsets
, obj
), ti
->size
);
261 ep
->rec
->ExceptionInformation
[1] = (ULONG_PTR
)data
;
269 /*********************************************************************
270 * ?__ExceptionPtrCurrentException@@YAXPAX@Z
271 * ?__ExceptionPtrCurrentException@@YAXPEAX@Z
273 void __cdecl
__ExceptionPtrCurrentException(exception_ptr
*ep
)
276 exception_ptr_from_record(ep
, msvcrt_get_thread_data()->exc_record
);
279 #if _MSVCR_VER >= 110
280 /*********************************************************************
281 * ?__ExceptionPtrToBool@@YA_NPBX@Z
282 * ?__ExceptionPtrToBool@@YA_NPEBX@Z
284 bool __cdecl
__ExceptionPtrToBool(exception_ptr
*ep
)
290 /*********************************************************************
291 * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
292 * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
295 void __cdecl
__ExceptionPtrCopyException(exception_ptr
*ep
,
296 exception
*object
, const cxx_exception_type
*type
)
298 const cxx_type_info
*ti
;
301 __ExceptionPtrDestroy(ep
);
303 ep
->rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD
));
304 ep
->ref
= HeapAlloc(GetProcessHeap(), 0, sizeof(int));
307 memset(ep
->rec
, 0, sizeof(EXCEPTION_RECORD
));
308 ep
->rec
->ExceptionCode
= CXX_EXCEPTION
;
309 ep
->rec
->ExceptionFlags
= EH_NONCONTINUABLE
;
310 ep
->rec
->NumberParameters
= 3;
311 ep
->rec
->ExceptionInformation
[0] = CXX_FRAME_MAGIC_VC6
;
312 ep
->rec
->ExceptionInformation
[2] = (ULONG_PTR
)type
;
314 ti
= type
->type_info_table
->info
[0];
315 data
= HeapAlloc(GetProcessHeap(), 0, ti
->size
);
316 if (ti
->flags
& CLASS_IS_SIMPLE_TYPE
)
318 memcpy(data
, object
, ti
->size
);
319 if (ti
->size
== sizeof(void *)) *data
= get_this_pointer(&ti
->offsets
, *data
);
321 else if (ti
->copy_ctor
)
323 call_copy_ctor(ti
->copy_ctor
, data
, get_this_pointer(&ti
->offsets
, object
),
324 ti
->flags
& CLASS_HAS_VIRTUAL_BASE_CLASS
);
327 memcpy(data
, get_this_pointer(&ti
->offsets
, object
), ti
->size
);
328 ep
->rec
->ExceptionInformation
[1] = (ULONG_PTR
)data
;
331 void __cdecl
__ExceptionPtrCopyException(exception_ptr
*ep
,
332 exception
*object
, const cxx_exception_type
*type
)
334 const cxx_type_info
*ti
;
338 RtlPcToFileHeader((void*)type
, (void**)&base
);
339 __ExceptionPtrDestroy(ep
);
341 ep
->rec
= HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD
));
342 ep
->ref
= HeapAlloc(GetProcessHeap(), 0, sizeof(int));
345 memset(ep
->rec
, 0, sizeof(EXCEPTION_RECORD
));
346 ep
->rec
->ExceptionCode
= CXX_EXCEPTION
;
347 ep
->rec
->ExceptionFlags
= EH_NONCONTINUABLE
;
348 ep
->rec
->NumberParameters
= 4;
349 ep
->rec
->ExceptionInformation
[0] = CXX_FRAME_MAGIC_VC6
;
350 ep
->rec
->ExceptionInformation
[2] = (ULONG_PTR
)type
;
351 ep
->rec
->ExceptionInformation
[3] = (ULONG_PTR
)base
;
353 ti
= (const cxx_type_info
*)(base
+ ((const cxx_type_info_table
*)(base
+ type
->type_info_table
))->info
[0]);
354 data
= HeapAlloc(GetProcessHeap(), 0, ti
->size
);
355 if (ti
->flags
& CLASS_IS_SIMPLE_TYPE
)
357 memcpy(data
, object
, ti
->size
);
358 if (ti
->size
== sizeof(void *)) *data
= get_this_pointer(&ti
->offsets
, *data
);
360 else if (ti
->copy_ctor
)
362 call_copy_ctor(base
+ ti
->copy_ctor
, data
, get_this_pointer(&ti
->offsets
, object
),
363 ti
->flags
& CLASS_HAS_VIRTUAL_BASE_CLASS
);
366 memcpy(data
, get_this_pointer(&ti
->offsets
, object
), ti
->size
);
367 ep
->rec
->ExceptionInformation
[1] = (ULONG_PTR
)data
;
371 bool __cdecl
__ExceptionPtrCompare(const exception_ptr
*ep1
, const exception_ptr
*ep2
)
373 return ep1
->rec
== ep2
->rec
;
378 #endif /* _MSVCR_VER >= 100 */