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
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
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
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
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
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
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
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 
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