Commit ca598405 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Implement RtlVirtualUnwind2.

parent 9ac8d63e
......@@ -125,10 +125,9 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
dispatch->FunctionEntry = RtlLookupFunctionEntry( pc, (DWORD_PTR *)&dispatch->ImageBase,
dispatch->HistoryTable );
dispatch->LanguageHandler = RtlVirtualUnwind( type, dispatch->ImageBase, pc, dispatch->FunctionEntry,
context, &dispatch->HandlerData,
(ULONG_PTR *)&dispatch->EstablisherFrame, NULL );
if (!context->Pc)
if (RtlVirtualUnwind2( type, dispatch->ImageBase, pc, dispatch->FunctionEntry, context,
NULL, &dispatch->HandlerData, (ULONG_PTR *)&dispatch->EstablisherFrame,
NULL, NULL, NULL, &dispatch->LanguageHandler, 0 ))
{
WARN( "exception data not found for pc %p, lr %p\n", (void *)pc, (void *)context->Lr );
return STATUS_INVALID_DISPOSITION;
......
......@@ -155,10 +155,10 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
if (dispatch->ControlPcIsUnwound) pc -= 4;
dispatch->FunctionEntry = RtlLookupFunctionEntry( pc, &dispatch->ImageBase, dispatch->HistoryTable );
dispatch->LanguageHandler = RtlVirtualUnwind( type, dispatch->ImageBase, pc, dispatch->FunctionEntry,
context, &dispatch->HandlerData,
&dispatch->EstablisherFrame, NULL );
if (!context->Pc)
if (RtlVirtualUnwind2( type, dispatch->ImageBase, pc, dispatch->FunctionEntry, context,
NULL, &dispatch->HandlerData, &dispatch->EstablisherFrame,
NULL, NULL, NULL, &dispatch->LanguageHandler, 0 ))
{
WARN( "exception data not found for pc %p, lr %p\n", (void *)pc, (void *)context->Lr );
return STATUS_INVALID_DISPOSITION;
......
......@@ -119,11 +119,9 @@ static NTSTATUS virtual_unwind( ULONG type, DISPATCHER_CONTEXT *dispatch, CONTEX
}
else WARN( "exception data not found for pc %p\n", (void *)context->Rip );
dispatch->LanguageHandler = RtlVirtualUnwind( type, dispatch->ImageBase, context->Rip,
dispatch->FunctionEntry, context,
&dispatch->HandlerData, &dispatch->EstablisherFrame,
NULL );
return STATUS_SUCCESS;
return RtlVirtualUnwind2( type, dispatch->ImageBase, context->Rip, dispatch->FunctionEntry,
context, NULL, &dispatch->HandlerData, &dispatch->EstablisherFrame,
NULL, NULL, NULL, &dispatch->LanguageHandler, 0 );
}
......
......@@ -46,6 +46,7 @@ static BOOLEAN (CDECL *pRtlDeleteFunctionTable)(RUNTIME_FUNCTION*);
static DWORD (WINAPI *pRtlAddGrowableFunctionTable)(void**, RUNTIME_FUNCTION*, DWORD, DWORD, ULONG_PTR, ULONG_PTR);
static void (WINAPI *pRtlGrowFunctionTable)(void*, DWORD);
static void (WINAPI *pRtlDeleteGrowableFunctionTable)(void*);
static NTSTATUS (WINAPI *pRtlVirtualUnwind2)(ULONG,ULONG_PTR,ULONG_PTR,RUNTIME_FUNCTION*,CONTEXT*,BOOLEAN*,void**,ULONG_PTR*,KNONVOLATILE_CONTEXT_POINTERS*,ULONG_PTR*,ULONG_PTR*,PEXCEPTION_ROUTINE*,ULONG);
static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE,PVOID*,SIZE_T*,ULONG,ULONG,MEM_EXTENDED_PARAMETER*,ULONG);
#ifdef __arm__
......@@ -125,8 +126,10 @@ static void call_virtual_unwind_arm( int testnum, const struct unwind_test_arm *
{
static const int code_offset = 1024;
static const int unwind_offset = 2048;
void *handler, *data;
void *data;
CONTEXT context;
NTSTATUS status;
PEXCEPTION_ROUTINE handler;
RUNTIME_FUNCTION runtime_func;
KNONVOLATILE_CONTEXT_POINTERS ctx_ptr;
UINT i, j, k;
......@@ -163,11 +166,44 @@ static void call_virtual_unwind_arm( int testnum, const struct unwind_test_arm *
trace( "%u/%u: pc=%p (%02x) fp=%p sp=%p\n", testnum, i,
(void *)orig_pc, *(UINT *)orig_pc, (void *)orig_fp, (void *)context.Sp );
if (test->results[i].handler == -2) orig_pc = context.Lr;
if (pRtlVirtualUnwind2)
{
CONTEXT new_context = context;
handler = (void *)0xdeadbeef;
data = (void *)0xdeadbeef;
frame = 0xdeadbeef;
status = pRtlVirtualUnwind2( UNW_FLAG_EHANDLER, (ULONG)code_mem, orig_pc,
test->unwind_info ? &runtime_func : NULL, &new_context,
NULL, &data, &frame, &ctx_ptr, NULL, NULL, &handler, 0 );
if (test->results[i].handler > 0)
{
ok( !status, "RtlVirtualUnwind2 failed %lx\n", status );
ok( (char *)handler == (char *)code_mem + 0x200,
"%u/%u: wrong handler %p/%p\n", testnum, i, handler, (char *)code_mem + 0x200 );
if (handler) ok( *(DWORD *)data == 0x08070605,
"%u/%u: wrong handler data %lx\n", testnum, i, *(DWORD *)data );
}
else if (test->results[i].handler < -1)
{
ok( status == STATUS_BAD_FUNCTION_TABLE, "RtlVirtualUnwind2 failed %lx\n", status );
ok( handler == (void *)0xdeadbeef, "handler set to %p\n", handler );
ok( data == (void *)0xdeadbeef, "handler data set to %p\n", data );
}
else
{
ok( !status, "RtlVirtualUnwind2 failed %lx\n", status );
ok( handler == NULL, "handler %p instead of NULL\n", handler );
ok( data == NULL, "handler data set to %p\n", data );
}
}
data = (void *)0xdeadbeef;
frame = 0xdeadbeef;
if (test->results[i].handler == -2) orig_pc = context.Lr;
handler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, (ULONG)code_mem, orig_pc,
test->unwind_info ? (RUNTIME_FUNCTION *)&runtime_func : NULL,
test->unwind_info ? &runtime_func : NULL,
&context, &data, &frame, &ctx_ptr );
if (test->results[i].handler > 0)
{
......@@ -1558,15 +1594,17 @@ static void call_virtual_unwind_arm64( void *code_mem, int testnum, const struct
{
static const int code_offset = 1024;
static const int unwind_offset = 2048;
void *handler, *data;
void *data;
#ifdef __x86_64__
ARM64EC_NT_CONTEXT context;
ARM64EC_NT_CONTEXT context, new_context;
#else
ARM64_NT_CONTEXT context;
ARM64_NT_CONTEXT context, new_context;
#endif
PEXCEPTION_ROUTINE handler;
ARM64_RUNTIME_FUNCTION runtime_func;
KNONVOLATILE_CONTEXT_POINTERS ctx_ptr;
UINT i, j, k;
NTSTATUS status;
ULONG64 fake_stack[256];
ULONG64 frame, orig_pc, orig_fp, unset_reg, sp_offset = 0, regval, *regptr;
static const UINT nb_regs = ARRAY_SIZE(test->results[i].regs);
......@@ -1604,9 +1642,42 @@ static void call_virtual_unwind_arm64( void *code_mem, int testnum, const struct
trace( "pc=%p (%02x) fp=%p sp=%p\n", (void *)orig_pc, *(UINT *)orig_pc, (void *)orig_fp, (void *)context.Sp );
if (test->results[i].handler == -2) orig_pc = context.Lr;
if (pRtlVirtualUnwind2)
{
new_context = context;
handler = (void *)0xdeadbeef;
data = (void *)0xdeadbeef;
frame = 0xdeadbeef;
status = pRtlVirtualUnwind2( UNW_FLAG_EHANDLER, (ULONG_PTR)code_mem, orig_pc,
test->unwind_info ? (RUNTIME_FUNCTION *)&runtime_func : NULL,
(CONTEXT *)&new_context, NULL, &data,
&frame, &ctx_ptr, NULL, NULL, &handler, 0 );
if (test->results[i].handler > 0)
{
ok( !status, "RtlVirtualUnwind2 failed %lx\n", status );
ok( (char *)handler == (char *)code_mem + 0x200,
"wrong handler %p/%p\n", handler, (char *)code_mem + 0x200 );
if (handler) ok( *(DWORD *)data == 0x08070605,
"wrong handler data %lx\n", *(DWORD *)data );
}
else if (test->results[i].handler < -1)
{
ok( status == STATUS_BAD_FUNCTION_TABLE, "RtlVirtualUnwind2 failed %lx\n", status );
ok( handler == (void *)0xdeadbeef, "handler set to %p\n", handler );
ok( data == (void *)0xdeadbeef, "handler data set to %p\n", data );
}
else
{
ok( !status, "RtlVirtualUnwind2 failed %lx\n", status );
ok( handler == NULL, "handler %p instead of NULL\n", handler );
ok( data == NULL, "handler data set to %p\n", data );
}
}
data = (void *)0xdeadbeef;
frame = 0xdeadbeef;
if (test->results[i].handler == -2) orig_pc = context.Lr;
handler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, (ULONG64)code_mem, orig_pc,
test->unwind_info ? (RUNTIME_FUNCTION *)&runtime_func : NULL,
(CONTEXT *)&context, &data, &frame, &ctx_ptr );
......@@ -2625,8 +2696,10 @@ static void call_virtual_unwind_x86( int testnum, const struct unwind_test_x86 *
{
static const int code_offset = 1024;
static const int unwind_offset = 2048;
void *handler, *data;
void *data;
NTSTATUS status;
CONTEXT context;
PEXCEPTION_ROUTINE handler;
RUNTIME_FUNCTION runtime_func;
KNONVOLATILE_CONTEXT_POINTERS ctx_ptr;
UINT i, j, k, broken_k;
......@@ -2661,8 +2734,31 @@ static void call_virtual_unwind_x86( int testnum, const struct unwind_test_x86 *
trace( "%u/%u: rip=%p (%02x) rbp=%p rsp=%p\n", testnum, i,
(void *)orig_rip, *(BYTE *)orig_rip, (void *)orig_rbp, (void *)context.Rsp );
data = (void *)0xdeadbeef;
if (!test->unwind_info) fake_stack[0] = 0x1234;
expected_handler = test->results[i].handler ? (char *)code_mem + 0x200 : NULL;
broken_handler = test->broken_results && test->broken_results[i].handler ? (char *)code_mem + 0x200 : NULL;
if (pRtlVirtualUnwind2)
{
CONTEXT new_context = context;
handler = (void *)0xdeadbeef;
data = (void *)0xdeadbeef;
status = pRtlVirtualUnwind2( UNW_FLAG_EHANDLER, (ULONG_PTR)code_mem, orig_rip,
test->unwind_info ? &runtime_func : NULL, &new_context,
NULL, &data, &frame, &ctx_ptr, NULL, NULL, &handler, 0 );
ok( !status, "RtlVirtualUnwind2 failed %lx\n", status );
ok( handler == expected_handler || broken( test->broken_results && handler == broken_handler ),
"%u/%u: wrong handler %p/%p\n", testnum, i, handler, expected_handler );
if (handler)
ok( *(DWORD *)data == 0x08070605, "%u/%u: wrong handler data %lx\n", testnum, i, *(DWORD *)data );
else
ok( data == (test->unwind_info ? (void *)0xdeadbeef : NULL),
"%u/%u: handler data set to %p\n", testnum, i, data );
}
data = (void *)0xdeadbeef;
handler = RtlVirtualUnwind( UNW_FLAG_EHANDLER, (ULONG64)code_mem, orig_rip,
test->unwind_info ? &runtime_func : NULL,
&context, &data, &frame, &ctx_ptr );
......@@ -3329,6 +3425,7 @@ START_TEST(unwind)
X(RtlInstallFunctionTableCallback);
X(RtlLookupFunctionEntry);
X(RtlLookupFunctionTable);
X(RtlVirtualUnwind2);
#undef X
#ifdef __arm__
......
......@@ -766,42 +766,59 @@ static ARM64_RUNTIME_FUNCTION *find_function_info_arm64( ULONG_PTR pc, ULONG_PTR
#ifdef __arm64ec__
#define RtlVirtualUnwind RtlVirtualUnwind_arm64
#define RtlVirtualUnwind2 RtlVirtualUnwind2_arm64
#define RtlLookupFunctionEntry RtlLookupFunctionEntry_arm64
#endif
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
* RtlVirtualUnwind2 (NTDLL.@)
*/
PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PTR pc,
ARM64_RUNTIME_FUNCTION *func, ARM64_NT_CONTEXT *context,
PVOID *handler_data, ULONG_PTR *frame_ret,
KNONVOLATILE_CONTEXT_POINTERS_ARM64 *ctx_ptr )
NTSTATUS WINAPI RtlVirtualUnwind2( ULONG type, ULONG_PTR base, ULONG_PTR pc,
ARM64_RUNTIME_FUNCTION *func, ARM64_NT_CONTEXT *context,
BOOLEAN *mach_frame_unwound, void **handler_data,
ULONG_PTR *frame_ret, KNONVOLATILE_CONTEXT_POINTERS_ARM64 *ctx_ptr,
ULONG_PTR *limit_low, ULONG_PTR *limit_high,
PEXCEPTION_ROUTINE *handler_ret, ULONG flags )
{
PEXCEPTION_ROUTINE handler;
TRACE( "type %lx base %I64x pc %I64x rva %I64x sp %I64x\n", type, base, pc, pc - base, context->Sp );
if (limit_low || limit_high) FIXME( "limits not supported\n" );
TRACE( "type %lx pc %I64x sp %I64x\n", type, pc, context->Sp );
if (!func && pc == context->Lr) /* invalid leaf function */
{
context->Pc = 0;
return NULL;
}
if (!func && pc == context->Lr) return STATUS_BAD_FUNCTION_TABLE; /* invalid leaf function */
*handler_data = NULL;
context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL;
if (!func) /* leaf function */
handler = NULL;
*handler_ret = NULL;
else if (func->Flag)
handler = unwind_packed_data( base, pc, func, context, ctx_ptr );
*handler_ret = unwind_packed_data( base, pc, func, context, ctx_ptr );
else
handler = unwind_full_data( base, pc, func, context, handler_data, ctx_ptr );
*handler_ret = unwind_full_data( base, pc, func, context, handler_data, ctx_ptr );
if (context->ContextFlags & CONTEXT_UNWOUND_TO_CALL) context->Pc = context->Lr;
TRACE( "ret: pc=%I64x lr=%I64x sp=%I64x handler=%p\n", context->Pc, context->Lr, context->Sp, handler );
TRACE( "ret: pc=%I64x lr=%I64x sp=%I64x handler=%p\n", context->Pc, context->Lr, context->Sp, *handler_ret );
*frame_ret = context->Sp;
return handler;
return STATUS_SUCCESS;
}
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
*/
PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PTR pc,
ARM64_RUNTIME_FUNCTION *func, ARM64_NT_CONTEXT *context,
PVOID *handler_data, ULONG_PTR *frame_ret,
KNONVOLATILE_CONTEXT_POINTERS_ARM64 *ctx_ptr )
{
PEXCEPTION_ROUTINE handler;
if (!RtlVirtualUnwind2( type, base, pc, func, context, NULL, handler_data,
frame_ret, ctx_ptr, NULL, NULL, &handler, 0 ))
return handler;
context->Pc = 0;
return NULL;
}
......@@ -850,6 +867,7 @@ BOOLEAN CDECL RtlAddFunctionTable( RUNTIME_FUNCTION *table, DWORD count, ULONG_P
}
#else
#undef RtlVirtualUnwind
#undef RtlVirtualUnwind2
#undef RtlLookupFunctionEntry
#endif
......@@ -1367,39 +1385,60 @@ static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
return NULL;
}
/***********************************************************************
* RtlVirtualUnwind (NTDLL.@)
/**********************************************************************
* RtlVirtualUnwind2 (NTDLL.@)
*/
PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PTR pc,
RUNTIME_FUNCTION *func, CONTEXT *context,
PVOID *handler_data, ULONG_PTR *frame_ret,
KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr )
NTSTATUS WINAPI RtlVirtualUnwind2( ULONG type, ULONG_PTR base, ULONG_PTR pc,
RUNTIME_FUNCTION *func, CONTEXT *context,
BOOLEAN *mach_frame_unwound, void **handler_data,
ULONG_PTR *frame_ret, KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr,
ULONG_PTR *limit_low, ULONG_PTR *limit_high,
PEXCEPTION_ROUTINE *handler_ret, ULONG flags )
{
PEXCEPTION_ROUTINE handler;
TRACE( "type %lx pc %Ix sp %lx\n", type, pc, context->Sp );
TRACE( "type %lx base %Ix pc %Ix rva %Ix sp %lx\n", type, base, pc, pc - base, context->Sp );
if (limit_low || limit_high) FIXME( "limits not supported\n" );
context->Pc = 0;
if (!func && pc == context->Lr) return NULL; /* invalid leaf function */
if (!func && pc == context->Lr) return STATUS_BAD_FUNCTION_TABLE; /* invalid leaf function */
*handler_data = NULL;
if (!func) /* leaf function */
handler = NULL;
*handler_ret = NULL;
else if (func->Flag)
handler = unwind_packed_data( base, pc, func, context, ctx_ptr );
*handler_ret = unwind_packed_data( base, pc, func, context, ctx_ptr );
else
handler = unwind_full_data( base, pc, func, context, handler_data, ctx_ptr );
*handler_ret = unwind_full_data( base, pc, func, context, handler_data, ctx_ptr );
TRACE( "ret: pc=%lx lr=%lx sp=%lx handler=%p\n", context->Pc, context->Lr, context->Sp, handler );
TRACE( "ret: pc=%lx lr=%lx sp=%lx handler=%p\n", context->Pc, context->Lr, context->Sp, *handler_ret );
if (!context->Pc)
{
context->Pc = context->Lr;
context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL;
}
*frame_ret = context->Sp;
return handler;
return STATUS_SUCCESS;
}
/***********************************************************************
* RtlVirtualUnwind (NTDLL.@)
*/
PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG_PTR base, ULONG_PTR pc,
RUNTIME_FUNCTION *func, CONTEXT *context,
PVOID *handler_data, ULONG_PTR *frame_ret,
KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr )
{
PEXCEPTION_ROUTINE handler;
if (!RtlVirtualUnwind2( type, base, pc, func, context, NULL, handler_data,
frame_ret, ctx_ptr, NULL, NULL, &handler, 0 ))
return handler;
context->Pc = 0;
return NULL;
}
......@@ -1808,12 +1847,14 @@ static RUNTIME_FUNCTION *find_function_info( ULONG_PTR pc, ULONG_PTR base,
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
* RtlVirtualUnwind2 (NTDLL.@)
*/
PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
RUNTIME_FUNCTION *function, CONTEXT *context,
PVOID *data, ULONG64 *frame_ret,
KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr )
NTSTATUS WINAPI RtlVirtualUnwind2( ULONG type, ULONG_PTR base, ULONG_PTR pc,
RUNTIME_FUNCTION *function, CONTEXT *context,
BOOLEAN *mach_frame_unwound, void **data,
ULONG_PTR *frame_ret, KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr,
ULONG_PTR *limit_low, ULONG_PTR *limit_high,
PEXCEPTION_ROUTINE *handler_ret, ULONG flags )
{
union handler_data *handler_data;
ULONG64 frame, off;
......@@ -1826,18 +1867,20 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
{
DWORD flags = context->ContextFlags & ~CONTEXT_UNWOUND_TO_CALL;
ARM64_NT_CONTEXT arm_context;
PEXCEPTION_ROUTINE ret;
NTSTATUS status;
context_x64_to_arm( &arm_context, (ARM64EC_NT_CONTEXT *)context );
ret = RtlVirtualUnwind_arm64( type, base, pc, (ARM64_RUNTIME_FUNCTION *)function,
&arm_context, data, frame_ret, NULL );
status = RtlVirtualUnwind2_arm64( type, base, pc, (ARM64_RUNTIME_FUNCTION *)function,
&arm_context, NULL, data, frame_ret, NULL,
limit_low, limit_high, handler_ret, flags );
context_arm_to_x64( (ARM64EC_NT_CONTEXT *)context, &arm_context );
context->ContextFlags = flags | (arm_context.ContextFlags & CONTEXT_UNWOUND_TO_CALL);
return ret;
return status;
}
#endif
TRACE( "type %lx rip %I64x rsp %I64x\n", type, pc, context->Rsp );
TRACE( "type %lx base %I64x rip %I64x rva %I64x rsp %I64x\n", type, base, pc, pc - base, context->Rsp );
if (limit_low || limit_high) FIXME( "limits not supported\n" );
frame = *frame_ret = context->Rsp;
......@@ -1846,7 +1889,8 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
context->Rip = *(ULONG64 *)context->Rsp;
context->Rsp += sizeof(ULONG64);
*data = NULL;
return NULL;
*handler_ret = NULL;
return STATUS_SUCCESS;
}
if (TRACE_ON(unwind)) dump_unwind_info( base, function );
......@@ -1859,7 +1903,7 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
if (info->version != 1 && info->version != 2)
{
FIXME( "unknown unwind info version %u at %p\n", info->version, info );
return NULL;
return STATUS_BAD_FUNCTION_TABLE;
}
if (info->frame_reg)
......@@ -1880,7 +1924,8 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
TRACE("inside epilog.\n");
interpret_epilog( (BYTE *)pc, context, ctx_ptr );
*frame_ret = frame;
return NULL;
*handler_ret = NULL;
return STATUS_SUCCESS;
}
}
......@@ -1959,11 +2004,33 @@ PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc
context->Rsp += sizeof(ULONG64);
}
if (!(info->flags & type)) return NULL; /* no matching handler */
if (prolog_offset != ~0) return NULL; /* inside prolog */
*handler_ret = NULL;
if (!(info->flags & type)) return STATUS_SUCCESS; /* no matching handler */
if (prolog_offset != ~0) return STATUS_SUCCESS; /* inside prolog */
*handler_ret = (PEXCEPTION_ROUTINE)((char *)base + handler_data->handler);
*data = &handler_data->handler + 1;
return (PEXCEPTION_ROUTINE)((char *)base + handler_data->handler);
return STATUS_SUCCESS;
}
/**********************************************************************
* RtlVirtualUnwind (NTDLL.@)
*/
PEXCEPTION_ROUTINE WINAPI RtlVirtualUnwind( ULONG type, ULONG64 base, ULONG64 pc,
RUNTIME_FUNCTION *func, CONTEXT *context,
PVOID *handler_data, ULONG64 *frame_ret,
KNONVOLATILE_CONTEXT_POINTERS *ctx_ptr )
{
PEXCEPTION_ROUTINE handler;
if (!RtlVirtualUnwind2( type, base, pc, func, context, NULL, handler_data,
frame_ret, ctx_ptr, NULL, NULL, &handler, 0 ))
return handler;
context->Rip = 0;
return NULL;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment