https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f1e5bc3d7421ae47a623f…
commit f1e5bc3d7421ae47a623ffcf7ecb07174a168f60
Author: Mark Jansen <mark.jansen(a)reactos.org>
AuthorDate: Sat Apr 11 22:30:47 2020 +0200
Commit: Mark Jansen <mark.jansen(a)reactos.org>
CommitDate: Fri Apr 17 17:47:09 2020 +0200
[LOADCONFIG_APITEST] Add apitest using the load config section
For now, the only test is related to a user trace stack db.
The entire test application is disabled for gcc,
since it is unable to generate this load config info.
The stacktrace test is disabled until it is implemented.
---
modules/rostests/apitests/CMakeLists.txt | 5 +
.../rostests/apitests/loadconfig/CMakeLists.txt | 12 ++
modules/rostests/apitests/loadconfig/common.c | 70 +++++++++
modules/rostests/apitests/loadconfig/loadconfig.h | 14 ++
modules/rostests/apitests/loadconfig/stacktrace.c | 166 +++++++++++++++++++++
modules/rostests/apitests/loadconfig/testlist.c | 12 ++
6 files changed, 279 insertions(+)
diff --git a/modules/rostests/apitests/CMakeLists.txt
b/modules/rostests/apitests/CMakeLists.txt
index 752755a453f..abb0fb8209b 100644
--- a/modules/rostests/apitests/CMakeLists.txt
+++ b/modules/rostests/apitests/CMakeLists.txt
@@ -22,6 +22,11 @@ add_subdirectory(gdi32)
add_subdirectory(gditools)
add_subdirectory(iphlpapi)
add_subdirectory(kernel32)
+if(NOT GCC)
+ # gcc / binutils are unable to add an IMAGE_LOAD_CONFIG_DIRECTORY
+ # So maybe we should resuscitate sdk/tools/pefixup.c
+ add_subdirectory(loadconfig)
+endif()
add_subdirectory(localspl)
add_subdirectory(mountmgr)
add_subdirectory(msgina)
diff --git a/modules/rostests/apitests/loadconfig/CMakeLists.txt
b/modules/rostests/apitests/loadconfig/CMakeLists.txt
new file mode 100644
index 00000000000..a09e73e90b1
--- /dev/null
+++ b/modules/rostests/apitests/loadconfig/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+list(APPEND SOURCE
+ common.c
+ stacktrace.c
+ loadconfig.h)
+
+add_executable(loadconfig_apitest ${SOURCE} testlist.c)
+target_link_libraries(loadconfig_apitest wine ${PSEH_LIB})
+set_module_type(loadconfig_apitest win32cui)
+add_importlibs(loadconfig_apitest msvcrt kernel32 ntdll)
+add_pch(loadconfig_apitest loadconfig.h SOURCE)
+add_rostests_file(TARGET loadconfig_apitest)
diff --git a/modules/rostests/apitests/loadconfig/common.c
b/modules/rostests/apitests/loadconfig/common.c
new file mode 100644
index 00000000000..ab1a26a6250
--- /dev/null
+++ b/modules/rostests/apitests/loadconfig/common.c
@@ -0,0 +1,70 @@
+/*
+ * PROJECT: ReactOS API tests
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: LOAD_CONFIG validation / registration
+ * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen(a)reactos.org)
+ */
+
+#include "loadconfig.h"
+
+
+// Tell the linker we want a LOAD_CONFIG
+const IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used =
+{
+ sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
+ 0, // TimeDateStamp
+ 0, // MajorVersion
+ 0, // MinorVersion
+ 0, // GlobalFlagsClear
+ FLG_USER_STACK_TRACE_DB, // GlobalFlagsSet
+ 0, // CriticalSectionDefaultTimeout
+ 0, // DeCommitFreeBlockThreshold
+ 0, // DeCommitTotalFreeThreshold
+ 0, // LockPrefixTable
+ 0, // MaximumAllocationSize
+ 0, // VirtualMemoryThreshold
+ 0, // ProcessHeapFlags
+ 0, // ProcessAffinityMask
+ 0, // CSDVersion
+ 0, // Reserved1
+ 0, // EditList
+ 0, // SecurityCookie
+};
+
+
+BOOL check_loadconfig()
+{
+ BOOL Result;
+ PPEB Peb = NtCurrentPeb();
+ ULONG ConfigSize = 0;
+ ULONG MinimalSize;
+ PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfig;
+
+ // Validate the required flag for the 'stacktrace' test
+ ok(Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB, "NtGlobalFlag:
0x%lx\n", Peb->NtGlobalFlag);
+ Result = (Peb->NtGlobalFlag & FLG_USER_STACK_TRACE_DB) != 0;
+
+ // Now validate our LOAD_CONFIG entry
+ LoadConfig =
(PIMAGE_LOAD_CONFIG_DIRECTORY)RtlImageDirectoryEntryToData(Peb->ImageBaseAddress,
+ TRUE,
+
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG,
+
&ConfigSize);
+
+ MinimalSize = FIELD_OFFSET(IMAGE_LOAD_CONFIG_DIRECTORY, SecurityCookie) +
sizeof(LoadConfig->SecurityCookie);
+ if (!LoadConfig || ConfigSize < MinimalSize)
+ {
+ ok(0, "Invalid IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG: %p, %lu (%lu)\n",
+ LoadConfig, ConfigSize, MinimalSize);
+ }
+ else
+ {
+ ok(LoadConfig->GlobalFlagsSet & FLG_USER_STACK_TRACE_DB,
+ "Invalid GlobalFlagsSet: %lx\n", LoadConfig->GlobalFlagsSet);
+ ok(!(LoadConfig->GlobalFlagsClear & FLG_USER_STACK_TRACE_DB),
+ "Invalid GlobalFlagsClear: %lx\n",
LoadConfig->GlobalFlagsClear);
+ ok(LoadConfig->Size == sizeof(IMAGE_LOAD_CONFIG_DIRECTORY),
+ "Unexpected size difference: %lu vs %u\n", LoadConfig->Size,
sizeof(IMAGE_LOAD_CONFIG_DIRECTORY));
+ }
+
+ return Result;
+}
diff --git a/modules/rostests/apitests/loadconfig/loadconfig.h
b/modules/rostests/apitests/loadconfig/loadconfig.h
new file mode 100644
index 00000000000..ce2d2910230
--- /dev/null
+++ b/modules/rostests/apitests/loadconfig/loadconfig.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+
+#include <apitest.h>
+#include <apitest_guard.h>
+#include <ndk/ntndk.h>
+#include <strsafe.h>
+
+
+/* common.c */
+BOOL check_loadconfig();
diff --git a/modules/rostests/apitests/loadconfig/stacktrace.c
b/modules/rostests/apitests/loadconfig/stacktrace.c
new file mode 100644
index 00000000000..f233563f61b
--- /dev/null
+++ b/modules/rostests/apitests/loadconfig/stacktrace.c
@@ -0,0 +1,166 @@
+/*
+ * PROJECT: ReactOS API tests
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Test for RtlQueryProcessBackTraceInformation & RtlLogStackBackTrace
+ * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen(a)reactos.org)
+ */
+
+#include "loadconfig.h"
+
+
+// This test serves 2 purposes:
+// 1. It tests RtlQueryProcessBackTraceInformation & RtlLogStackBackTrace
+// 2. It tests the correct activation of IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG (see also
common.c)
+
+NTSTATUS NTAPI RtlQueryProcessBackTraceInformation(IN OUT PRTL_DEBUG_INFORMATION
Buffer);
+
+
+// Seems that this struct is wrong in our sdk?
+typedef struct _RTL_PROCESS_BACKTRACE_INFORMATION_32
+{
+ PVOID SymbolicBackTrace;
+ ULONG TraceCount;
+ USHORT Index;
+ USHORT Depth;
+ PVOID BackTrace[32];
+} RTL_PROCESS_BACKTRACE_INFORMATION_32, *PRTL_PROCESS_BACKTRACE_INFORMATION_32;
+
+
+static PVOID g_Call_Address;
+static PVOID g_PreviousReturnAddress;
+
+__declspec(noinline)
+PVOID GetFunctionAddress()
+{
+ return _ReturnAddress();
+}
+
+__declspec(noinline)
+USHORT Call_Backtrace_2()
+{
+ USHORT Index;
+ Index = RtlLogStackBackTrace();
+ ok(Index != 0, "RtlLogStackBackTrace failed\n");
+ return Index;
+}
+
+
+__declspec(noinline)
+USHORT Call_Backtrace_1()
+{
+ USHORT Index;
+ // It seems that the function calling RtlLogStackBackTrace is skipped,
+ // so we wrap it in a deeper nested function to be able to check it
+ g_Call_Address = GetFunctionAddress();
+ g_PreviousReturnAddress = _ReturnAddress();
+ Index = Call_Backtrace_2();
+ return Index;
+}
+
+static void Check_Stacktrace(PVOID* BackTrace, USHORT Depth)
+{
+ ok(Depth > 2, "Unexpected Depth: %lu\n", (ULONG)Depth);
+ if (Depth > 2)
+ {
+ ULONG_PTR EndAddress = ((ULONG_PTR)g_Call_Address + 0x20);
+ ok(BackTrace[0] >= g_Call_Address && (ULONG_PTR)BackTrace[0] <
EndAddress,
+ "Unexpected return: %p, expected between %p and %p\n", BackTrace[0],
g_Call_Address, (PVOID)EndAddress);
+ ok(BackTrace[1] == g_PreviousReturnAddress, "Unexpected return: %p,
expected: %p\n",
+ BackTrace[1], g_PreviousReturnAddress);
+ }
+}
+
+static void test_QueryBacktrace(PRTL_DEBUG_INFORMATION Buffer1, PRTL_DEBUG_INFORMATION
Buffer2)
+{
+ NTSTATUS Status;
+ USHORT StackTrace;
+ PRTL_PROCESS_BACKTRACES Backtraces;
+ ULONG OldNumberOfBackTraces, n;
+ PRTL_PROCESS_BACKTRACE_INFORMATION_32 FirstBacktrace;
+ int found = 0;
+
+ Status = RtlQueryProcessBackTraceInformation(Buffer1);
+ ok_hex(Status, STATUS_SUCCESS);
+ if (Status != STATUS_SUCCESS)
+ return;
+
+ Backtraces = Buffer1->BackTraces;
+ ok(Backtraces != NULL, "No BackTraces\n");
+ if (!Backtraces)
+ return;
+
+ OldNumberOfBackTraces = Backtraces->NumberOfBackTraces;
+ // Capture a stacktrace
+ StackTrace = Call_Backtrace_1();
+
+ // Show that the old debugbuffer is not changed
+ ok(OldNumberOfBackTraces == Backtraces->NumberOfBackTraces, "Debug buffer
changed! (%lu => %lu)\n",
+ OldNumberOfBackTraces, Backtraces->NumberOfBackTraces);
+
+ // Ask for a new snapshot
+ Status = RtlQueryProcessBackTraceInformation(Buffer2);
+ ok_hex(Status, STATUS_SUCCESS);
+ if (Status != STATUS_SUCCESS)
+ return;
+
+ Backtraces = Buffer2->BackTraces;
+ ok(Backtraces != NULL, "No BackTraces\n");
+ if (!Backtraces)
+ return;
+
+ ok(OldNumberOfBackTraces+1 == Backtraces->NumberOfBackTraces, "Stacktrace not
added! (%lu => %lu)\n",
+ OldNumberOfBackTraces, Backtraces->NumberOfBackTraces);
+
+ FirstBacktrace =
(PRTL_PROCESS_BACKTRACE_INFORMATION_32)&Backtraces->BackTraces[0];
+ trace("NumberOfBackTraces=%lu\n", Backtraces->NumberOfBackTraces);
+ for (n = 0; n < Backtraces->NumberOfBackTraces; ++n)
+ {
+ PRTL_PROCESS_BACKTRACE_INFORMATION_32 Info = FirstBacktrace + n;
+#if 0
+ USHORT j;
+
+ trace("BackTraces[%02lu]->SymbolicBackTrace = %p\n", n,
Info->SymbolicBackTrace);
+ trace("BackTraces[%02lu]->TraceCount = %lu\n", n,
Info->TraceCount);
+ trace("BackTraces[%02lu]->Index = %lu\n", n,
(ULONG)Info->Index);
+ trace("BackTraces[%02lu]->Depth = %lu\n", n,
(ULONG)Info->Depth);
+ for (j = 0; j < Info->Depth; ++j)
+ {
+ trace("BackTraces[%02lu]->BackTrace[%02u] = %p\n", n, j,
Info->BackTrace[j]);
+ }
+ trace("\n");
+#endif
+ if (Info->Index == StackTrace)
+ {
+ found = 1;
+ Check_Stacktrace(Info->BackTrace, Info->Depth);
+ }
+ }
+ ok(found, "Stacktrace not found :(\n");
+}
+
+
+START_TEST(stacktrace)
+{
+ PRTL_DEBUG_INFORMATION Buffer1, Buffer2;
+
+ if (!check_loadconfig())
+ return;
+
+ skip("QueryBacktrace not implemented yet\n");
+ return;
+
+ Buffer1 = RtlCreateQueryDebugBuffer(0, FALSE);
+ ok(Buffer1 != NULL, "Failed!\n");
+ if (Buffer1)
+ {
+ Buffer2 = RtlCreateQueryDebugBuffer(0, FALSE);
+ ok(Buffer2 != NULL, "Failed!\n");
+ if (Buffer2)
+ {
+ test_QueryBacktrace(Buffer1, Buffer2);
+ RtlDestroyQueryDebugBuffer(Buffer2);
+ }
+
+ RtlDestroyQueryDebugBuffer(Buffer1);
+ }
+}
diff --git a/modules/rostests/apitests/loadconfig/testlist.c
b/modules/rostests/apitests/loadconfig/testlist.c
new file mode 100644
index 00000000000..7f585152fa6
--- /dev/null
+++ b/modules/rostests/apitests/loadconfig/testlist.c
@@ -0,0 +1,12 @@
+
+#define STANDALONE
+#include <apitest.h>
+
+extern void func_stacktrace(void);
+
+const struct test winetest_testlist[] =
+{
+ { "stacktrace", func_stacktrace },
+
+ { 0, 0 }
+};