1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS API tests
3c2c66affSColin Finck  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4c2c66affSColin Finck  * PURPOSE:         Tests for the NtQueryInformationProcess API
5c2c66affSColin Finck  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6c2c66affSColin Finck  */
7c2c66affSColin Finck 
8*283bbe73SAmine Khaldi #include "precomp.h"
9c2c66affSColin Finck 
10c2c66affSColin Finck static LARGE_INTEGER TestStartTime;
11c2c66affSColin Finck 
12c2c66affSColin Finck static
13c2c66affSColin Finck void
14c2c66affSColin Finck Test_ProcessTimes(void)
15c2c66affSColin Finck {
16c2c66affSColin Finck #define SPIN_TIME 1000000
17c2c66affSColin Finck     NTSTATUS Status;
18c2c66affSColin Finck     KERNEL_USER_TIMES Times1;
19c2c66affSColin Finck     KERNEL_USER_TIMES Times2;
20c2c66affSColin Finck     ULONG Length;
21c2c66affSColin Finck     LARGE_INTEGER Time1, Time2;
22c2c66affSColin Finck 
23c2c66affSColin Finck     /* Everything is NULL */
24c2c66affSColin Finck     Status = NtQueryInformationProcess(NULL,
25c2c66affSColin Finck                                        ProcessTimes,
26c2c66affSColin Finck                                        NULL,
27c2c66affSColin Finck                                        0,
28c2c66affSColin Finck                                        NULL);
29c2c66affSColin Finck     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
30c2c66affSColin Finck 
31c2c66affSColin Finck     /* Right size, invalid process */
32c2c66affSColin Finck     Status = NtQueryInformationProcess(NULL,
33c2c66affSColin Finck                                        ProcessTimes,
34c2c66affSColin Finck                                        NULL,
35c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES),
36c2c66affSColin Finck                                        NULL);
37c2c66affSColin Finck     ok_hex(Status, STATUS_INVALID_HANDLE);
38c2c66affSColin Finck 
39c2c66affSColin Finck     /* Valid process, no buffer */
40c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
41c2c66affSColin Finck                                        ProcessTimes,
42c2c66affSColin Finck                                        NULL,
43c2c66affSColin Finck                                        0,
44c2c66affSColin Finck                                        NULL);
45c2c66affSColin Finck     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
46c2c66affSColin Finck 
47c2c66affSColin Finck     /* Unaligned buffer, wrong size */
48c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
49c2c66affSColin Finck                                        ProcessTimes,
50c2c66affSColin Finck                                        (PVOID)2,
51c2c66affSColin Finck                                        0,
52c2c66affSColin Finck                                        NULL);
53c2c66affSColin Finck     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
54c2c66affSColin Finck 
55c2c66affSColin Finck     /* Unaligned buffer, correct size */
56c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
57c2c66affSColin Finck                                        ProcessTimes,
58c2c66affSColin Finck                                        (PVOID)2,
59c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES),
60c2c66affSColin Finck                                        NULL);
61c2c66affSColin Finck     ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT);
62c2c66affSColin Finck 
63c2c66affSColin Finck     /* Buffer too small */
64c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
65c2c66affSColin Finck                                        ProcessTimes,
66c2c66affSColin Finck                                        NULL,
67c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES) - 1,
68c2c66affSColin Finck                                        NULL);
69c2c66affSColin Finck     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
70c2c66affSColin Finck 
71c2c66affSColin Finck     /* Right buffer size but NULL pointer */
72c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
73c2c66affSColin Finck                                        ProcessTimes,
74c2c66affSColin Finck                                        NULL,
75c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES),
76c2c66affSColin Finck                                        NULL);
77c2c66affSColin Finck     ok_hex(Status, STATUS_ACCESS_VIOLATION);
78c2c66affSColin Finck 
79c2c66affSColin Finck     /* Buffer too large */
80c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
81c2c66affSColin Finck                                        ProcessTimes,
82c2c66affSColin Finck                                        NULL,
83c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES) + 1,
84c2c66affSColin Finck                                        NULL);
85c2c66affSColin Finck     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
86c2c66affSColin Finck 
87c2c66affSColin Finck     /* Buffer too small, ask for length */
88c2c66affSColin Finck     Length = 0x55555555;
89c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
90c2c66affSColin Finck                                        ProcessTimes,
91c2c66affSColin Finck                                        NULL,
92c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES) - 1,
93c2c66affSColin Finck                                        &Length);
94c2c66affSColin Finck     ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
95c2c66affSColin Finck     ok_dec(Length, 0x55555555);
96c2c66affSColin Finck 
97c2c66affSColin Finck     Status = NtQuerySystemTime(&Time1);
98c2c66affSColin Finck     ok_hex(Status, STATUS_SUCCESS);
99c2c66affSColin Finck 
100c2c66affSColin Finck     /* Do some busy waiting to increase UserTime */
101c2c66affSColin Finck     do
102c2c66affSColin Finck     {
103c2c66affSColin Finck         Status = NtQuerySystemTime(&Time2);
104c2c66affSColin Finck         if (!NT_SUCCESS(Status))
105c2c66affSColin Finck         {
106c2c66affSColin Finck             ok(0, "NtQuerySystemTime failed with %lx\n", Status);
107c2c66affSColin Finck             break;
108c2c66affSColin Finck         }
109c2c66affSColin Finck     } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME);
110c2c66affSColin Finck 
111c2c66affSColin Finck     /* Valid parameters, no return length */
112c2c66affSColin Finck     Status = NtQuerySystemTime(&Time1);
113c2c66affSColin Finck     ok_hex(Status, STATUS_SUCCESS);
114c2c66affSColin Finck 
115c2c66affSColin Finck     RtlFillMemory(&Times1, sizeof(Times1), 0x55);
116c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
117c2c66affSColin Finck                                        ProcessTimes,
118c2c66affSColin Finck                                        &Times1,
119c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES),
120c2c66affSColin Finck                                        NULL);
121c2c66affSColin Finck     ok_hex(Status, STATUS_SUCCESS);
122c2c66affSColin Finck     ok(Times1.CreateTime.QuadPart < TestStartTime.QuadPart,
123c2c66affSColin Finck        "CreateTime is %I64u, expected < %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart);
124c2c66affSColin Finck     ok(Times1.CreateTime.QuadPart > TestStartTime.QuadPart - 100000000LL,
125c2c66affSColin Finck        "CreateTime is %I64u, expected > %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart - 100000000LL);
126c2c66affSColin Finck     ok(Times1.ExitTime.QuadPart == 0,
127c2c66affSColin Finck        "ExitTime is %I64u, expected 0\n", Times1.ExitTime.QuadPart);
128c2c66affSColin Finck     ok(Times1.KernelTime.QuadPart != 0, "KernelTime is 0\n");
129c2c66affSColin Finck     ok(Times1.UserTime.QuadPart != 0, "UserTime is 0\n");
130c2c66affSColin Finck 
131c2c66affSColin Finck     /* Do some busy waiting to increase UserTime */
132c2c66affSColin Finck     do
133c2c66affSColin Finck     {
134c2c66affSColin Finck         Status = NtQuerySystemTime(&Time2);
135c2c66affSColin Finck         if (!NT_SUCCESS(Status))
136c2c66affSColin Finck         {
137c2c66affSColin Finck             ok(0, "NtQuerySystemTime failed with %lx\n", Status);
138c2c66affSColin Finck             break;
139c2c66affSColin Finck         }
140c2c66affSColin Finck     } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME);
141c2c66affSColin Finck 
142c2c66affSColin Finck     /* Again, this time with a return length */
143c2c66affSColin Finck     Length = 0x55555555;
144c2c66affSColin Finck     RtlFillMemory(&Times2, sizeof(Times2), 0x55);
145c2c66affSColin Finck     Status = NtQueryInformationProcess(NtCurrentProcess(),
146c2c66affSColin Finck                                        ProcessTimes,
147c2c66affSColin Finck                                        &Times2,
148c2c66affSColin Finck                                        sizeof(KERNEL_USER_TIMES),
149c2c66affSColin Finck                                        &Length);
150c2c66affSColin Finck     ok_hex(Status, STATUS_SUCCESS);
151c2c66affSColin Finck     ok_dec(Length, sizeof(KERNEL_USER_TIMES));
152c2c66affSColin Finck     ok(Times1.CreateTime.QuadPart == Times2.CreateTime.QuadPart,
153c2c66affSColin Finck        "CreateTimes not equal: %I64u != %I64u\n", Times1.CreateTime.QuadPart, Times2.CreateTime.QuadPart);
154c2c66affSColin Finck     ok(Times2.ExitTime.QuadPart == 0,
155c2c66affSColin Finck        "ExitTime is %I64u, expected 0\n", Times2.ExitTime.QuadPart);
156c2c66affSColin Finck     ok(Times2.KernelTime.QuadPart != 0, "KernelTime is 0\n");
157c2c66affSColin Finck     ok(Times2.UserTime.QuadPart != 0, "UserTime is 0\n");
158c2c66affSColin Finck 
159c2c66affSColin Finck     /* Compare the two sets of KernelTime/UserTime values */
160c2c66affSColin Finck     Status = NtQuerySystemTime(&Time2);
161c2c66affSColin Finck     ok_hex(Status, STATUS_SUCCESS);
162c2c66affSColin Finck     /* Time values must have increased */
163c2c66affSColin Finck     ok(Times2.KernelTime.QuadPart > Times1.KernelTime.QuadPart,
164c2c66affSColin Finck        "KernelTime values inconsistent. Expected %I64u > %I64u\n", Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart);
165c2c66affSColin Finck     ok(Times2.UserTime.QuadPart > Times1.UserTime.QuadPart,
166c2c66affSColin Finck        "UserTime values inconsistent. Expected %I64u > %I64u\n", Times2.UserTime.QuadPart, Times1.UserTime.QuadPart);
167c2c66affSColin Finck     /* They can't have increased by more than wall clock time difference (we only have one thread) */
168c2c66affSColin Finck     ok(Times2.KernelTime.QuadPart - Times1.KernelTime.QuadPart < Time2.QuadPart - Time1.QuadPart,
169c2c66affSColin Finck        "KernelTime values inconsistent. Expected %I64u - %I64u < %I64u\n",
170c2c66affSColin Finck        Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart, Time2.QuadPart - Time1.QuadPart);
171c2c66affSColin Finck     ok(Times2.UserTime.QuadPart - Times1.UserTime.QuadPart < Time2.QuadPart - Time1.QuadPart,
172c2c66affSColin Finck        "UserTime values inconsistent. Expected %I64u - %I64u < %I64u\n",
173c2c66affSColin Finck        Times2.UserTime.QuadPart, Times1.UserTime.QuadPart, Time2.QuadPart - Time1.QuadPart);
174c2c66affSColin Finck 
175c2c66affSColin Finck     trace("KernelTime1 = %I64u\n", Times1.KernelTime.QuadPart);
176c2c66affSColin Finck     trace("KernelTime2 = %I64u\n", Times2.KernelTime.QuadPart);
177c2c66affSColin Finck     trace("UserTime1 = %I64u\n", Times1.UserTime.QuadPart);
178c2c66affSColin Finck     trace("UserTime2 = %I64u\n", Times2.UserTime.QuadPart);
179c2c66affSColin Finck 
180c2c66affSColin Finck     /* TODO: Test ExitTime on a terminated process */
181c2c66affSColin Finck #undef SPIN_TIME
182c2c66affSColin Finck }
183c2c66affSColin Finck 
184c2c66affSColin Finck START_TEST(NtQueryInformationProcess)
185c2c66affSColin Finck {
186c2c66affSColin Finck     NTSTATUS Status;
187c2c66affSColin Finck 
188c2c66affSColin Finck     Status = NtQuerySystemTime(&TestStartTime);
189c2c66affSColin Finck     ok_hex(Status, STATUS_SUCCESS);
190c2c66affSColin Finck 
191c2c66affSColin Finck     Test_ProcessTimes();
192c2c66affSColin Finck }
193