https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ae8ebe45d20b933a5890a…
commit ae8ebe45d20b933a5890afa65e3e8d7e5c2f8a54
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sun May 2 20:45:57 2021 +0200
Commit: George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Sun May 2 20:45:57 2021 +0200
[NTDLL_APITEST] Implement alignment probing library code
The probing library code only probes data types for threads/processes information
classes in Process Structure subsystem for now.
---
modules/rostests/apitests/ntdll/precomp.h | 23 +++
modules/rostests/apitests/ntdll/probelib.c | 320 +++++++++++++++++++++++++++++
2 files changed, 343 insertions(+)
diff --git a/modules/rostests/apitests/ntdll/precomp.h
b/modules/rostests/apitests/ntdll/precomp.h
index 82d3e0733b0..d476f1cc958 100644
--- a/modules/rostests/apitests/ntdll/precomp.h
+++ b/modules/rostests/apitests/ntdll/precomp.h
@@ -12,4 +12,27 @@
#include <ndk/ntndk.h>
#include <strsafe.h>
+/* probelib.c */
+typedef enum _ALIGNMENT_PROBE_MODE
+{
+ QUERY,
+ SET
+} ALIGNMENT_PROBE_MODE;
+
+VOID
+QuerySetProcessValidator(
+ _In_ ALIGNMENT_PROBE_MODE ValidationMode,
+ _In_ ULONG InfoClassIndex,
+ _In_ PVOID InfoPointer,
+ _In_ ULONG InfoLength,
+ _In_ NTSTATUS ExpectedStatus);
+
+VOID
+QuerySetThreadValidator(
+ _In_ ALIGNMENT_PROBE_MODE ValidationMode,
+ _In_ ULONG InfoClassIndex,
+ _In_ PVOID InfoPointer,
+ _In_ ULONG InfoLength,
+ _In_ NTSTATUS ExpectedStatus);
+
#endif /* _NTDLL_APITEST_PRECOMP_H_ */
diff --git a/modules/rostests/apitests/ntdll/probelib.c
b/modules/rostests/apitests/ntdll/probelib.c
new file mode 100644
index 00000000000..e59b1f5284f
--- /dev/null
+++ b/modules/rostests/apitests/ntdll/probelib.c
@@ -0,0 +1,320 @@
+/*
+ * PROJECT: ReactOS API Tests
+ * LICENSE: GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE: Small library with probing utilities for thread/process classes
information
+ * COPYRIGHT: Copyright 2020 George Bișoc <george.bisoc(a)reactos.org>
+ */
+
+#include "precomp.h"
+#include <internal/ps_i.h>
+
+VOID
+QuerySetProcessValidator(
+ _In_ ALIGNMENT_PROBE_MODE ValidationMode,
+ _In_ ULONG InfoClassIndex,
+ _In_ PVOID InfoPointer,
+ _In_ ULONG InfoLength,
+ _In_ NTSTATUS ExpectedStatus)
+{
+ NTSTATUS Status, SpecialStatus = STATUS_SUCCESS;
+
+ /* Before doing anything, check if we want query or set validation */
+ switch (ValidationMode)
+ {
+ case QUERY:
+ {
+ switch (InfoClassIndex)
+ {
+ case ProcessWorkingSetWatch:
+ {
+ SpecialStatus = STATUS_UNSUCCESSFUL;
+ break;
+ }
+
+ case ProcessHandleTracing:
+ {
+ SpecialStatus = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /*
+ * This class returns an arbitrary size pointed by InformationLength
+ * which equates to the image filename of the process. Such status
+ * is returned in an invalid address query (STATUS_ACCESS_VIOLATION)
+ * where the function expects STATUS_INFO_LENGTH_MISMATCH instead.
+ */
+ case ProcessImageFileName:
+ {
+ SpecialStatus = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* These classes don't belong in the query group */
+ case ProcessBasePriority:
+ case ProcessRaisePriority:
+ case ProcessExceptionPort:
+ case ProcessAccessToken:
+ case ProcessLdtSize:
+ case ProcessIoPortHandlers:
+ case ProcessUserModeIOPL:
+ case ProcessEnableAlignmentFaultFixup:
+ case ProcessAffinityMask:
+ case ProcessForegroundInformation:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ /* These classes don't exist in Server 2003 */
+ case ProcessIoPriority:
+ case ProcessTlsInformation:
+ case ProcessCycleTime:
+ case ProcessPagePriority:
+ case ProcessInstrumentationCallback:
+ case ProcessThreadStackAllocation:
+ case ProcessWorkingSetWatchEx:
+ case ProcessImageFileNameWin32:
+ case ProcessImageFileMapping:
+ case ProcessAffinityUpdateMode:
+ case ProcessMemoryAllocationMode:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+ }
+
+ /* Query the information */
+ Status = NtQueryInformationProcess(NtCurrentProcess(),
+ InfoClassIndex,
+ InfoPointer,
+ InfoLength,
+ NULL);
+
+ /* And probe the results we've got */
+ ok(Status == ExpectedStatus || Status == SpecialStatus || Status ==
STATUS_DATATYPE_MISALIGNMENT,
+ "0x%lx or special status (0x%lx) expected but got 0x%lx for class
information %lu in query information process operation!\n", ExpectedStatus,
SpecialStatus, Status, InfoClassIndex);
+ break;
+ }
+
+ case SET:
+ {
+ switch (InfoClassIndex)
+ {
+ case ProcessIoPortHandlers:
+ {
+ SpecialStatus = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /*
+ * This class returns STATUS_SUCCESS when testing
+ * for STATUS_ACCESS_VIOLATION (setting an invalid address).
+ */
+ case ProcessWorkingSetWatch:
+ {
+ SpecialStatus = STATUS_PORT_ALREADY_SET;
+ break;
+ }
+
+ case ProcessUserModeIOPL:
+ {
+ SpecialStatus = STATUS_PRIVILEGE_NOT_HELD;
+ break;
+ }
+
+ /* These classes don't belong in the set group */
+ case ProcessBasicInformation:
+ case ProcessIoCounters:
+ case ProcessVmCounters:
+ case ProcessTimes:
+ case ProcessDebugPort:
+ case ProcessPooledUsageAndLimits:
+ case ProcessHandleCount:
+ case ProcessWow64Information:
+ case ProcessImageFileName:
+ case ProcessLUIDDeviceMapsEnabled:
+ case ProcessDebugObjectHandle:
+ case ProcessCookie:
+ case ProcessImageInformation:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ /* These classes don't exist in Server 2003 */
+ case ProcessIoPriority:
+ case ProcessTlsInformation:
+ case ProcessCycleTime:
+ case ProcessPagePriority:
+ case ProcessInstrumentationCallback:
+ case ProcessThreadStackAllocation:
+ case ProcessWorkingSetWatchEx:
+ case ProcessImageFileNameWin32:
+ case ProcessImageFileMapping:
+ case ProcessAffinityUpdateMode:
+ case ProcessMemoryAllocationMode:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ /* Alignment probing is not performed for these classes */
+ case ProcessEnableAlignmentFaultFixup:
+ case ProcessPriorityClass:
+ case ProcessForegroundInformation:
+ {
+ SpecialStatus = STATUS_ACCESS_VIOLATION;
+ break;
+ }
+ }
+
+ /* Set the information */
+ Status = NtSetInformationProcess(NtCurrentProcess(),
+ InfoClassIndex,
+ InfoPointer,
+ InfoLength);
+
+ /* And probe the results we've got */
+ ok(Status == ExpectedStatus || Status == SpecialStatus || Status ==
STATUS_DATATYPE_MISALIGNMENT || Status == STATUS_SUCCESS,
+ "0x%lx or special status (0x%lx) expected but got 0x%lx for class
information %lu in set information process operation!\n", ExpectedStatus,
SpecialStatus, Status, InfoClassIndex);
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+VOID
+QuerySetThreadValidator(
+ _In_ ALIGNMENT_PROBE_MODE ValidationMode,
+ _In_ ULONG InfoClassIndex,
+ _In_ PVOID InfoPointer,
+ _In_ ULONG InfoLength,
+ _In_ NTSTATUS ExpectedStatus)
+{
+ NTSTATUS Status, SpecialStatus = STATUS_SUCCESS;
+
+ /* Before doing anything, check if we want query or set validation */
+ switch (ValidationMode)
+ {
+ case QUERY:
+ {
+ switch (InfoClassIndex)
+ {
+ /* These classes don't belong in the query group */
+ case ThreadPriority:
+ case ThreadBasePriority:
+ case ThreadAffinityMask:
+ case ThreadImpersonationToken:
+ case ThreadEnableAlignmentFaultFixup:
+ case ThreadZeroTlsCell:
+ case ThreadIdealProcessor:
+ case ThreadSetTlsArrayAddress:
+ case ThreadHideFromDebugger:
+ case ThreadSwitchLegacyState:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ /* These classes don't exist in Server 2003 SP2 */
+ case ThreadEventPair_Reusable:
+ case ThreadLastSystemCall:
+ case ThreadIoPriority:
+ case ThreadCycleTime:
+ case ThreadPagePriority:
+ case ThreadActualBasePriority:
+ case ThreadTebInformation:
+ case ThreadCSwitchMon:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+ }
+
+ /* Query the information */
+ Status = NtQueryInformationThread(NtCurrentThread(),
+ InfoClassIndex,
+ InfoPointer,
+ InfoLength,
+ NULL);
+
+ /* And probe the results we've got */
+ ok(Status == ExpectedStatus || Status == SpecialStatus || Status ==
STATUS_DATATYPE_MISALIGNMENT,
+ "0x%lx or special status (0x%lx) expected but got 0x%lx for class
information %lu in query information thread operation!\n", ExpectedStatus,
SpecialStatus, Status, InfoClassIndex);
+ break;
+ }
+
+ case SET:
+ {
+ switch (InfoClassIndex)
+ {
+ /* This class is not implemented in Windows Server 2003 SP2 */
+ case ThreadSwitchLegacyState:
+ {
+ SpecialStatus = STATUS_NOT_IMPLEMENTED;
+ break;
+ }
+
+ /*
+ * This class doesn't take a strict type for size length.
+ * The function happily succeds on an information length
+ * mismatch scenario with STATUS_SUCCESS.
+ */
+ case ThreadHideFromDebugger:
+ {
+ SpecialStatus = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ /* These classes don't belong in the set group */
+ case ThreadBasicInformation:
+ case ThreadTimes:
+ case ThreadDescriptorTableEntry:
+ case ThreadPerformanceCount:
+ case ThreadAmILastThread:
+ case ThreadIsIoPending:
+ case ThreadIsTerminated:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ /* These classes don't exist in Server 2003 SP2 */
+ case ThreadEventPair_Reusable:
+ case ThreadLastSystemCall:
+ case ThreadIoPriority:
+ case ThreadCycleTime:
+ case ThreadPagePriority:
+ case ThreadActualBasePriority:
+ case ThreadTebInformation:
+ case ThreadCSwitchMon:
+ {
+ SpecialStatus = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+
+ /* Alignment probing is not performed for this class */
+ case ThreadEnableAlignmentFaultFixup:
+ {
+ SpecialStatus = STATUS_ACCESS_VIOLATION;
+ break;
+ }
+ }
+
+ /* Set the information */
+ Status = NtSetInformationThread(NtCurrentThread(),
+ InfoClassIndex,
+ InfoPointer,
+ InfoLength);
+
+ /* And probe the results we've got */
+ ok(Status == ExpectedStatus || Status == SpecialStatus || Status ==
STATUS_DATATYPE_MISALIGNMENT || Status == STATUS_SUCCESS,
+ "0x%lx or special status (0x%lx) expected but got 0x%lx for class
information %lu in set information thread operation!\n", ExpectedStatus,
SpecialStatus, Status, InfoClassIndex);
+ }
+
+ default:
+ break;
+ }
+}