1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Tests for the NtQueryInformationProcess API
5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org>
6 * George Bișoc <george.bisoc@reactos.org>
7 */
8
9 #include "precomp.h"
10 #include <internal/ps_i.h>
11
12 static LARGE_INTEGER TestStartTime;
13
14 static
15 void
Test_ProcessTimes(void)16 Test_ProcessTimes(void)
17 {
18 #define SPIN_TIME 1000000
19 NTSTATUS Status;
20 KERNEL_USER_TIMES Times1;
21 KERNEL_USER_TIMES Times2;
22 ULONG Length;
23 LARGE_INTEGER Time1, Time2;
24
25 /* Everything is NULL */
26 Status = NtQueryInformationProcess(NULL,
27 ProcessTimes,
28 NULL,
29 0,
30 NULL);
31 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
32
33 /* Right size, invalid process */
34 Status = NtQueryInformationProcess(NULL,
35 ProcessTimes,
36 NULL,
37 sizeof(KERNEL_USER_TIMES),
38 NULL);
39 ok_hex(Status, STATUS_INVALID_HANDLE);
40
41 /* Valid process, no buffer */
42 Status = NtQueryInformationProcess(NtCurrentProcess(),
43 ProcessTimes,
44 NULL,
45 0,
46 NULL);
47 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
48
49 /* Unaligned buffer, wrong size */
50 Status = NtQueryInformationProcess(NtCurrentProcess(),
51 ProcessTimes,
52 (PVOID)2,
53 0,
54 NULL);
55 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
56
57 /* Unaligned buffer, correct size */
58 Status = NtQueryInformationProcess(NtCurrentProcess(),
59 ProcessTimes,
60 (PVOID)2,
61 sizeof(KERNEL_USER_TIMES),
62 NULL);
63 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
64
65 /* Buffer too small */
66 Status = NtQueryInformationProcess(NtCurrentProcess(),
67 ProcessTimes,
68 NULL,
69 sizeof(KERNEL_USER_TIMES) - 1,
70 NULL);
71 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
72
73 /* Right buffer size but NULL pointer */
74 Status = NtQueryInformationProcess(NtCurrentProcess(),
75 ProcessTimes,
76 NULL,
77 sizeof(KERNEL_USER_TIMES),
78 NULL);
79 ok_hex(Status, STATUS_ACCESS_VIOLATION);
80
81 /* Buffer too large */
82 Status = NtQueryInformationProcess(NtCurrentProcess(),
83 ProcessTimes,
84 NULL,
85 sizeof(KERNEL_USER_TIMES) + 1,
86 NULL);
87 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
88
89 /* Buffer too small, ask for length */
90 Length = 0x55555555;
91 Status = NtQueryInformationProcess(NtCurrentProcess(),
92 ProcessTimes,
93 NULL,
94 sizeof(KERNEL_USER_TIMES) - 1,
95 &Length);
96 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
97 ok_dec(Length, 0x55555555);
98
99 Status = NtQuerySystemTime(&Time1);
100 ok_hex(Status, STATUS_SUCCESS);
101
102 /* Do some busy waiting to increase UserTime */
103 do
104 {
105 Status = NtQuerySystemTime(&Time2);
106 if (!NT_SUCCESS(Status))
107 {
108 ok(0, "NtQuerySystemTime failed with %lx\n", Status);
109 break;
110 }
111 } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME);
112
113 /* Valid parameters, no return length */
114 Status = NtQuerySystemTime(&Time1);
115 ok_hex(Status, STATUS_SUCCESS);
116
117 RtlFillMemory(&Times1, sizeof(Times1), 0x55);
118 Status = NtQueryInformationProcess(NtCurrentProcess(),
119 ProcessTimes,
120 &Times1,
121 sizeof(KERNEL_USER_TIMES),
122 NULL);
123 ok_hex(Status, STATUS_SUCCESS);
124 ok(Times1.CreateTime.QuadPart < TestStartTime.QuadPart,
125 "CreateTime is %I64u, expected < %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart);
126 ok(Times1.CreateTime.QuadPart > TestStartTime.QuadPart - 100000000LL,
127 "CreateTime is %I64u, expected > %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart - 100000000LL);
128 ok(Times1.ExitTime.QuadPart == 0,
129 "ExitTime is %I64u, expected 0\n", Times1.ExitTime.QuadPart);
130 ok(Times1.KernelTime.QuadPart != 0, "KernelTime is 0\n");
131 ros_skip_flaky
132 ok(Times1.UserTime.QuadPart != 0, "UserTime is 0\n");
133
134 /* Do some busy waiting to increase UserTime */
135 do
136 {
137 Status = NtQuerySystemTime(&Time2);
138 if (!NT_SUCCESS(Status))
139 {
140 ok(0, "NtQuerySystemTime failed with %lx\n", Status);
141 break;
142 }
143 } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME);
144
145 /* Again, this time with a return length */
146 Length = 0x55555555;
147 RtlFillMemory(&Times2, sizeof(Times2), 0x55);
148 Status = NtQueryInformationProcess(NtCurrentProcess(),
149 ProcessTimes,
150 &Times2,
151 sizeof(KERNEL_USER_TIMES),
152 &Length);
153 ok_hex(Status, STATUS_SUCCESS);
154 ok_dec(Length, sizeof(KERNEL_USER_TIMES));
155 ok(Times1.CreateTime.QuadPart == Times2.CreateTime.QuadPart,
156 "CreateTimes not equal: %I64u != %I64u\n", Times1.CreateTime.QuadPart, Times2.CreateTime.QuadPart);
157 ok(Times2.ExitTime.QuadPart == 0,
158 "ExitTime is %I64u, expected 0\n", Times2.ExitTime.QuadPart);
159 ok(Times2.KernelTime.QuadPart != 0, "KernelTime is 0\n");
160 ok(Times2.UserTime.QuadPart != 0, "UserTime is 0\n");
161
162 /* Compare the two sets of KernelTime/UserTime values */
163 Status = NtQuerySystemTime(&Time2);
164 ok_hex(Status, STATUS_SUCCESS);
165 /* Time values must have increased */
166 ok(Times2.KernelTime.QuadPart > Times1.KernelTime.QuadPart,
167 "KernelTime values inconsistent. Expected %I64u > %I64u\n", Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart);
168 ros_skip_flaky
169 ok(Times2.UserTime.QuadPart > Times1.UserTime.QuadPart,
170 "UserTime values inconsistent. Expected %I64u > %I64u\n", Times2.UserTime.QuadPart, Times1.UserTime.QuadPart);
171 /* They can't have increased by more than wall clock time difference (we only have one thread) */
172 ros_skip_flaky
173 ok(Times2.KernelTime.QuadPart - Times1.KernelTime.QuadPart < Time2.QuadPart - Time1.QuadPart,
174 "KernelTime values inconsistent. Expected %I64u - %I64u < %I64u\n",
175 Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart, Time2.QuadPart - Time1.QuadPart);
176 ok(Times2.UserTime.QuadPart - Times1.UserTime.QuadPart < Time2.QuadPart - Time1.QuadPart,
177 "UserTime values inconsistent. Expected %I64u - %I64u < %I64u\n",
178 Times2.UserTime.QuadPart, Times1.UserTime.QuadPart, Time2.QuadPart - Time1.QuadPart);
179
180 trace("KernelTime1 = %I64u\n", Times1.KernelTime.QuadPart);
181 trace("KernelTime2 = %I64u\n", Times2.KernelTime.QuadPart);
182 trace("UserTime1 = %I64u\n", Times1.UserTime.QuadPart);
183 trace("UserTime2 = %I64u\n", Times2.UserTime.QuadPart);
184
185 /* TODO: Test ExitTime on a terminated process */
186 #undef SPIN_TIME
187 }
188
189 static
190 void
Test_ProcessBasicInformation(void)191 Test_ProcessBasicInformation(void)
192 {
193 NTSTATUS Status;
194 ULONG Length;
195 PROCESS_BASIC_INFORMATION BasicInfo;
196
197 /* Everything is NULL */
198 Status = NtQueryInformationProcess(NULL,
199 ProcessBasicInformation,
200 NULL,
201 0,
202 NULL);
203 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
204
205 /* Right size, invalid process handle */
206 Status = NtQueryInformationProcess(NULL,
207 ProcessBasicInformation,
208 NULL,
209 sizeof(BasicInfo),
210 NULL);
211 ok_hex(Status, STATUS_INVALID_HANDLE);
212
213 /* Valid process handle, no buffer */
214 Status = NtQueryInformationProcess(NtCurrentProcess(),
215 ProcessBasicInformation,
216 NULL,
217 0,
218 NULL);
219 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
220
221 /* Unaligned buffer, wrong size */
222 Status = NtQueryInformationProcess(NtCurrentProcess(),
223 ProcessBasicInformation,
224 (PVOID)2,
225 0,
226 NULL);
227 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
228
229 /* Unaligned buffer, correct size */
230 Status = NtQueryInformationProcess(NtCurrentProcess(),
231 ProcessBasicInformation,
232 (PVOID)2,
233 sizeof(BasicInfo),
234 NULL);
235 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
236
237 /* Buffer too small */
238 Status = NtQueryInformationProcess(NtCurrentProcess(),
239 ProcessBasicInformation,
240 NULL,
241 sizeof(BasicInfo) - 1,
242 NULL);
243 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
244
245 /* Right buffer size but NULL pointer */
246 Status = NtQueryInformationProcess(NtCurrentProcess(),
247 ProcessBasicInformation,
248 NULL,
249 sizeof(BasicInfo),
250 NULL);
251 ok_hex(Status, STATUS_ACCESS_VIOLATION);
252
253 /* Buffer too large */
254 Status = NtQueryInformationProcess(NtCurrentProcess(),
255 ProcessBasicInformation,
256 NULL,
257 sizeof(BasicInfo) + 1,
258 NULL);
259 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
260
261 /* Buffer too small, ask for length */
262 Length = 0x55555555;
263 Status = NtQueryInformationProcess(NtCurrentProcess(),
264 ProcessBasicInformation,
265 NULL,
266 sizeof(BasicInfo) - 1,
267 &Length);
268 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
269 ok_dec(Length, 0x55555555);
270
271 /* Valid parameters, no return length */
272 RtlFillMemory(&BasicInfo, sizeof(BasicInfo), 0x55);
273 Status = NtQueryInformationProcess(NtCurrentProcess(),
274 ProcessBasicInformation,
275 &BasicInfo,
276 sizeof(BasicInfo),
277 NULL);
278 ok_hex(Status, STATUS_SUCCESS);
279
280 /* Trace the returned data (1) */
281 trace("[1] BasicInfo.ExitStatus = %lx\n", BasicInfo.ExitStatus);
282 trace("[1] BasicInfo.PebBaseAddress = %p\n", BasicInfo.PebBaseAddress);
283 trace("[1] BasicInfo.AffinityMask = %Ix\n", BasicInfo.AffinityMask);
284 trace("[1] BasicInfo.BasePriority = %ld\n", BasicInfo.BasePriority);
285 trace("[1] BasicInfo.UniqueProcessId = %Iu\n", BasicInfo.UniqueProcessId);
286 trace("[1] BasicInfo.InheritedFromUniqueProcessId = %Iu\n", BasicInfo.InheritedFromUniqueProcessId);
287
288 /* Again, this time with a return length */
289 Length = 0x55555555;
290 RtlFillMemory(&BasicInfo, sizeof(BasicInfo), 0x55);
291 Status = NtQueryInformationProcess(NtCurrentProcess(),
292 ProcessBasicInformation,
293 &BasicInfo,
294 sizeof(BasicInfo),
295 &Length);
296 ok_hex(Status, STATUS_SUCCESS);
297 ok_dec(Length, sizeof(BasicInfo));
298
299 /* Trace the returned data (2) */
300 trace("[2] BasicInfo.ExitStatus = %lx\n", BasicInfo.ExitStatus);
301 trace("[2] BasicInfo.PebBaseAddress = %p\n", BasicInfo.PebBaseAddress);
302 trace("[2] BasicInfo.AffinityMask = %Ix\n", BasicInfo.AffinityMask);
303 trace("[2] BasicInfo.BasePriority = %ld\n", BasicInfo.BasePriority);
304 trace("[2] BasicInfo.UniqueProcessId = %Iu\n", BasicInfo.UniqueProcessId);
305 trace("[2] BasicInfo.InheritedFromUniqueProcessId = %Iu\n", BasicInfo.InheritedFromUniqueProcessId);
306 }
307
308 static
309 void
Test_ProcessQuotaLimits(void)310 Test_ProcessQuotaLimits(void)
311 {
312 NTSTATUS Status;
313 ULONG Length;
314 QUOTA_LIMITS QuotaLimits;
315
316 /* Everything is NULL */
317 Status = NtQueryInformationProcess(NULL,
318 ProcessQuotaLimits,
319 NULL,
320 0,
321 NULL);
322 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
323
324 /* Right size, invalid process handle */
325 Status = NtQueryInformationProcess(NULL,
326 ProcessQuotaLimits,
327 NULL,
328 sizeof(QuotaLimits),
329 NULL);
330 ok_hex(Status, STATUS_INVALID_HANDLE);
331
332 /* Valid process handle, no buffer */
333 Status = NtQueryInformationProcess(NtCurrentProcess(),
334 ProcessQuotaLimits,
335 NULL,
336 0,
337 NULL);
338 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
339
340 /* Unaligned buffer, wrong size */
341 Status = NtQueryInformationProcess(NtCurrentProcess(),
342 ProcessQuotaLimits,
343 (PVOID)2,
344 0,
345 NULL);
346 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
347
348 /* Unaligned buffer, correct size */
349 Status = NtQueryInformationProcess(NtCurrentProcess(),
350 ProcessQuotaLimits,
351 (PVOID)2,
352 sizeof(QuotaLimits),
353 NULL);
354 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
355
356 /* Buffer too small */
357 Status = NtQueryInformationProcess(NtCurrentProcess(),
358 ProcessQuotaLimits,
359 NULL,
360 sizeof(QuotaLimits) - 1,
361 NULL);
362 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
363
364 /* Right buffer size but NULL pointer */
365 Status = NtQueryInformationProcess(NtCurrentProcess(),
366 ProcessQuotaLimits,
367 NULL,
368 sizeof(QuotaLimits),
369 NULL);
370 ok_hex(Status, STATUS_ACCESS_VIOLATION);
371
372 /* Buffer too large */
373 Status = NtQueryInformationProcess(NtCurrentProcess(),
374 ProcessQuotaLimits,
375 NULL,
376 sizeof(QuotaLimits) + 1,
377 NULL);
378 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
379
380 /* Buffer too small, ask for length */
381 Length = 0x55555555;
382 Status = NtQueryInformationProcess(NtCurrentProcess(),
383 ProcessQuotaLimits,
384 NULL,
385 sizeof(QuotaLimits) - 1,
386 &Length);
387 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
388 ok_dec(Length, 0x55555555);
389
390 /* Valid parameters, no return length */
391 RtlFillMemory(&QuotaLimits, sizeof(QuotaLimits), 0x55);
392 Status = NtQueryInformationProcess(NtCurrentProcess(),
393 ProcessQuotaLimits,
394 &QuotaLimits,
395 sizeof(QuotaLimits),
396 NULL);
397 ok_hex(Status, STATUS_SUCCESS);
398
399 /* Trace the returned data (1) */
400 trace("[1] QuotaLimits.PagedPoolLimit = %Iu\n", QuotaLimits.PagedPoolLimit);
401 trace("[1] QuotaLimits.NonPagedPoolLimit = %Iu\n", QuotaLimits.NonPagedPoolLimit);
402 trace("[1] QuotaLimits.MinimumWorkingSetSize = %Iu\n", QuotaLimits.MinimumWorkingSetSize);
403 trace("[1] QuotaLimits.MaximumWorkingSetSize = %Iu\n", QuotaLimits.MaximumWorkingSetSize);
404 trace("[1] QuotaLimits.PagefileLimit = %Iu\n", QuotaLimits.PagefileLimit);
405 trace("[1] QuotaLimits.TimeLimit = %I64d\n", QuotaLimits.TimeLimit.QuadPart);
406
407 /* Again, this time with a return length */
408 Length = 0x55555555;
409 RtlFillMemory(&QuotaLimits, sizeof(QuotaLimits), 0x55);
410 Status = NtQueryInformationProcess(NtCurrentProcess(),
411 ProcessQuotaLimits,
412 &QuotaLimits,
413 sizeof(QuotaLimits),
414 &Length);
415 ok_hex(Status, STATUS_SUCCESS);
416 ok_dec(Length, sizeof(QuotaLimits));
417
418 /* Trace the returned data (2) */
419 trace("[2] QuotaLimits.PagedPoolLimit = %Iu\n", QuotaLimits.PagedPoolLimit);
420 trace("[2] QuotaLimits.NonPagedPoolLimit = %Iu\n", QuotaLimits.NonPagedPoolLimit);
421 trace("[2] QuotaLimits.MinimumWorkingSetSize = %Iu\n", QuotaLimits.MinimumWorkingSetSize);
422 trace("[2] QuotaLimits.MaximumWorkingSetSize = %Iu\n", QuotaLimits.MaximumWorkingSetSize);
423 trace("[2] QuotaLimits.PagefileLimit = %Iu\n", QuotaLimits.PagefileLimit);
424 trace("[2] QuotaLimits.TimeLimit = %I64d\n", QuotaLimits.TimeLimit.QuadPart);
425 }
426
427 static
428 void
Test_ProcessQuotaLimitsEx(void)429 Test_ProcessQuotaLimitsEx(void)
430 {
431 NTSTATUS Status;
432 ULONG Length;
433 QUOTA_LIMITS_EX QuotaLimitsEx;
434
435 /* Right size, invalid process handle */
436 Status = NtQueryInformationProcess(NULL,
437 ProcessQuotaLimits,
438 NULL,
439 sizeof(QuotaLimitsEx),
440 NULL);
441 ok_hex(Status, STATUS_INVALID_HANDLE);
442
443 /* Unaligned buffer, correct size */
444 Status = NtQueryInformationProcess(NtCurrentProcess(),
445 ProcessQuotaLimits,
446 (PVOID)2,
447 sizeof(QuotaLimitsEx),
448 NULL);
449 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
450
451 /* Buffer too small */
452 Status = NtQueryInformationProcess(NtCurrentProcess(),
453 ProcessQuotaLimits,
454 NULL,
455 sizeof(QuotaLimitsEx) - 1,
456 NULL);
457 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
458
459 /* Right buffer size but NULL pointer */
460 Status = NtQueryInformationProcess(NtCurrentProcess(),
461 ProcessQuotaLimits,
462 NULL,
463 sizeof(QuotaLimitsEx),
464 NULL);
465 ok_hex(Status, STATUS_ACCESS_VIOLATION);
466
467 /* Buffer too large */
468 Status = NtQueryInformationProcess(NtCurrentProcess(),
469 ProcessQuotaLimits,
470 NULL,
471 sizeof(QuotaLimitsEx) + 1,
472 NULL);
473 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
474
475 /* Buffer too small, ask for length */
476 Length = 0x55555555;
477 Status = NtQueryInformationProcess(NtCurrentProcess(),
478 ProcessQuotaLimits,
479 NULL,
480 sizeof(QuotaLimitsEx) - 1,
481 &Length);
482 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
483 ok_dec(Length, 0x55555555);
484
485 /* Valid parameters, no return length */
486 RtlFillMemory(&QuotaLimitsEx, sizeof(QuotaLimitsEx), 0x55);
487 Status = NtQueryInformationProcess(NtCurrentProcess(),
488 ProcessQuotaLimits,
489 &QuotaLimitsEx,
490 sizeof(QuotaLimitsEx),
491 NULL);
492 ok_hex(Status, STATUS_SUCCESS);
493
494 /* Trace the returned data (1) */
495 trace("[1] QuotaLimitsEx.PagedPoolLimit = %Iu\n", QuotaLimitsEx.PagedPoolLimit);
496 trace("[1] QuotaLimitsEx.NonPagedPoolLimit = %Iu\n", QuotaLimitsEx.NonPagedPoolLimit);
497 trace("[1] QuotaLimitsEx.MinimumWorkingSetSize = %Iu\n", QuotaLimitsEx.MinimumWorkingSetSize);
498 trace("[1] QuotaLimitsEx.MaximumWorkingSetSize = %Iu\n", QuotaLimitsEx.MaximumWorkingSetSize);
499 trace("[1] QuotaLimitsEx.PagefileLimit = %Iu\n", QuotaLimitsEx.PagefileLimit);
500 trace("[1] QuotaLimitsEx.TimeLimit = %I64d\n", QuotaLimitsEx.TimeLimit.QuadPart);
501 //trace("[1] QuotaLimitsEx.WorkingSetLimit = %Iu\n", QuotaLimitsEx.WorkingSetLimit); // Not used on Win2k3
502 trace("[1] QuotaLimitsEx.Flags = %lx\n", QuotaLimitsEx.Flags);
503 trace("[1] QuotaLimitsEx.CpuRateLimit.RateData = %lx\n", QuotaLimitsEx.CpuRateLimit.RateData);
504
505 /* Again, this time with a return length */
506 Length = 0x55555555;
507 RtlFillMemory(&QuotaLimitsEx, sizeof(QuotaLimitsEx), 0x55);
508 Status = NtQueryInformationProcess(NtCurrentProcess(),
509 ProcessQuotaLimits,
510 &QuotaLimitsEx,
511 sizeof(QuotaLimitsEx),
512 &Length);
513 ok_hex(Status, STATUS_SUCCESS);
514 ok_dec(Length, sizeof(QuotaLimitsEx));
515
516 /* Trace the returned data (2) */
517 trace("[2] QuotaLimitsEx.PagedPoolLimit = %Iu\n", QuotaLimitsEx.PagedPoolLimit);
518 trace("[2] QuotaLimitsEx.NonPagedPoolLimit = %Iu\n", QuotaLimitsEx.NonPagedPoolLimit);
519 trace("[2] QuotaLimitsEx.MinimumWorkingSetSize = %Iu\n", QuotaLimitsEx.MinimumWorkingSetSize);
520 trace("[2] QuotaLimitsEx.MaximumWorkingSetSize = %Iu\n", QuotaLimitsEx.MaximumWorkingSetSize);
521 trace("[2] QuotaLimitsEx.PagefileLimit = %Iu\n", QuotaLimitsEx.PagefileLimit);
522 trace("[2] QuotaLimitsEx.TimeLimit = %I64d\n", QuotaLimitsEx.TimeLimit.QuadPart);
523 //trace("[2] QuotaLimitsEx.WorkingSetLimit = %Iu\n", QuotaLimitsEx.WorkingSetLimit); // Not used on Win2k3
524 trace("[2] QuotaLimitsEx.Flags = %lx\n", QuotaLimitsEx.Flags);
525 trace("[2] QuotaLimitsEx.CpuRateLimit.RateData = %lx\n", QuotaLimitsEx.CpuRateLimit.RateData);
526 }
527
528 static
529 void
Test_ProcessPriorityClassAlignment(void)530 Test_ProcessPriorityClassAlignment(void)
531 {
532 NTSTATUS Status;
533 PPROCESS_PRIORITY_CLASS ProcPriority;
534
535 /* Allocate some memory for the priority class structure */
536 ProcPriority = malloc(sizeof(PROCESS_PRIORITY_CLASS));
537 if (ProcPriority == NULL)
538 {
539 skip("Failed to allocate memory for PROCESS_PRIORITY_CLASS!\n");
540 return;
541 }
542
543 /*
544 * Initialize the PriorityClass member to ensure the test won't randomly succeed (if such data is uninitialized).
545 * Filling 85 to the data member makes sure that if the test fails continously then NtQueryInformationProcess()
546 * didn't initialize the structure with data.
547 */
548 RtlFillMemory(&ProcPriority->PriorityClass, sizeof(ProcPriority->PriorityClass), 0x55);
549
550 /* Unaligned buffer -- wrong size */
551 Status = NtQueryInformationProcess(NtCurrentProcess(),
552 ProcessPriorityClass,
553 (PVOID)1,
554 0,
555 NULL);
556 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
557
558 /* Unaligned buffer -- correct size */
559 Status = NtQueryInformationProcess(NtCurrentProcess(),
560 ProcessPriorityClass,
561 (PVOID)1,
562 sizeof(PROCESS_PRIORITY_CLASS),
563 NULL);
564 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
565
566 /* Unaligned buffer -- wrong size (but this time do with an alignment of 2) */
567 Status = NtQueryInformationProcess(NtCurrentProcess(),
568 ProcessPriorityClass,
569 (PVOID)2,
570 0,
571 NULL);
572 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
573
574 /* Unaligned buffer -- correct size (but this time do with an alignment of 2) */
575 Status = NtQueryInformationProcess(NtCurrentProcess(),
576 ProcessPriorityClass,
577 (PVOID)2,
578 sizeof(PROCESS_PRIORITY_CLASS),
579 NULL);
580 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
581
582 /* Do not care for the length but expect to return the priority class */
583 Status = NtQueryInformationProcess(NtCurrentProcess(),
584 ProcessPriorityClass,
585 ProcPriority,
586 sizeof(PROCESS_PRIORITY_CLASS),
587 NULL);
588 ok_hex(Status, STATUS_SUCCESS);
589
590 /* Make sure the returned priority class is a valid number (non negative) but also it should be within the PROCESS_PRIORITY_CLASS range */
591 ok(ProcPriority->PriorityClass > PROCESS_PRIORITY_CLASS_INVALID && ProcPriority->PriorityClass <= PROCESS_PRIORITY_CLASS_ABOVE_NORMAL,
592 "Expected a valid number from priority class range but got %d\n", ProcPriority->PriorityClass);
593 free(ProcPriority);
594 }
595
596 static
597 void
Test_ProcessWx86Information(void)598 Test_ProcessWx86Information(void)
599 {
600 NTSTATUS Status;
601 ULONG VdmPower = 1, ReturnLength;
602
603 /* Everything is NULL */
604 Status = NtQueryInformationProcess(NULL,
605 ProcessWx86Information,
606 NULL,
607 0,
608 NULL);
609 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
610
611 /* Given an invalid process handle */
612 Status = NtQueryInformationProcess(NULL,
613 ProcessWx86Information,
614 &VdmPower,
615 sizeof(VdmPower),
616 NULL);
617 ok_hex(Status, STATUS_INVALID_HANDLE);
618
619 /* Don't query anything */
620 Status = NtQueryInformationProcess(NtCurrentProcess(),
621 ProcessWx86Information,
622 NULL,
623 sizeof(VdmPower),
624 NULL);
625 ok_hex(Status, STATUS_ACCESS_VIOLATION);
626
627 /* The buffer is misaligned and information length is wrong */
628 Status = NtQueryInformationProcess(NtCurrentProcess(),
629 ProcessWx86Information,
630 (PVOID)1,
631 0,
632 NULL);
633 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
634
635 /* The buffer is misaligned */
636 Status = NtQueryInformationProcess(NtCurrentProcess(),
637 ProcessWx86Information,
638 (PVOID)1,
639 sizeof(VdmPower),
640 NULL);
641 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
642
643 /* The buffer is misaligned -- try with an alignment size of 2 */
644 Status = NtQueryInformationProcess(NtCurrentProcess(),
645 ProcessWx86Information,
646 (PVOID)2,
647 sizeof(VdmPower),
648 NULL);
649 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
650
651 /* Query the VDM power */
652 Status = NtQueryInformationProcess(NtCurrentProcess(),
653 ProcessWx86Information,
654 &VdmPower,
655 sizeof(VdmPower),
656 NULL);
657 ok_hex(Status, STATUS_SUCCESS);
658 ok(VdmPower == 0 || VdmPower == 1, "The VDM power value must be within the boundary between 0 and 1, not anything else! Got %lu\n", VdmPower);
659
660 /* Same but with ReturnLength */
661 Status = NtQueryInformationProcess(NtCurrentProcess(),
662 ProcessWx86Information,
663 &VdmPower,
664 sizeof(VdmPower),
665 &ReturnLength);
666 ok_hex(Status, STATUS_SUCCESS);
667 ok(ReturnLength != 0, "ReturnLength shouldn't be 0!\n");
668 ok(VdmPower == 0 || VdmPower == 1, "The VDM power value must be within the boundary between 0 and 1, not anything else! Got %lu\n", VdmPower);
669
670 /* Trace the VDM power value and returned length */
671 trace("ReturnLength = %lu\n", ReturnLength);
672 trace("VdmPower = %lu\n", VdmPower);
673 }
674
675 static
676 void
Test_ProcQueryAlignmentProbe(void)677 Test_ProcQueryAlignmentProbe(void)
678 {
679 ULONG InfoClass;
680
681 /* Iterate over the process info classes and begin the tests */
682 for (InfoClass = 0; InfoClass < _countof(PsProcessInfoClass); InfoClass++)
683 {
684 /* The buffer is misaligned */
685 QuerySetProcessValidator(QUERY,
686 InfoClass,
687 (PVOID)(ULONG_PTR)1,
688 PsProcessInfoClass[InfoClass].RequiredSizeQUERY,
689 STATUS_DATATYPE_MISALIGNMENT);
690
691 /* We query an invalid buffer address */
692 QuerySetProcessValidator(QUERY,
693 InfoClass,
694 (PVOID)(ULONG_PTR)PsProcessInfoClass[InfoClass].AlignmentQUERY,
695 PsProcessInfoClass[InfoClass].RequiredSizeQUERY,
696 STATUS_ACCESS_VIOLATION);
697
698 /* The information length is wrong */
699 QuerySetProcessValidator(QUERY,
700 InfoClass,
701 (PVOID)(ULONG_PTR)PsProcessInfoClass[InfoClass].AlignmentQUERY,
702 PsProcessInfoClass[InfoClass].RequiredSizeQUERY - 1,
703 STATUS_INFO_LENGTH_MISMATCH);
704 }
705 }
706
START_TEST(NtQueryInformationProcess)707 START_TEST(NtQueryInformationProcess)
708 {
709 NTSTATUS Status;
710
711 /* Make sure that some time has passed since process creation, even if the resolution of our NtQuerySystemTime is low. */
712 Sleep(1);
713
714 Status = NtQuerySystemTime(&TestStartTime);
715 ok_hex(Status, STATUS_SUCCESS);
716
717 Test_ProcessTimes();
718 Test_ProcessBasicInformation();
719 Test_ProcessQuotaLimits();
720 Test_ProcessQuotaLimitsEx();
721 Test_ProcessPriorityClassAlignment();
722 Test_ProcessWx86Information();
723 Test_ProcQueryAlignmentProbe();
724 }
725