https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ae8ebe45d20b933a5890afa65e3e8d7e5c2f8a54
commit ae8ebe45d20b933a5890afa65e3e8d7e5c2f8a54 Author: George Bișoc <george.bi...@reactos.org> AuthorDate: Sun May 2 20:45:57 2021 +0200 Commit: George Bișoc <george.bi...@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.bi...@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; + } +}