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
QuerySetProcessValidator(_In_ ALIGNMENT_PROBE_MODE ValidationMode,_In_ ULONG InfoClassIndex,_In_ PVOID InfoPointer,_In_ ULONG InfoLength,_In_ NTSTATUS ExpectedStatus)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
QuerySetThreadValidator(_In_ ALIGNMENT_PROBE_MODE ValidationMode,_In_ ULONG InfoClassIndex,_In_ PVOID InfoPointer,_In_ ULONG InfoLength,_In_ NTSTATUS ExpectedStatus)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