[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.
This commit is contained in:
George Bișoc 2021-05-02 20:45:57 +02:00
parent 66007dee2b
commit ae8ebe45d2
No known key found for this signature in database
GPG key ID: 688C4FBE25D7DEF6
2 changed files with 343 additions and 0 deletions

View file

@ -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_ */

View file

@ -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;
}
}