2 * msvcrt C++ exception handling
4 * Copyright 2011 Alexandre Julliard
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
28 #define WIN32_NO_STATUS
33 #include "wine/exception.h"
35 #include "wine/debug.h"
37 #include "cppexcept.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(seh
);
55 #define TYPE_FLAG_CONST 1
56 #define TYPE_FLAG_VOLATILE 2
57 #define TYPE_FLAG_REFERENCE 8
74 typedef struct __cxx_function_descr
90 cxx_frame_info frame_info
;
92 EXCEPTION_RECORD
*prev_rec
;
99 EXCEPTION_RECORD
*seh_rec
;
100 DISPATCHER_CONTEXT
*dispatch
;
101 const cxx_function_descr
*descr
;
104 static inline void* rva_to_ptr(UINT rva
, ULONG64 base
)
106 return rva
? (void*)(base
+rva
) : NULL
;
109 static inline void dump_type(UINT type_rva
, ULONG64 base
)
111 const cxx_type_info
*type
= rva_to_ptr(type_rva
, base
);
113 TRACE("flags %x type %x %s offsets %d,%d,%d size %d copy ctor %x(%p)\n",
114 type
->flags
, type
->type_info
, dbgstr_type_info(rva_to_ptr(type
->type_info
, base
)),
115 type
->offsets
.this_offset
, type
->offsets
.vbase_descr
, type
->offsets
.vbase_offset
,
116 type
->size
, type
->copy_ctor
, rva_to_ptr(type
->copy_ctor
, base
));
119 static void dump_exception_type(const cxx_exception_type
*type
, ULONG64 base
)
121 const cxx_type_info_table
*type_info_table
= rva_to_ptr(type
->type_info_table
, base
);
124 TRACE("flags %x destr %x(%p) handler %x(%p) type info %x(%p)\n",
125 type
->flags
, type
->destructor
, rva_to_ptr(type
->destructor
, base
),
126 type
->custom_handler
, rva_to_ptr(type
->custom_handler
, base
),
127 type
->type_info_table
, type_info_table
);
128 for (i
= 0; i
< type_info_table
->count
; i
++)
131 dump_type(type_info_table
->info
[i
], base
);
135 static void dump_function_descr(const cxx_function_descr
*descr
, ULONG64 image_base
)
137 unwind_info
*unwind_table
= rva_to_ptr(descr
->unwind_table
, image_base
);
138 tryblock_info
*tryblock
= rva_to_ptr(descr
->tryblock
, image_base
);
139 ipmap_info
*ipmap
= rva_to_ptr(descr
->ipmap
, image_base
);
142 TRACE("magic %x\n", descr
->magic
);
143 TRACE("unwind table: %x(%p) %d\n", descr
->unwind_table
, unwind_table
, descr
->unwind_count
);
144 for (i
=0; i
<descr
->unwind_count
; i
++)
146 TRACE(" %d: prev %d func %x(%p)\n", i
, unwind_table
[i
].prev
,
147 unwind_table
[i
].handler
, rva_to_ptr(unwind_table
[i
].handler
, image_base
));
149 TRACE("try table: %x(%p) %d\n", descr
->tryblock
, tryblock
, descr
->tryblock_count
);
150 for (i
=0; i
<descr
->tryblock_count
; i
++)
152 catchblock_info
*catchblock
= rva_to_ptr(tryblock
[i
].catchblock
, image_base
);
154 TRACE(" %d: start %d end %d catchlevel %d catch %x(%p) %d\n", i
,
155 tryblock
[i
].start_level
, tryblock
[i
].end_level
,
156 tryblock
[i
].catch_level
, tryblock
[i
].catchblock
,
157 catchblock
, tryblock
[i
].catchblock_count
);
158 for (j
=0; j
<tryblock
[i
].catchblock_count
; j
++)
160 TRACE(" %d: flags %x offset %d handler %x(%p) frame %x type %x %s\n",
161 j
, catchblock
[j
].flags
, catchblock
[j
].offset
, catchblock
[j
].handler
,
162 rva_to_ptr(catchblock
[j
].handler
, image_base
), catchblock
[j
].frame
,
163 catchblock
[j
].type_info
,
164 dbgstr_type_info(rva_to_ptr(catchblock
[j
].type_info
, image_base
)));
167 TRACE("ipmap: %x(%p) %d\n", descr
->ipmap
, ipmap
, descr
->ipmap_count
);
168 for (i
=0; i
<descr
->ipmap_count
; i
++)
170 TRACE(" %d: ip %x state %d\n", i
, ipmap
[i
].ip
, ipmap
[i
].state
);
172 TRACE("unwind_help %d\n", descr
->unwind_help
);
173 if (descr
->magic
<= CXX_FRAME_MAGIC_VC6
) return;
174 TRACE("expect list: %x\n", descr
->expect_list
);
175 if (descr
->magic
<= CXX_FRAME_MAGIC_VC7
) return;
176 TRACE("flags: %08x\n", descr
->flags
);
179 static inline int ip_to_state(ipmap_info
*ipmap
, UINT count
, int ip
)
181 UINT low
= 0, high
= count
-1, med
;
184 med
= low
+ (high
-low
)/2;
186 if (ipmap
[med
].ip
<= ip
&& ipmap
[med
+1].ip
> ip
)
191 if (ipmap
[med
].ip
< ip
) low
= med
+1;
195 TRACE("%x -> %d\n", ip
, ipmap
[low
].state
);
196 return ipmap
[low
].state
;
199 /* check if the exception type is caught by a given catch block, and return the type that matched */
200 static const cxx_type_info
*find_caught_type(cxx_exception_type
*exc_type
, ULONG64 exc_base
,
201 const type_info
*catch_ti
, UINT catch_flags
)
203 const cxx_type_info_table
*type_info_table
= rva_to_ptr(exc_type
->type_info_table
, exc_base
);
206 for (i
= 0; i
< type_info_table
->count
; i
++)
208 const cxx_type_info
*type
= rva_to_ptr(type_info_table
->info
[i
], exc_base
);
209 const type_info
*ti
= rva_to_ptr(type
->type_info
, exc_base
);
211 if (!catch_ti
) return type
; /* catch(...) matches any type */
214 if (strcmp( catch_ti
->mangled
, ti
->mangled
)) continue;
216 /* type is the same, now check the flags */
217 if ((exc_type
->flags
& TYPE_FLAG_CONST
) &&
218 !(catch_flags
& TYPE_FLAG_CONST
)) continue;
219 if ((exc_type
->flags
& TYPE_FLAG_VOLATILE
) &&
220 !(catch_flags
& TYPE_FLAG_VOLATILE
)) continue;
221 return type
; /* it matched */
226 static inline void copy_exception(void *object
, ULONG64 frame
,
227 DISPATCHER_CONTEXT
*dispatch
,
228 const catchblock_info
*catchblock
,
229 const cxx_type_info
*type
, ULONG64 exc_base
)
231 const type_info
*catch_ti
= rva_to_ptr(catchblock
->type_info
, dispatch
->ImageBase
);
232 void **dest
= rva_to_ptr(catchblock
->offset
, frame
);
234 if (!catch_ti
|| !catch_ti
->mangled
[0]) return;
235 if (!catchblock
->offset
) return;
237 if (catchblock
->flags
& TYPE_FLAG_REFERENCE
)
239 *dest
= get_this_pointer(&type
->offsets
, object
);
241 else if (type
->flags
& CLASS_IS_SIMPLE_TYPE
)
243 memmove(dest
, object
, type
->size
);
244 /* if it is a pointer, adjust it */
245 if (type
->size
== sizeof(void*)) *dest
= get_this_pointer(&type
->offsets
, *dest
);
247 else /* copy the object */
251 if (type
->flags
& CLASS_HAS_VIRTUAL_BASE_CLASS
)
253 void (__cdecl
*copy_ctor
)(void*, void*, int) =
254 rva_to_ptr(type
->copy_ctor
, exc_base
);
255 copy_ctor(dest
, get_this_pointer(&type
->offsets
, object
), 1);
259 void (__cdecl
*copy_ctor
)(void*, void*) =
260 rva_to_ptr(type
->copy_ctor
, exc_base
);
261 copy_ctor(dest
, get_this_pointer(&type
->offsets
, object
));
265 memmove(dest
, get_this_pointer(&type
->offsets
,object
), type
->size
);
269 static void cxx_local_unwind(ULONG64 frame
, DISPATCHER_CONTEXT
*dispatch
,
270 const cxx_function_descr
*descr
, int last_level
)
272 const unwind_info
*unwind_table
= rva_to_ptr(descr
->unwind_table
, dispatch
->ImageBase
);
273 void (__cdecl
*handler
)(ULONG64 unk
, ULONG64 rbp
);
274 int *unwind_help
= rva_to_ptr(descr
->unwind_help
, frame
);
277 if (unwind_help
[0] == -2)
279 trylevel
= ip_to_state(rva_to_ptr(descr
->ipmap
, dispatch
->ImageBase
),
280 descr
->ipmap_count
, dispatch
->ControlPc
-dispatch
->ImageBase
);
284 trylevel
= unwind_help
[0];
287 TRACE("current level: %d, last level: %d\n", trylevel
, last_level
);
288 while (trylevel
> last_level
)
290 if (trylevel
<0 || trylevel
>=descr
->unwind_count
)
292 ERR("invalid trylevel %d\n", trylevel
);
295 handler
= rva_to_ptr(unwind_table
[trylevel
].handler
, dispatch
->ImageBase
);
298 TRACE("handler: %p\n", handler
);
301 trylevel
= unwind_table
[trylevel
].prev
;
303 unwind_help
[0] = trylevel
;
306 static LONG CALLBACK
cxx_rethrow_filter(PEXCEPTION_POINTERS eptrs
, void *c
)
308 EXCEPTION_RECORD
*rec
= eptrs
->ExceptionRecord
;
309 cxx_catch_ctx
*ctx
= c
;
311 if (rec
->ExceptionCode
!= CXX_EXCEPTION
)
312 return EXCEPTION_CONTINUE_SEARCH
;
313 if (!rec
->ExceptionInformation
[1] && !rec
->ExceptionInformation
[2])
314 return EXCEPTION_EXECUTE_HANDLER
;
315 if (rec
->ExceptionInformation
[1] == ctx
->prev_rec
->ExceptionInformation
[1])
317 return EXCEPTION_CONTINUE_SEARCH
;
320 static void CALLBACK
cxx_catch_cleanup(BOOL normal
, void *c
)
322 cxx_catch_ctx
*ctx
= c
;
323 __CxxUnregisterExceptionObject(&ctx
->frame_info
, ctx
->rethrow
);
326 static void* WINAPI
call_catch_block(EXCEPTION_RECORD
*rec
)
328 ULONG64 frame
= rec
->ExceptionInformation
[1];
329 const cxx_function_descr
*descr
= (void*)rec
->ExceptionInformation
[2];
330 EXCEPTION_RECORD
*prev_rec
= (void*)rec
->ExceptionInformation
[4];
331 EXCEPTION_RECORD
*untrans_rec
= (void*)rec
->ExceptionInformation
[6];
332 CONTEXT
*context
= (void*)rec
->ExceptionInformation
[7];
333 void* (__cdecl
*handler
)(ULONG64 unk
, ULONG64 rbp
) = (void*)rec
->ExceptionInformation
[5];
334 int *unwind_help
= rva_to_ptr(descr
->unwind_help
, frame
);
335 EXCEPTION_POINTERS ep
= { prev_rec
, context
};
337 void *ret_addr
= NULL
;
339 TRACE("calling handler %p\n", handler
);
342 ctx
.prev_rec
= prev_rec
;
343 __CxxRegisterExceptionObject(&ep
, &ctx
.frame_info
);
344 msvcrt_get_thread_data()->processing_throw
--;
349 ret_addr
= handler(0, frame
);
351 __EXCEPT_CTX(cxx_rethrow_filter
, &ctx
)
353 TRACE("detect rethrow: exception code: %lx\n", prev_rec
->ExceptionCode
);
358 __DestructExceptionObject(prev_rec
);
359 RaiseException(untrans_rec
->ExceptionCode
, untrans_rec
->ExceptionFlags
,
360 untrans_rec
->NumberParameters
, untrans_rec
->ExceptionInformation
);
364 RaiseException(prev_rec
->ExceptionCode
, prev_rec
->ExceptionFlags
,
365 prev_rec
->NumberParameters
, prev_rec
->ExceptionInformation
);
370 __FINALLY_CTX(cxx_catch_cleanup
, &ctx
)
377 static inline BOOL
cxx_is_consolidate(const EXCEPTION_RECORD
*rec
)
379 return rec
->ExceptionCode
==STATUS_UNWIND_CONSOLIDATE
&& rec
->NumberParameters
==8 &&
380 rec
->ExceptionInformation
[0]==(ULONG_PTR
)call_catch_block
;
383 static inline void find_catch_block(EXCEPTION_RECORD
*rec
, CONTEXT
*context
,
384 EXCEPTION_RECORD
*untrans_rec
,
385 ULONG64 frame
, DISPATCHER_CONTEXT
*dispatch
,
386 const cxx_function_descr
*descr
,
387 cxx_exception_type
*info
, ULONG64 orig_frame
)
389 ULONG64 exc_base
= (rec
->NumberParameters
== 4 ? rec
->ExceptionInformation
[3] : 0);
390 int trylevel
= ip_to_state(rva_to_ptr(descr
->ipmap
, dispatch
->ImageBase
),
391 descr
->ipmap_count
, dispatch
->ControlPc
-dispatch
->ImageBase
);
392 thread_data_t
*data
= msvcrt_get_thread_data();
393 const tryblock_info
*in_catch
;
394 EXCEPTION_RECORD catch_record
;
399 data
->processing_throw
++;
400 for (i
=descr
->tryblock_count
; i
>0; i
--)
402 in_catch
= rva_to_ptr(descr
->tryblock
, dispatch
->ImageBase
);
403 in_catch
= &in_catch
[i
-1];
405 if (trylevel
>in_catch
->end_level
&& trylevel
<=in_catch
->catch_level
)
411 unwind_help
= rva_to_ptr(descr
->unwind_help
, orig_frame
);
412 if (trylevel
> unwind_help
[1])
413 unwind_help
[0] = unwind_help
[1] = trylevel
;
415 trylevel
= unwind_help
[1];
416 TRACE("current trylevel: %d\n", trylevel
);
418 for (i
=0; i
<descr
->tryblock_count
; i
++)
420 const tryblock_info
*tryblock
= rva_to_ptr(descr
->tryblock
, dispatch
->ImageBase
);
421 tryblock
= &tryblock
[i
];
423 if (trylevel
< tryblock
->start_level
) continue;
424 if (trylevel
> tryblock
->end_level
) continue;
428 if(tryblock
->start_level
<= in_catch
->end_level
) continue;
429 if(tryblock
->end_level
> in_catch
->catch_level
) continue;
432 /* got a try block */
433 for (j
=0; j
<tryblock
->catchblock_count
; j
++)
435 const catchblock_info
*catchblock
= rva_to_ptr(tryblock
->catchblock
, dispatch
->ImageBase
);
436 catchblock
= &catchblock
[j
];
440 const cxx_type_info
*type
= find_caught_type(info
, exc_base
,
441 rva_to_ptr(catchblock
->type_info
, dispatch
->ImageBase
),
445 TRACE("matched type %p in tryblock %d catchblock %d\n", type
, i
, j
);
447 /* copy the exception to its destination on the stack */
448 copy_exception((void*)rec
->ExceptionInformation
[1],
449 orig_frame
, dispatch
, catchblock
, type
, exc_base
);
453 /* no CXX_EXCEPTION only proceed with a catch(...) block*/
454 if (catchblock
->type_info
)
456 TRACE("found catch(...) block\n");
459 /* unwind stack and call catch */
460 memset(&catch_record
, 0, sizeof(catch_record
));
461 catch_record
.ExceptionCode
= STATUS_UNWIND_CONSOLIDATE
;
462 catch_record
.ExceptionFlags
= EXCEPTION_NONCONTINUABLE
;
463 catch_record
.NumberParameters
= 8;
464 catch_record
.ExceptionInformation
[0] = (ULONG_PTR
)call_catch_block
;
465 catch_record
.ExceptionInformation
[1] = orig_frame
;
466 catch_record
.ExceptionInformation
[2] = (ULONG_PTR
)descr
;
467 catch_record
.ExceptionInformation
[3] = tryblock
->start_level
;
468 catch_record
.ExceptionInformation
[4] = (ULONG_PTR
)rec
;
469 catch_record
.ExceptionInformation
[5] =
470 (ULONG_PTR
)rva_to_ptr(catchblock
->handler
, dispatch
->ImageBase
);
471 catch_record
.ExceptionInformation
[6] = (ULONG_PTR
)untrans_rec
;
472 catch_record
.ExceptionInformation
[7] = (ULONG_PTR
)context
;
473 RtlUnwindEx((void*)frame
, (void*)dispatch
->ControlPc
, &catch_record
, NULL
, &ctx
, NULL
);
477 TRACE("no matching catch block found\n");
478 data
->processing_throw
--;
481 static LONG CALLBACK
se_translation_filter(EXCEPTION_POINTERS
*ep
, void *c
)
483 se_translator_ctx
*ctx
= (se_translator_ctx
*)c
;
484 EXCEPTION_RECORD
*rec
= ep
->ExceptionRecord
;
485 cxx_exception_type
*exc_type
;
487 if (rec
->ExceptionCode
!= CXX_EXCEPTION
)
489 TRACE("non-c++ exception thrown in SEH handler: %lx\n", rec
->ExceptionCode
);
493 exc_type
= (cxx_exception_type
*)rec
->ExceptionInformation
[2];
494 find_catch_block(rec
, ep
->ContextRecord
, ctx
->seh_rec
, ctx
->dest_frame
, ctx
->dispatch
,
495 ctx
->descr
, exc_type
, ctx
->orig_frame
);
497 __DestructExceptionObject(rec
);
498 return ExceptionContinueSearch
;
501 static void check_noexcept( PEXCEPTION_RECORD rec
,
502 const cxx_function_descr
*descr
, BOOL nested
)
504 if (!nested
&& rec
->ExceptionCode
== CXX_EXCEPTION
&&
505 descr
->magic
>= CXX_FRAME_MAGIC_VC8
&&
506 (descr
->flags
& FUNC_DESCR_NOEXCEPT
))
508 ERR("noexcept function propagating exception\n");
513 static DWORD
cxx_frame_handler(EXCEPTION_RECORD
*rec
, ULONG64 frame
,
514 CONTEXT
*context
, DISPATCHER_CONTEXT
*dispatch
,
515 const cxx_function_descr
*descr
)
517 int trylevel
= ip_to_state(rva_to_ptr(descr
->ipmap
, dispatch
->ImageBase
),
518 descr
->ipmap_count
, dispatch
->ControlPc
-dispatch
->ImageBase
);
519 cxx_exception_type
*exc_type
;
520 ULONG64 orig_frame
= frame
;
522 DWORD throw_func_off
;
525 int unwindlevel
= -1;
527 if (descr
->magic
<CXX_FRAME_MAGIC_VC6
|| descr
->magic
>CXX_FRAME_MAGIC_VC8
)
529 FIXME("unhandled frame magic %x\n", descr
->magic
);
530 return ExceptionContinueSearch
;
533 if (descr
->magic
>= CXX_FRAME_MAGIC_VC8
&&
534 (descr
->flags
& FUNC_DESCR_SYNCHRONOUS
) &&
535 (rec
->ExceptionCode
!= CXX_EXCEPTION
&&
536 !cxx_is_consolidate(rec
) &&
537 rec
->ExceptionCode
!= STATUS_LONGJUMP
))
538 return ExceptionContinueSearch
; /* handle only c++ exceptions */
540 /* update orig_frame if it's a nested exception */
541 throw_func_off
= RtlLookupFunctionEntry(dispatch
->ControlPc
, &throw_base
, NULL
)->BeginAddress
;
542 throw_func
= rva_to_ptr(throw_func_off
, throw_base
);
543 TRACE("reconstructed handler pointer: %p\n", throw_func
);
544 for (i
=descr
->tryblock_count
; i
>0; i
--)
546 const tryblock_info
*tryblock
= rva_to_ptr(descr
->tryblock
, dispatch
->ImageBase
);
547 tryblock
= &tryblock
[i
-1];
549 if (trylevel
>tryblock
->end_level
&& trylevel
<=tryblock
->catch_level
)
551 for (j
=0; j
<tryblock
->catchblock_count
; j
++)
553 const catchblock_info
*catchblock
= rva_to_ptr(tryblock
->catchblock
, dispatch
->ImageBase
);
554 catchblock
= &catchblock
[j
];
556 if (rva_to_ptr(catchblock
->handler
, dispatch
->ImageBase
) == throw_func
)
558 TRACE("nested exception detected\n");
559 unwindlevel
= tryblock
->end_level
;
560 orig_frame
= *(ULONG64
*)rva_to_ptr(catchblock
->frame
, frame
);
561 TRACE("setting orig_frame to %I64x\n", orig_frame
);
567 if (rec
->ExceptionFlags
& (EH_UNWINDING
|EH_EXIT_UNWIND
))
569 if (rec
->ExceptionFlags
& EH_TARGET_UNWIND
)
570 cxx_local_unwind(orig_frame
, dispatch
, descr
,
571 cxx_is_consolidate(rec
) ? rec
->ExceptionInformation
[3] : trylevel
);
573 cxx_local_unwind(orig_frame
, dispatch
, descr
, unwindlevel
);
574 return ExceptionContinueSearch
;
576 if (!descr
->tryblock_count
)
578 check_noexcept(rec
, descr
, orig_frame
!= frame
);
579 return ExceptionContinueSearch
;
582 if (rec
->ExceptionCode
== CXX_EXCEPTION
&&
583 (!rec
->ExceptionInformation
[1] && !rec
->ExceptionInformation
[2]))
585 TRACE("rethrow detected.\n");
586 *rec
= *msvcrt_get_thread_data()->exc_record
;
588 if (rec
->ExceptionCode
== CXX_EXCEPTION
)
590 exc_type
= (cxx_exception_type
*)rec
->ExceptionInformation
[2];
594 TRACE("handling C++ exception rec %p frame %I64x descr %p\n", rec
, frame
, descr
);
595 dump_exception_type(exc_type
, rec
->ExceptionInformation
[3]);
596 dump_function_descr(descr
, dispatch
->ImageBase
);
601 thread_data_t
*data
= msvcrt_get_thread_data();
604 TRACE("handling C exception code %lx rec %p frame %I64x descr %p\n",
605 rec
->ExceptionCode
, rec
, frame
, descr
);
607 if (data
->se_translator
) {
608 EXCEPTION_POINTERS except_ptrs
;
609 se_translator_ctx ctx
;
611 ctx
.dest_frame
= frame
;
612 ctx
.orig_frame
= orig_frame
;
614 ctx
.dispatch
= dispatch
;
618 except_ptrs
.ExceptionRecord
= rec
;
619 except_ptrs
.ContextRecord
= context
;
620 data
->se_translator(rec
->ExceptionCode
, &except_ptrs
);
622 __EXCEPT_CTX(se_translation_filter
, &ctx
)
629 find_catch_block(rec
, context
, NULL
, frame
, dispatch
, descr
, exc_type
, orig_frame
);
630 check_noexcept(rec
, descr
, orig_frame
!= frame
);
631 return ExceptionContinueSearch
;
634 /*********************************************************************
635 * __CxxExceptionFilter (MSVCRT.@)
637 int CDECL
__CxxExceptionFilter( PEXCEPTION_POINTERS ptrs
,
638 const type_info
*ti
, int flags
, void **copy
)
640 FIXME( "%p %p %x %p: not implemented\n", ptrs
, ti
, flags
, copy
);
641 return EXCEPTION_CONTINUE_SEARCH
;
644 /*********************************************************************
645 * __CxxFrameHandler (MSVCRT.@)
647 EXCEPTION_DISPOSITION CDECL
__CxxFrameHandler( EXCEPTION_RECORD
*rec
, ULONG64 frame
,
648 CONTEXT
*context
, DISPATCHER_CONTEXT
*dispatch
)
650 TRACE( "%p %I64x %p %p\n", rec
, frame
, context
, dispatch
);
651 return cxx_frame_handler( rec
, frame
, context
, dispatch
,
652 rva_to_ptr(*(UINT
*)dispatch
->HandlerData
, dispatch
->ImageBase
) );
656 /*********************************************************************
657 * __CppXcptFilter (MSVCRT.@)
659 int CDECL
__CppXcptFilter(NTSTATUS ex
, PEXCEPTION_POINTERS ptr
)
661 /* only filter c++ exceptions */
662 if (ex
!= CXX_EXCEPTION
) return EXCEPTION_CONTINUE_SEARCH
;
663 return _XcptFilter( ex
, ptr
);
667 /*********************************************************************
668 * __CxxDetectRethrow (MSVCRT.@)
670 BOOL CDECL
__CxxDetectRethrow(PEXCEPTION_POINTERS ptrs
)
672 PEXCEPTION_RECORD rec
;
677 rec
= ptrs
->ExceptionRecord
;
679 if (rec
->ExceptionCode
== CXX_EXCEPTION
&&
680 rec
->NumberParameters
== 4 &&
681 rec
->ExceptionInformation
[0] == CXX_FRAME_MAGIC_VC6
&&
682 rec
->ExceptionInformation
[2])
684 ptrs
->ExceptionRecord
= msvcrt_get_thread_data()->exc_record
;
687 return (msvcrt_get_thread_data()->exc_record
== rec
);
691 /*********************************************************************
692 * __CxxQueryExceptionSize (MSVCRT.@)
694 unsigned int CDECL
__CxxQueryExceptionSize(void)
696 return sizeof(cxx_exception_type
);
700 /*******************************************************************
703 __ASM_GLOBAL_FUNC( MSVCRT__setjmp
,
704 "jmp " __ASM_NAME("__wine_setjmpex") );
706 /*******************************************************************
709 void __cdecl
MSVCRT_longjmp( _JUMP_BUFFER
*jmp
, int retval
)
711 EXCEPTION_RECORD rec
;
713 if (!retval
) retval
= 1;
716 rec
.ExceptionCode
= STATUS_LONGJUMP
;
717 rec
.ExceptionFlags
= 0;
718 rec
.ExceptionRecord
= NULL
;
719 rec
.ExceptionAddress
= NULL
;
720 rec
.NumberParameters
= 1;
721 rec
.ExceptionInformation
[0] = (DWORD_PTR
)jmp
;
722 RtlUnwind( (void *)jmp
->Frame
, (void *)jmp
->Rip
, &rec
, IntToPtr(retval
) );
724 __wine_longjmp( (__wine_jmp_buf
*)jmp
, retval
);
727 /*******************************************************************
728 * _local_unwind (MSVCRT.@)
730 void __cdecl
_local_unwind( void *frame
, void *target
)
732 RtlUnwind( frame
, target
, NULL
, 0 );
735 /*********************************************************************
736 * _fpieee_flt (MSVCRT.@)
738 int __cdecl
_fpieee_flt(__msvcrt_ulong exception_code
, EXCEPTION_POINTERS
*ep
,
739 int (__cdecl
*handler
)(_FPIEEE_RECORD
*))
741 FIXME("(%lx %p %p) opcode: %#I64x\n", exception_code
, ep
, handler
,
742 *(ULONG64
*)ep
->ContextRecord
->Rip
);
743 return EXCEPTION_CONTINUE_SEARCH
;
746 #if _MSVCR_VER>=110 && _MSVCR_VER<=120
747 /*********************************************************************
748 * __crtCapturePreviousContext (MSVCR110.@)
750 void __cdecl
get_prev_context(CONTEXT
*ctx
, DWORD64 rip
)
752 ULONG64 frame
, image_base
;
753 RUNTIME_FUNCTION
*rf
;
756 TRACE("(%p)\n", ctx
);
758 rf
= RtlLookupFunctionEntry(ctx
->Rip
, &image_base
, NULL
);
760 FIXME("RtlLookupFunctionEntry failed\n");
764 RtlVirtualUnwind(UNW_FLAG_NHANDLER
, image_base
, ctx
->Rip
,
765 rf
, ctx
, &data
, &frame
, NULL
);
768 __ASM_GLOBAL_FUNC( __crtCapturePreviousContext
,
769 "movq %rcx,8(%rsp)\n\t"
770 "call " __ASM_NAME("RtlCaptureContext") "\n\t"
771 "movq 8(%rsp),%rcx\n\t" /* context */
772 "leaq 8(%rsp),%rax\n\t"
773 "movq %rax,0x98(%rcx)\n\t" /* context->Rsp */
774 "movq (%rsp),%rax\n\t"
775 "movq %rax,0xf8(%rcx)\n\t" /* context->Rip */
776 "jmp " __ASM_NAME("get_prev_context") )
779 #endif /* __x86_64__ */