winmm: Avoid explicitly casting the pointer returned from Heap(Re)Alloc.
[wine.git] / dlls / msvcrt / exception_ptr.c
blobbd341ac49a11510d289a1fff18b3355bd2bb49d0
1 /*
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
21 #include <stdarg.h>
22 #include <stdbool.h>
24 #include "windef.h"
25 #include "winternl.h"
26 #include "wine/exception.h"
27 #include "wine/debug.h"
28 #include "msvcrt.h"
29 #include "cxx.h"
31 #ifdef __i386__
33 extern void call_copy_ctor( void *func, void *this, void *src, int has_vbase );
35 __ASM_GLOBAL_FUNC( call_copy_ctor,
36 "pushl %ebp\n\t"
37 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
38 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
39 "movl %esp, %ebp\n\t"
40 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
41 "pushl $1\n\t"
42 "movl 12(%ebp), %ecx\n\t"
43 "pushl 16(%ebp)\n\t"
44 "call *8(%ebp)\n\t"
45 "leave\n"
46 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
47 __ASM_CFI(".cfi_same_value %ebp\n\t")
48 "ret" );
50 #elif _MSVCR_VER >= 100
52 static inline void call_copy_ctor( void *func, void *this, void *src, int has_vbase )
54 if (has_vbase)
55 ((void (__cdecl*)(void*, void*, BOOL))func)(this, src, 1);
56 else
57 ((void (__cdecl*)(void*, void*))func)(this, src);
60 #endif
62 #if _MSVCR_VER >= 100
64 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
66 /*********************************************************************
67 * ?__ExceptionPtrCreate@@YAXPAX@Z
68 * ?__ExceptionPtrCreate@@YAXPEAX@Z
70 void __cdecl __ExceptionPtrCreate(exception_ptr *ep)
72 TRACE("(%p)\n", ep);
74 ep->rec = NULL;
75 ep->ref = NULL;
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"
83 "call *8(%esp)\n\t"
84 "ret" );
85 #elif __x86_64__
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);
90 func(object);
92 #else
93 #define call_dtor(type, func, object) ((void (__thiscall*)(void*))(func))(object)
94 #endif
96 /*********************************************************************
97 * ?__ExceptionPtrDestroy@@YAXPAX@Z
98 * ?__ExceptionPtrDestroy@@YAXPEAX@Z
100 void __cdecl __ExceptionPtrDestroy(exception_ptr *ep)
102 TRACE("(%p)\n", ep);
104 if (!ep->rec)
105 return;
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);
123 #ifndef _CONCRT
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 */
134 *ep = *copy;
135 if (ep->ref)
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 */
148 if (ep->ref)
149 InterlockedDecrement(ep->ref);
151 *ep = *assign;
152 if (ep->ref)
153 InterlockedIncrement(ep->ref);
156 #endif
158 /*********************************************************************
159 * ?__ExceptionPtrRethrow@@YAXPBX@Z
160 * ?__ExceptionPtrRethrow@@YAXPEBX@Z
162 void __cdecl __ExceptionPtrRethrow(const exception_ptr *ep)
164 TRACE("(%p)\n", ep);
166 if (!ep->rec)
168 throw_exception("bad exception");
169 return;
172 RaiseException(ep->rec->ExceptionCode, ep->rec->ExceptionFlags & (~EH_UNWINDING),
173 ep->rec->NumberParameters, ep->rec->ExceptionInformation);
176 #ifndef __x86_64__
177 void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec)
179 TRACE("(%p)\n", ep);
181 if (!rec)
183 ep->rec = NULL;
184 ep->ref = NULL;
185 return;
188 ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
189 ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
191 *ep->rec = *rec;
192 *ep->ref = 1;
194 if (ep->rec->ExceptionCode == CXX_EXCEPTION)
196 const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
197 const cxx_type_info *ti;
198 void **data, *obj;
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);
214 else
215 memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
216 ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
218 return;
220 #else
221 void exception_ptr_from_record(exception_ptr *ep, EXCEPTION_RECORD *rec)
223 TRACE("(%p)\n", ep);
225 if (!rec)
227 ep->rec = NULL;
228 ep->ref = NULL;
229 return;
232 ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
233 ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
235 *ep->rec = *rec;
236 *ep->ref = 1;
238 if (ep->rec->ExceptionCode == CXX_EXCEPTION)
240 const cxx_exception_type *et = (void*)ep->rec->ExceptionInformation[2];
241 const cxx_type_info *ti;
242 void **data, *obj;
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);
259 else
260 memcpy(data, get_this_pointer(&ti->offsets, obj), ti->size);
261 ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
263 return;
265 #endif
267 #ifndef _CONCRT
269 /*********************************************************************
270 * ?__ExceptionPtrCurrentException@@YAXPAX@Z
271 * ?__ExceptionPtrCurrentException@@YAXPEAX@Z
273 void __cdecl __ExceptionPtrCurrentException(exception_ptr *ep)
275 TRACE("(%p)\n", 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)
286 return !!ep->rec;
288 #endif
290 /*********************************************************************
291 * ?__ExceptionPtrCopyException@@YAXPAXPBX1@Z
292 * ?__ExceptionPtrCopyException@@YAXPEAXPEBX1@Z
294 #ifndef __x86_64__
295 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
296 exception *object, const cxx_exception_type *type)
298 const cxx_type_info *ti;
299 void **data;
301 __ExceptionPtrDestroy(ep);
303 ep->rec = HeapAlloc(GetProcessHeap(), 0, sizeof(EXCEPTION_RECORD));
304 ep->ref = HeapAlloc(GetProcessHeap(), 0, sizeof(int));
305 *ep->ref = 1;
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);
326 else
327 memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
328 ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
330 #else
331 void __cdecl __ExceptionPtrCopyException(exception_ptr *ep,
332 exception *object, const cxx_exception_type *type)
334 const cxx_type_info *ti;
335 void **data;
336 char *base;
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));
343 *ep->ref = 1;
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);
365 else
366 memcpy(data, get_this_pointer(&ti->offsets, object), ti->size);
367 ep->rec->ExceptionInformation[1] = (ULONG_PTR)data;
369 #endif
371 bool __cdecl __ExceptionPtrCompare(const exception_ptr *ep1, const exception_ptr *ep2)
373 return ep1->rec == ep2->rec;
376 #endif
378 #endif /* _MSVCR_VER >= 100 */