1 /*
2  * PROJECT:         ReactOS API tests
3  * LICENSE:         GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:         Tests for the NtSetInformationProcess API
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 static
12 void
Test_ProcBasePriorityClass(void)13 Test_ProcBasePriorityClass(void)
14 {
15     NTSTATUS Status;
16 
17     /*
18      * Assign a priority of HIGH_PRIORITY (see pstypes.h).
19      * The function will fail with a status of STATUS_PRIVILEGE_NOT_HELD
20      * as the process who executed the caller doesn't have the requested
21      * privileges to perform the operation.
22     */
23     KPRIORITY BasePriority = HIGH_PRIORITY;
24 
25     /* Everything is NULL */
26     Status = NtSetInformationProcess(NULL,
27                                      ProcessBasePriority,
28                                      NULL,
29                                      0);
30     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
31 
32     /* Set the base priority to an invalid process handle */
33     Status = NtSetInformationProcess(NULL,
34                                      ProcessBasePriority,
35                                      &BasePriority,
36                                      sizeof(KPRIORITY));
37     ok_hex(Status, STATUS_INVALID_HANDLE);
38 
39     /* Don't input anything to the caller but the length information is valid */
40     Status = NtSetInformationProcess(NtCurrentProcess(),
41                                      ProcessBasePriority,
42                                      NULL,
43                                      sizeof(KPRIORITY));
44     ok_hex(Status, STATUS_ACCESS_VIOLATION);
45 
46     /* Give the base priority input to the caller but length is invalid */
47     Status = NtSetInformationProcess(NtCurrentProcess(),
48                                      ProcessBasePriority,
49                                      &BasePriority,
50                                      0);
51     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
52 
53     /* The input buffer is misaligned and length information invalid */
54     Status = NtSetInformationProcess(NtCurrentProcess(),
55                                      ProcessBasePriority,
56                                      (PVOID)1,
57                                      0);
58     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
59 
60     /* The input buffer is misaligned */
61     Status = NtSetInformationProcess(NtCurrentProcess(),
62                                      ProcessBasePriority,
63                                      (PVOID)1,
64                                      sizeof(KPRIORITY));
65     ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
66 
67     /* The input buffer is misaligned (try with an alignment of 2) */
68     Status = NtSetInformationProcess(NtCurrentProcess(),
69                                      ProcessBasePriority,
70                                      (PVOID)2,
71                                      sizeof(KPRIORITY));
72     ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
73 
74     /* Set the base priority but we have lack privileges to do so */
75     Status = NtSetInformationProcess(NtCurrentProcess(),
76                                      ProcessBasePriority,
77                                      &BasePriority,
78                                      sizeof(KPRIORITY));
79     ok_hex(Status, STATUS_PRIVILEGE_NOT_HELD);
80 
81     /*
82      * Assign a random priority value this time and
83      * set the base priority to the current process.
84     */
85     BasePriority = 8;
86     Status = NtSetInformationProcess(NtCurrentProcess(),
87                                      ProcessBasePriority,
88                                      &BasePriority,
89                                      sizeof(KPRIORITY));
90     ok_hex(Status, STATUS_SUCCESS);
91 }
92 
93 static
94 void
Test_ProcRaisePriorityClass(void)95 Test_ProcRaisePriorityClass(void)
96 {
97     NTSTATUS Status;
98 
99     /* Raise the priority as much as possible */
100     ULONG RaisePriority = MAXIMUM_PRIORITY;
101 
102     /* Everything is NULL */
103     Status = NtSetInformationProcess(NULL,
104                                      ProcessRaisePriority,
105                                      NULL,
106                                      0);
107     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
108 
109     /* A invalid handle to process is given */
110     Status = NtSetInformationProcess(NULL,
111                                      ProcessRaisePriority,
112                                      &RaisePriority,
113                                      sizeof(ULONG));
114     ok_hex(Status, STATUS_INVALID_HANDLE);
115 
116     /* The input buffer is misaligned and length information invalid */
117     Status = NtSetInformationProcess(NtCurrentProcess(),
118                                      ProcessRaisePriority,
119                                      (PVOID)1,
120                                      0);
121     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
122 
123     /* A NULL buffer has been accessed */
124     Status = NtSetInformationProcess(NtCurrentProcess(),
125                                      ProcessRaisePriority,
126                                      NULL,
127                                      sizeof(ULONG));
128     ok_hex(Status, STATUS_ACCESS_VIOLATION);
129 
130     /* The input buffer is misaligned */
131     Status = NtSetInformationProcess(NtCurrentProcess(),
132                                      ProcessRaisePriority,
133                                      (PVOID)1,
134                                      sizeof(ULONG));
135     ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
136 
137     /* The input buffer is misaligned -- try with an alignment size of 2 */
138     Status = NtSetInformationProcess(NtCurrentProcess(),
139                                      ProcessRaisePriority,
140                                      (PVOID)2,
141                                      sizeof(ULONG));
142     ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
143 
144     /* Raise the priority of the given current process */
145     Status = NtSetInformationProcess(NtCurrentProcess(),
146                                      ProcessRaisePriority,
147                                      &RaisePriority,
148                                      sizeof(ULONG));
149     ok_hex(Status, STATUS_SUCCESS);
150 }
151 
152 static
153 void
Test_ProcForegroundBackgroundClass(void)154 Test_ProcForegroundBackgroundClass(void)
155 {
156     NTSTATUS Status;
157     PPROCESS_FOREGROUND_BACKGROUND ProcForeground;
158 
159     ProcForeground = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PROCESS_FOREGROUND_BACKGROUND));
160     if (ProcForeground == NULL)
161     {
162         skip("Failed to allocate memory block from heap for PROCESS_FOREGROUND_BACKGROUND!\n");
163         return;
164     }
165 
166     /* As a test, set the foreground of the retrieved current process to FALSE */
167     ProcForeground->Foreground = FALSE;
168 
169     /* Set everything NULL for the caller */
170     Status = NtSetInformationProcess(NULL,
171                                      ProcessForegroundInformation,
172                                      NULL,
173                                      0);
174     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
175 
176     /* Give an invalid process handle (but the input buffer and length are correct) */
177     Status = NtSetInformationProcess(NULL,
178                                      ProcessForegroundInformation,
179                                      ProcForeground,
180                                      sizeof(PROCESS_FOREGROUND_BACKGROUND));
181     ok_hex(Status, STATUS_INVALID_HANDLE);
182 
183     /* Give a buffer data to the argument input as NULL */
184     Status = NtSetInformationProcess(NtCurrentProcess(),
185                                      ProcessForegroundInformation,
186                                      NULL,
187                                      sizeof(PROCESS_FOREGROUND_BACKGROUND));
188     ok_hex(Status, STATUS_ACCESS_VIOLATION);
189 
190     /* Set the information process foreground with an incorrect buffer alignment and zero buffer length */
191     Status = NtSetInformationProcess(NtCurrentProcess(),
192                                      ProcessForegroundInformation,
193                                      (PVOID)1,
194                                      0);
195     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
196 
197     /*
198      * Set the information process foreground with an incorrect buffer alignment but correct size length.
199      * The function will return STATUS_ACCESS_VIOLATION as the alignment probe requirement is not performed
200      * in this class.
201      */
202     Status = NtSetInformationProcess(NtCurrentProcess(),
203                                      ProcessForegroundInformation,
204                                      (PVOID)1,
205                                      sizeof(PROCESS_FOREGROUND_BACKGROUND));
206     ok_hex(Status, STATUS_ACCESS_VIOLATION);
207 
208     /* Set the foreground information to the current given process, we must expect the function should succeed */
209     Status = NtSetInformationProcess(NtCurrentProcess(),
210                                      ProcessForegroundInformation,
211                                      ProcForeground,
212                                      sizeof(PROCESS_FOREGROUND_BACKGROUND));
213     ok_hex(Status, STATUS_SUCCESS);
214 
215     /* Clear all the stuff */
216     HeapFree(GetProcessHeap(), 0, ProcForeground);
217 }
218 
219 static
220 void
Test_ProcessWx86InformationClass(void)221 Test_ProcessWx86InformationClass(void)
222 {
223     NTSTATUS Status;
224     ULONG VdmPower = 1;
225 
226     /* Everything is NULL */
227     Status = NtSetInformationProcess(NULL,
228                                      ProcessWx86Information,
229                                      NULL,
230                                      0);
231     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
232 
233     /* Don't set anything to the process */
234     Status = NtSetInformationProcess(NtCurrentProcess(),
235                                      ProcessWx86Information,
236                                      NULL,
237                                      sizeof(VdmPower));
238     ok_hex(Status, STATUS_ACCESS_VIOLATION);
239 
240     /* The buffer is misaligned and information length is wrong */
241     Status = NtSetInformationProcess(NtCurrentProcess(),
242                                      ProcessWx86Information,
243                                      (PVOID)1,
244                                      0);
245     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
246 
247     /* The buffer is misaligned */
248     Status = NtSetInformationProcess(NtCurrentProcess(),
249                                      ProcessWx86Information,
250                                      (PVOID)1,
251                                      sizeof(VdmPower));
252     ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
253 
254     /* The buffer is misaligned -- try with an alignment size of 2 */
255     Status = NtSetInformationProcess(NtCurrentProcess(),
256                                      ProcessWx86Information,
257                                      (PVOID)2,
258                                      sizeof(VdmPower));
259     ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
260 
261     /* We do not have privileges to set the VDM power */
262     Status = NtSetInformationProcess(NtCurrentProcess(),
263                                      ProcessWx86Information,
264                                      &VdmPower,
265                                      sizeof(VdmPower));
266     ok_hex(Status, STATUS_PRIVILEGE_NOT_HELD);
267 }
268 
269 static
270 void
Test_ProcSetAlignmentProbe(void)271 Test_ProcSetAlignmentProbe(void)
272 {
273     ULONG InfoClass;
274 
275     /* Iterate over the process info classes and begin the tests */
276     for (InfoClass = 0; InfoClass < _countof(PsProcessInfoClass); InfoClass++)
277     {
278         /* The buffer is misaligned */
279         QuerySetProcessValidator(SET,
280                                  InfoClass,
281                                  (PVOID)(ULONG_PTR)1,
282                                  PsProcessInfoClass[InfoClass].RequiredSizeSET,
283                                  STATUS_DATATYPE_MISALIGNMENT);
284 
285         /* We set an invalid buffer address */
286         QuerySetProcessValidator(SET,
287                                  InfoClass,
288                                  (PVOID)(ULONG_PTR)PsProcessInfoClass[InfoClass].AlignmentSET,
289                                  PsProcessInfoClass[InfoClass].RequiredSizeSET,
290                                  STATUS_ACCESS_VIOLATION);
291 
292         /* The information length is wrong */
293         QuerySetProcessValidator(SET,
294                                  InfoClass,
295                                  (PVOID)(ULONG_PTR)PsProcessInfoClass[InfoClass].AlignmentSET,
296                                  PsProcessInfoClass[InfoClass].RequiredSizeSET - 1,
297                                  STATUS_INFO_LENGTH_MISMATCH);
298     }
299 }
300 
START_TEST(NtSetInformationProcess)301 START_TEST(NtSetInformationProcess)
302 {
303     Test_ProcForegroundBackgroundClass();
304     Test_ProcBasePriorityClass();
305     Test_ProcRaisePriorityClass();
306     Test_ProcessWx86InformationClass();
307     Test_ProcSetAlignmentProbe();
308 }
309