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