1 /* 2 * PROJECT: ReactOS API Tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Small library with probing utilities for thread/process classes information 5 * COPYRIGHT: Copyright 2020 George Bișoc <george.bisoc@reactos.org> 6 */ 7 8 #include "precomp.h" 9 #include <internal/ps_i.h> 10 11 VOID 12 QuerySetProcessValidator( 13 _In_ ALIGNMENT_PROBE_MODE ValidationMode, 14 _In_ ULONG InfoClassIndex, 15 _In_ PVOID InfoPointer, 16 _In_ ULONG InfoLength, 17 _In_ NTSTATUS ExpectedStatus) 18 { 19 NTSTATUS Status, SpecialStatus = STATUS_SUCCESS; 20 21 /* Before doing anything, check if we want query or set validation */ 22 switch (ValidationMode) 23 { 24 case QUERY: 25 { 26 switch (InfoClassIndex) 27 { 28 case ProcessWorkingSetWatch: 29 { 30 SpecialStatus = STATUS_UNSUCCESSFUL; 31 break; 32 } 33 34 case ProcessHandleTracing: 35 { 36 SpecialStatus = STATUS_INVALID_PARAMETER; 37 break; 38 } 39 40 /* 41 * This class returns an arbitrary size pointed by InformationLength 42 * which equates to the image filename of the process. Such status 43 * is returned in an invalid address query (STATUS_ACCESS_VIOLATION) 44 * where the function expects STATUS_INFO_LENGTH_MISMATCH instead. 45 */ 46 case ProcessImageFileName: 47 { 48 SpecialStatus = STATUS_INFO_LENGTH_MISMATCH; 49 break; 50 } 51 52 /* This one works different from the others */ 53 case ProcessUserModeIOPL: 54 { 55 if (ExpectedStatus == STATUS_INFO_LENGTH_MISMATCH) 56 { 57 SpecialStatus = STATUS_ACCESS_VIOLATION; 58 } 59 else 60 { 61 SpecialStatus = STATUS_INVALID_INFO_CLASS; 62 } 63 break; 64 } 65 66 /* These classes don't belong in the query group */ 67 case ProcessBasePriority: 68 case ProcessRaisePriority: 69 case ProcessExceptionPort: 70 case ProcessAccessToken: 71 case ProcessLdtSize: 72 case ProcessIoPortHandlers: 73 case ProcessEnableAlignmentFaultFixup: 74 case ProcessAffinityMask: 75 case ProcessForegroundInformation: 76 { 77 SpecialStatus = STATUS_INVALID_INFO_CLASS; 78 break; 79 } 80 81 /* These classes don't exist in Server 2003 */ 82 case ProcessIoPriority: 83 case ProcessTlsInformation: 84 case ProcessCycleTime: 85 case ProcessPagePriority: 86 case ProcessInstrumentationCallback: 87 case ProcessThreadStackAllocation: 88 case ProcessWorkingSetWatchEx: 89 case ProcessImageFileNameWin32: 90 case ProcessImageFileMapping: 91 case ProcessAffinityUpdateMode: 92 case ProcessMemoryAllocationMode: 93 { 94 SpecialStatus = STATUS_INVALID_INFO_CLASS; 95 break; 96 } 97 } 98 99 /* Query the information */ 100 Status = NtQueryInformationProcess(NtCurrentProcess(), 101 InfoClassIndex, 102 InfoPointer, 103 InfoLength, 104 NULL); 105 106 /* And probe the results we've got */ 107 ok(Status == ExpectedStatus || Status == SpecialStatus || Status == STATUS_DATATYPE_MISALIGNMENT, 108 "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); 109 break; 110 } 111 112 case SET: 113 { 114 switch (InfoClassIndex) 115 { 116 case ProcessIoPortHandlers: 117 { 118 SpecialStatus = STATUS_INVALID_PARAMETER; 119 break; 120 } 121 122 /* 123 * This class returns STATUS_SUCCESS when testing 124 * for STATUS_ACCESS_VIOLATION (setting an invalid address). 125 */ 126 case ProcessWorkingSetWatch: 127 { 128 SpecialStatus = STATUS_PORT_ALREADY_SET; 129 break; 130 } 131 132 /* This one works different from the others */ 133 case ProcessUserModeIOPL: 134 { 135 if (ExpectedStatus == STATUS_INFO_LENGTH_MISMATCH) 136 { 137 SpecialStatus = STATUS_ACCESS_VIOLATION; 138 } 139 else 140 { 141 SpecialStatus = STATUS_PRIVILEGE_NOT_HELD; 142 } 143 break; 144 } 145 146 /* These classes don't belong in the set group */ 147 case ProcessBasicInformation: 148 case ProcessIoCounters: 149 case ProcessVmCounters: 150 case ProcessTimes: 151 case ProcessDebugPort: 152 case ProcessPooledUsageAndLimits: 153 case ProcessHandleCount: 154 case ProcessWow64Information: 155 case ProcessImageFileName: 156 case ProcessLUIDDeviceMapsEnabled: 157 case ProcessDebugObjectHandle: 158 case ProcessCookie: 159 case ProcessImageInformation: 160 { 161 SpecialStatus = STATUS_INVALID_INFO_CLASS; 162 break; 163 } 164 165 /* These classes don't exist in Server 2003 */ 166 case ProcessIoPriority: 167 case ProcessTlsInformation: 168 case ProcessCycleTime: 169 case ProcessPagePriority: 170 case ProcessInstrumentationCallback: 171 case ProcessThreadStackAllocation: 172 case ProcessWorkingSetWatchEx: 173 case ProcessImageFileNameWin32: 174 case ProcessImageFileMapping: 175 case ProcessAffinityUpdateMode: 176 case ProcessMemoryAllocationMode: 177 { 178 SpecialStatus = STATUS_INVALID_INFO_CLASS; 179 break; 180 } 181 182 /* Alignment probing is not performed for these classes */ 183 case ProcessEnableAlignmentFaultFixup: 184 case ProcessPriorityClass: 185 case ProcessForegroundInformation: 186 { 187 SpecialStatus = STATUS_ACCESS_VIOLATION; 188 break; 189 } 190 } 191 192 /* Set the information */ 193 Status = NtSetInformationProcess(NtCurrentProcess(), 194 InfoClassIndex, 195 InfoPointer, 196 InfoLength); 197 198 /* And probe the results we've got */ 199 ok(Status == ExpectedStatus || Status == SpecialStatus || Status == STATUS_DATATYPE_MISALIGNMENT || Status == STATUS_SUCCESS, 200 "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); 201 break; 202 } 203 204 default: 205 break; 206 } 207 } 208 209 VOID 210 QuerySetThreadValidator( 211 _In_ ALIGNMENT_PROBE_MODE ValidationMode, 212 _In_ ULONG InfoClassIndex, 213 _In_ PVOID InfoPointer, 214 _In_ ULONG InfoLength, 215 _In_ NTSTATUS ExpectedStatus) 216 { 217 NTSTATUS Status, SpecialStatus = STATUS_SUCCESS; 218 219 /* Before doing anything, check if we want query or set validation */ 220 switch (ValidationMode) 221 { 222 case QUERY: 223 { 224 switch (InfoClassIndex) 225 { 226 /* These classes don't belong in the query group */ 227 case ThreadPriority: 228 case ThreadBasePriority: 229 case ThreadAffinityMask: 230 case ThreadImpersonationToken: 231 case ThreadEnableAlignmentFaultFixup: 232 case ThreadZeroTlsCell: 233 case ThreadIdealProcessor: 234 case ThreadSetTlsArrayAddress: 235 case ThreadHideFromDebugger: 236 case ThreadSwitchLegacyState: 237 { 238 SpecialStatus = STATUS_INVALID_INFO_CLASS; 239 break; 240 } 241 242 /* These classes don't exist in Server 2003 SP2 */ 243 case ThreadEventPair_Reusable: 244 case ThreadLastSystemCall: 245 case ThreadIoPriority: 246 case ThreadCycleTime: 247 case ThreadPagePriority: 248 case ThreadActualBasePriority: 249 case ThreadTebInformation: 250 case ThreadCSwitchMon: 251 { 252 SpecialStatus = STATUS_INVALID_INFO_CLASS; 253 break; 254 } 255 } 256 257 /* Query the information */ 258 Status = NtQueryInformationThread(NtCurrentThread(), 259 InfoClassIndex, 260 InfoPointer, 261 InfoLength, 262 NULL); 263 264 /* And probe the results we've got */ 265 ok(Status == ExpectedStatus || Status == SpecialStatus || Status == STATUS_DATATYPE_MISALIGNMENT, 266 "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); 267 break; 268 } 269 270 case SET: 271 { 272 switch (InfoClassIndex) 273 { 274 /* This class is not implemented in Windows Server 2003 SP2 */ 275 case ThreadSwitchLegacyState: 276 { 277 SpecialStatus = STATUS_NOT_IMPLEMENTED; 278 break; 279 } 280 281 /* 282 * This class doesn't take a strict type for size length. 283 * The function happily succeds on an information length 284 * mismatch scenario with STATUS_SUCCESS. 285 */ 286 case ThreadHideFromDebugger: 287 { 288 SpecialStatus = STATUS_INFO_LENGTH_MISMATCH; 289 break; 290 } 291 292 /* These classes don't belong in the set group */ 293 case ThreadBasicInformation: 294 case ThreadTimes: 295 case ThreadDescriptorTableEntry: 296 case ThreadPerformanceCount: 297 case ThreadAmILastThread: 298 case ThreadIsIoPending: 299 case ThreadIsTerminated: 300 { 301 SpecialStatus = STATUS_INVALID_INFO_CLASS; 302 break; 303 } 304 305 /* These classes don't exist in Server 2003 SP2 */ 306 case ThreadEventPair_Reusable: 307 case ThreadLastSystemCall: 308 case ThreadIoPriority: 309 case ThreadCycleTime: 310 case ThreadPagePriority: 311 case ThreadActualBasePriority: 312 case ThreadTebInformation: 313 case ThreadCSwitchMon: 314 { 315 SpecialStatus = STATUS_INVALID_INFO_CLASS; 316 break; 317 } 318 319 /* Alignment probing is not performed for this class */ 320 case ThreadEnableAlignmentFaultFixup: 321 { 322 SpecialStatus = STATUS_ACCESS_VIOLATION; 323 break; 324 } 325 } 326 327 /* Set the information */ 328 Status = NtSetInformationThread(NtCurrentThread(), 329 InfoClassIndex, 330 InfoPointer, 331 InfoLength); 332 333 /* And probe the results we've got */ 334 ok(Status == ExpectedStatus || Status == SpecialStatus || Status == STATUS_DATATYPE_MISALIGNMENT || Status == STATUS_SUCCESS, 335 "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); 336 } 337 338 default: 339 break; 340 } 341 } 342