msvcrt: Clean up registered C++ objects in handler.
Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ac9db1138c
commit
57266eec5e
|
@ -108,6 +108,12 @@ typedef struct __cxx_function_descr
|
||||||
UINT flags;
|
UINT flags;
|
||||||
} cxx_function_descr;
|
} cxx_function_descr;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
cxx_frame_info frame_info;
|
||||||
|
BOOL rethrow;
|
||||||
|
} cxx_catch_ctx;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ULONG64 dest_frame;
|
ULONG64 dest_frame;
|
||||||
|
@ -318,17 +324,27 @@ static void cxx_local_unwind(ULONG64 frame, DISPATCHER_CONTEXT *dispatch,
|
||||||
unwind_help[0] = last_level;
|
unwind_help[0] = last_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LONG CALLBACK cxx_rethrow_filter(PEXCEPTION_POINTERS eptrs)
|
static LONG CALLBACK cxx_rethrow_filter(PEXCEPTION_POINTERS eptrs, void *c)
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD *rec = eptrs->ExceptionRecord;
|
EXCEPTION_RECORD *rec = eptrs->ExceptionRecord;
|
||||||
|
thread_data_t *data = msvcrt_get_thread_data();
|
||||||
|
cxx_catch_ctx *ctx = c;
|
||||||
|
|
||||||
if (rec->ExceptionCode != CXX_EXCEPTION)
|
if (rec->ExceptionCode != CXX_EXCEPTION)
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
if (!rec->ExceptionInformation[1] && !rec->ExceptionInformation[2])
|
if (!rec->ExceptionInformation[1] && !rec->ExceptionInformation[2])
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
if (rec->ExceptionInformation[1] == data->exc_record->ExceptionInformation[1])
|
||||||
|
ctx->rethrow = TRUE;
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CALLBACK cxx_catch_cleanup(BOOL normal, void *c)
|
||||||
|
{
|
||||||
|
cxx_catch_ctx *ctx = c;
|
||||||
|
__CxxUnregisterExceptionObject(&ctx->frame_info, ctx->rethrow);
|
||||||
|
}
|
||||||
|
|
||||||
static void* WINAPI call_catch_block(EXCEPTION_RECORD *rec)
|
static void* WINAPI call_catch_block(EXCEPTION_RECORD *rec)
|
||||||
{
|
{
|
||||||
ULONG64 frame = rec->ExceptionInformation[1];
|
ULONG64 frame = rec->ExceptionInformation[1];
|
||||||
|
@ -336,25 +352,31 @@ static void* WINAPI call_catch_block(EXCEPTION_RECORD *rec)
|
||||||
EXCEPTION_RECORD *prev_rec = (void*)rec->ExceptionInformation[4];
|
EXCEPTION_RECORD *prev_rec = (void*)rec->ExceptionInformation[4];
|
||||||
void* (__cdecl *handler)(ULONG64 unk, ULONG64 rbp) = (void*)rec->ExceptionInformation[5];
|
void* (__cdecl *handler)(ULONG64 unk, ULONG64 rbp) = (void*)rec->ExceptionInformation[5];
|
||||||
int *unwind_help = rva_to_ptr(descr->unwind_help, frame);
|
int *unwind_help = rva_to_ptr(descr->unwind_help, frame);
|
||||||
cxx_frame_info frame_info;
|
cxx_catch_ctx ctx;
|
||||||
void *ret_addr = NULL;
|
void *ret_addr = NULL;
|
||||||
|
|
||||||
TRACE("calling handler %p\n", handler);
|
TRACE("calling handler %p\n", handler);
|
||||||
|
|
||||||
__CxxRegisterExceptionObject(&prev_rec, &frame_info);
|
ctx.rethrow = FALSE;
|
||||||
|
__CxxRegisterExceptionObject(&prev_rec, &ctx.frame_info);
|
||||||
__TRY
|
__TRY
|
||||||
{
|
{
|
||||||
ret_addr = handler(0, frame);
|
__TRY
|
||||||
}
|
{
|
||||||
__EXCEPT(cxx_rethrow_filter)
|
ret_addr = handler(0, frame);
|
||||||
{
|
}
|
||||||
TRACE("detect rethrow: exception code: %x\n", prev_rec->ExceptionCode);
|
__EXCEPT_CTX(cxx_rethrow_filter, &ctx)
|
||||||
|
{
|
||||||
|
TRACE("detect rethrow: exception code: %x\n", prev_rec->ExceptionCode);
|
||||||
|
ctx.rethrow = TRUE;
|
||||||
|
|
||||||
RaiseException(prev_rec->ExceptionCode, prev_rec->ExceptionFlags,
|
RaiseException(prev_rec->ExceptionCode, prev_rec->ExceptionFlags,
|
||||||
prev_rec->NumberParameters, prev_rec->ExceptionInformation);
|
prev_rec->NumberParameters, prev_rec->ExceptionInformation);
|
||||||
|
}
|
||||||
|
__ENDTRY
|
||||||
}
|
}
|
||||||
__ENDTRY
|
__FINALLY_CTX(cxx_catch_cleanup, &ctx)
|
||||||
__CxxUnregisterExceptionObject(&frame_info, FALSE);
|
|
||||||
unwind_help[0] = -2;
|
unwind_help[0] = -2;
|
||||||
unwind_help[1] = -1;
|
unwind_help[1] = -1;
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
|
@ -534,10 +556,6 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame,
|
||||||
{
|
{
|
||||||
if (cxx_is_consolidate(rec))
|
if (cxx_is_consolidate(rec))
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD *new_rec = (void*)rec->ExceptionInformation[4];
|
|
||||||
thread_data_t *data = msvcrt_get_thread_data();
|
|
||||||
frame_info *cur;
|
|
||||||
|
|
||||||
if (rec->ExceptionFlags & EH_TARGET_UNWIND)
|
if (rec->ExceptionFlags & EH_TARGET_UNWIND)
|
||||||
{
|
{
|
||||||
const cxx_function_descr *orig_descr = (void*)rec->ExceptionInformation[2];
|
const cxx_function_descr *orig_descr = (void*)rec->ExceptionInformation[2];
|
||||||
|
@ -548,18 +566,6 @@ static DWORD cxx_frame_handler(EXCEPTION_RECORD *rec, ULONG64 frame,
|
||||||
}
|
}
|
||||||
else if(frame == orig_frame)
|
else if(frame == orig_frame)
|
||||||
cxx_local_unwind(frame, dispatch, descr, -1);
|
cxx_local_unwind(frame, dispatch, descr, -1);
|
||||||
|
|
||||||
/* FIXME: we should only unregister frames registered by call_catch_block here */
|
|
||||||
for (cur = data->frame_info_head; cur; cur = cur->next)
|
|
||||||
{
|
|
||||||
if ((ULONG64)cur <= frame)
|
|
||||||
{
|
|
||||||
__CxxUnregisterExceptionObject((cxx_frame_info*)cur,
|
|
||||||
new_rec->ExceptionCode == CXX_EXCEPTION &&
|
|
||||||
data->exc_record->ExceptionCode == CXX_EXCEPTION &&
|
|
||||||
new_rec->ExceptionInformation[1] == data->exc_record->ExceptionInformation[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ExceptionContinueSearch;
|
return ExceptionContinueSearch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue