Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/ntdll.spec | 2 +- dlls/ntdll/signal_arm.c | 11 +++++++ dlls/ntdll/signal_arm64.c | 11 +++++++ dlls/ntdll/signal_i386.c | 24 ++++++++++++++ dlls/ntdll/signal_x86_64.c | 24 ++++++++++++++ dlls/ntdll/tests/exception.c | 51 +++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- include/ddk/ntddk.h | 3 ++ include/winnt.h | 2 ++ 9 files changed, 128 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 13e65f65139..c54b2e205aa 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1073,7 +1073,7 @@ @ stdcall RtlWakeAddressSingle(ptr) @ stdcall RtlWakeAllConditionVariable(ptr) @ stdcall RtlWakeConditionVariable(ptr) -@ stub RtlWalkFrameChain +@ stdcall RtlWalkFrameChain(ptr long long) @ stdcall RtlWalkHeap(long ptr) @ stdcall RtlWow64EnableFsRedirection(long) @ stdcall RtlWow64EnableFsRedirectionEx(long ptr) diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index 0ef210a0331..1ab4aa032c0 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -308,6 +308,17 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, return 0; }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + + FIXME( "callers %p, count %u, flags %#x stub.\n", callers, count, flags ); + + return 0; +} + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 290639b676b..401db35d405 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -1481,6 +1481,17 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, return 0; }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + + FIXME( "callers %p, count %u, flags %#x stub.\n", callers, count, flags ); + + return 0; +} + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 0245aa602a1..9390ffa3df3 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -520,6 +520,30 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + CONTEXT context; + ULONG skip; + ULONG ret; + + TRACE( "callers %p, count %u, flags %#x.\n", callers, count, flags ); + + RtlCaptureContext( &context ); + + skip = (flags >> 8) & 0xff; + flags &= ~0xff00; + + if (flags) + FIXME( "flags %#x are not supported.\n", flags ); + + ret = capture_stack_back_trace( &context, skip, count, callers, NULL ); + return ret ? ret + skip : 0; +} + + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index dbf622392b7..e57b538d17c 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -1545,6 +1545,30 @@ USHORT WINAPI RtlCaptureStackBackTrace( ULONG skip, ULONG count, PVOID *buffer, }
+/********************************************************************** + * RtlWalkFrameChain (NTDLL.@) + */ +ULONG WINAPI RtlWalkFrameChain(void **callers, ULONG count, ULONG flags) +{ + CONTEXT context; + ULONG skip; + ULONG ret; + + TRACE( "callers %p, count %u, flags %#x.\n", callers, count, flags ); + + RtlCaptureContext( &context ); + + skip = (flags >> 8) & 0xff; + flags &= ~0xff00; + + if (flags) + FIXME( "flags %#x are not supported.\n", flags ); + + ret = capture_stack_back_trace( &context, skip, count, callers, NULL ); + return ret ? ret + skip : 0; +} + + /*********************************************************************** * signal_start_thread */ diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 6af68317732..63b1edeebc9 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -28,6 +28,7 @@ #include "winnt.h" #include "winreg.h" #include "winternl.h" +#include "ddk/ntddk.h" #include "ddk/wdm.h" #include "excpt.h" #include "wine/test.h" @@ -9113,6 +9114,55 @@ static void test_copy_context(void) } #endif
+static void test_walk_stack(void) +{ + ULONG frame_count, frame_count2; + void *addrs[256], *addrs2[256]; + void *start, *end; + unsigned int i; + + memset(addrs, 0xcc, sizeof(addrs)); + memset(addrs2, 0xcc, sizeof(addrs2)); + + frame_count = RtlCaptureStackBackTrace(0, ARRAY_SIZE(addrs), addrs, NULL); + frame_count2 = RtlWalkFrameChain(addrs2, ARRAY_SIZE(addrs2), 0); + + trace("frame_count %u.\n", frame_count); + + ok(frame_count > 1, "Got zero frame_count.\n"); + ok(frame_count == frame_count2, "Got unexpected frame_count %u, frame_count2 %u.\n", frame_count, frame_count2); + + start = test_walk_stack; + end = (BYTE *)start + 0x1000; + todo_wine_if(sizeof(void *) == 4) + ok(addrs[0] >= start && addrs[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", + start, end, addrs[0]); + todo_wine_if(sizeof(void *) == 4) + ok(addrs2[0] >= start && addrs2[0] < end, "Address is not inside test function, start %p, end %p, addr %p.\n", + start, end, addrs2[0]); + + for (i = 1; i < frame_count; ++i) + { + ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]); + } + todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n"); + + memset(addrs, 0xcc, sizeof(addrs)); + memset(addrs2, 0xcc, sizeof(addrs2)); + + frame_count = RtlCaptureStackBackTrace(1, ARRAY_SIZE(addrs), addrs, NULL); + ok(frame_count == frame_count2 - 1, "Got unexpected frame_count %u.\n", frame_count); + + frame_count2 = RtlWalkFrameChain(addrs2, frame_count2, 1 << RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT) - 1; + ok(frame_count == frame_count2, "Got unexpected frame_count %u, frame_count2 %u.\n", frame_count, frame_count2); + + for (i = 0; i < frame_count; ++i) + { + ok(addrs[i] == addrs2[i], "i %u, addresses do not match, %p vs %p.\n", i, addrs[i], addrs2[i]); + } + todo_wine ok(!!addrs[frame_count - 1], "Expected non-NULL last address.\n"); +} + START_TEST(exception) { HMODULE hntdll = GetModuleHandleA("ntdll.dll"); @@ -9339,5 +9389,6 @@ START_TEST(exception) test_suspend_thread(); test_suspend_process(); test_unload_trace(); + test_walk_stack(); VirtualFree(code_mem, 0, MEM_RELEASE); } diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 0208e2f633f..b94e58ccb26 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1300,7 +1300,7 @@ @ stdcall RtlVerifyVersionInfo(ptr long int64) @ stdcall -arch=arm64,x86_64 RtlVirtualUnwind(long long long ptr ptr ptr ptr ptr) @ stub RtlVolumeDeviceToDosName -@ stub RtlWalkFrameChain +@ stdcall RtlWalkFrameChain(ptr long long) @ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long) @ stub RtlZeroHeap @ stdcall RtlZeroMemory(ptr long) diff --git a/include/ddk/ntddk.h b/include/ddk/ntddk.h index 41ad3d721bd..ce558139aa6 100644 --- a/include/ddk/ntddk.h +++ b/include/ddk/ntddk.h @@ -245,6 +245,8 @@ typedef EXPAND_STACK_CALLOUT *PEXPAND_STACK_CALLOUT; typedef GUID UUID; #endif
+#define RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT 8 + NTSTATUS WINAPI ExUuidCreate(UUID*); NTSTATUS WINAPI IoQueryDeviceDescription(PINTERFACE_TYPE,PULONG,PCONFIGURATION_TYPE,PULONG, PCONFIGURATION_TYPE,PULONG,PIO_QUERY_DEVICE_ROUTINE,PVOID); @@ -267,5 +269,6 @@ NTSTATUS WINAPI PsSetCreateThreadNotifyRoutine(PCREATE_THREAD_NOTIFY_ROUTINE); NTSTATUS WINAPI PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE); void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE,PRTL_AVL_COMPARE_ROUTINE,PRTL_AVL_ALLOCATE_ROUTINE, PRTL_AVL_FREE_ROUTINE,void *); void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE,void *,ULONG,BOOL*); +ULONG WINAPI RtlWalkFrameChain(void **,ULONG,ULONG);
#endif diff --git a/include/winnt.h b/include/winnt.h index ef731e29c52..eb1bd165720 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -1840,6 +1840,8 @@ NTSYSAPI PVOID WINAPI RtlVirtualUnwind(DWORD,ULONG_PTR,ULONG_PTR,RUNTIME_FUNCT
#endif
+NTSYSAPI USHORT WINAPI RtlCaptureStackBackTrace(ULONG,ULONG,void **,ULONG *); + /* * Product types */