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