[NTDLL_APITEST] Implement alignment probing library code
authorGeorge Bișoc <george.bisoc@reactos.org>
Sun, 2 May 2021 18:45:57 +0000 (20:45 +0200)
committerGeorge Bișoc <george.bisoc@reactos.org>
Sun, 2 May 2021 18:45:57 +0000 (20:45 +0200)
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
modules/rostests/apitests/ntdll/probelib.c [new file with mode: 0644]

index 82d3e07..d476f1c 100644 (file)
 #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 (file)
index 0000000..e59b1f5
--- /dev/null
@@ -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@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;
+    }
+}