diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index ac5f403131f..bf4a53e1b6e 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -531,6 +531,20 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, void **buffer, } +/************************************************************************* + * RtlGetCallersAddress (NTDLL.@) + */ +void WINAPI RtlGetCallersAddress( void **caller, void **parent ) +{ + void *buffer[2]; + ULONG count = ARRAY_SIZE(buffer), skip = 2; /* skip our frame and the parent */ + + count = RtlWalkFrameChain( buffer, count + skip, skip << 8 ); + *caller = count > 0 ? buffer[0] : NULL; + *parent = count > 1 ? buffer[1] : NULL; +} + + /********************************************************************** * RtlGetEnabledExtendedFeatures (NTDLL.@) */ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 3d45b3d1e9a..d40bfd33a58 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -716,7 +716,7 @@ @ stub RtlGenerate8dot3Name @ stdcall RtlGetAce(ptr long ptr) @ stdcall RtlGetActiveActivationContext(ptr) -@ stub RtlGetCallersAddress +@ stdcall RtlGetCallersAddress(ptr ptr) @ stdcall RtlGetCompressionWorkSpaceSize(long ptr ptr) @ stdcall RtlGetControlSecurityDescriptor(ptr ptr ptr) @ stdcall RtlGetCurrentDirectory_U(long ptr) diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 3fa0c1801b4..d3c279ecab8 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -66,6 +66,7 @@ static void * (WINAPI *pRtlLocateLegacyContext)(CONTEXT_EX *context_ex, ULONG static void (WINAPI *pRtlSetExtendedFeaturesMask)(CONTEXT_EX *context_ex, ULONG64 feature_mask); static ULONG64 (WINAPI *pRtlGetExtendedFeaturesMask)(CONTEXT_EX *context_ex); static void * (WINAPI *pRtlPcToFileHeader)(PVOID pc, PVOID *address); +static void (WINAPI *pRtlGetCallersAddress)(void**,void**); static NTSTATUS (WINAPI *pNtRaiseException)(EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance); static NTSTATUS (WINAPI *pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*); static NTSTATUS (WINAPI *pNtTerminateProcess)(HANDLE handle, LONG exit_code); @@ -10784,6 +10785,18 @@ static void test_backtrace(void) ok( module == GetModuleHandleA(0), "wrong module %p %s / %p for %p\n", module, debugstr_w(name), GetModuleHandleA(0), buffer[0]); + if (pRtlGetCallersAddress) + { + void *caller, *parent; + + caller = parent = (void *)0xdeadbeef; + pRtlGetCallersAddress( &caller, &parent ); + ok( caller == (count > 1 ? buffer[1] : NULL) || broken(is_arm64ec), /* caller is entry thunk */ + "wrong caller %p / %p\n", caller, buffer[1] ); + ok( parent == (count > 2 ? buffer[2] : NULL), "wrong parent %p / %p\n", parent, buffer[2] ); + } + else win_skip( "RtlGetCallersAddress not supported\n" ); + if (count && !buffer[count - 1]) count--; /* win11 32-bit */ if (count <= 1) return; RtlPcToFileHeader( buffer[count - 1], &module ); @@ -10844,6 +10857,7 @@ START_TEST(exception) X(RtlSetExtendedFeaturesMask); X(RtlGetExtendedFeaturesMask); X(RtlPcToFileHeader); + X(RtlGetCallersAddress); X(RtlCopyContext); X(RtlCopyExtendedContext); X(KiUserApcDispatcher); diff --git a/include/rtlsupportapi.h b/include/rtlsupportapi.h index becb6179a56..a9dd5515501 100644 --- a/include/rtlsupportapi.h +++ b/include/rtlsupportapi.h @@ -24,6 +24,7 @@ NTSYSAPI void WINAPI RtlCaptureContext(CONTEXT*); NTSYSAPI void WINAPI RtlCaptureContext2(CONTEXT*); NTSYSAPI USHORT WINAPI RtlCaptureStackBackTrace(ULONG,ULONG,void**,ULONG*); +NTSYSAPI void WINAPI RtlGetCallersAddress(void**,void**); NTSYSAPI void WINAPI RtlRaiseException(EXCEPTION_RECORD*); NTSYSAPI void CDECL RtlRestoreContext(CONTEXT*,EXCEPTION_RECORD*); NTSYSAPI void WINAPI RtlUnwind(void*,void*,EXCEPTION_RECORD*,void*);