e641a8d0ff231a85d74cf663b0b5acb81dc1862e
[reactos.git] / modules / rostests / winetests / ntdll / info.c
1 /* Unit test suite for *Information* Registry API functions
2 *
3 * Copyright 2005 Paul Vriens
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 */
20
21 #include "ntdll_test.h"
22 #include <winnls.h>
23 #include <stdio.h>
24
25 static NTSTATUS (WINAPI * pRtlDowncaseUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);
26 static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
27 static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*);
28 static NTSTATUS (WINAPI * pNtPowerInformation)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
29 static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
30 static NTSTATUS (WINAPI * pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
31 static NTSTATUS (WINAPI * pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
32 static NTSTATUS (WINAPI * pNtSetInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG);
33 static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
34 static NTSTATUS (WINAPI * pNtQueryVirtualMemory)(HANDLE, LPCVOID, MEMORY_INFORMATION_CLASS , PVOID , SIZE_T , SIZE_T *);
35 static NTSTATUS (WINAPI * pNtCreateSection)(HANDLE*,ACCESS_MASK,const OBJECT_ATTRIBUTES*,const LARGE_INTEGER*,ULONG,ULONG,HANDLE);
36 static NTSTATUS (WINAPI * pNtMapViewOfSection)(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,SECTION_INHERIT,ULONG,ULONG);
37 static NTSTATUS (WINAPI * pNtUnmapViewOfSection)(HANDLE,PVOID);
38 static NTSTATUS (WINAPI * pNtClose)(HANDLE);
39 static ULONG (WINAPI * pNtGetCurrentProcessorNumber)(void);
40 static BOOL (WINAPI * pIsWow64Process)(HANDLE, PBOOL);
41 static BOOL (WINAPI * pGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP,SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*,DWORD*);
42
43 static BOOL is_wow64;
44
45 /* one_before_last_pid is used to be able to compare values of a still running process
46 with the output of the test_query_process_times and test_query_process_handlecount tests.
47 */
48 static DWORD one_before_last_pid = 0;
49
50 #define NTDLL_GET_PROC(func) do { \
51 p ## func = (void*)GetProcAddress(hntdll, #func); \
52 if(!p ## func) { \
53 trace("GetProcAddress(%s) failed\n", #func); \
54 return FALSE; \
55 } \
56 } while(0)
57
58 static BOOL InitFunctionPtrs(void)
59 {
60 /* All needed functions are NT based, so using GetModuleHandle is a good check */
61 HMODULE hntdll = GetModuleHandleA("ntdll");
62 HMODULE hkernel32 = GetModuleHandleA("kernel32");
63
64 if (!hntdll)
65 {
66 win_skip("Not running on NT\n");
67 return FALSE;
68 }
69
70 NTDLL_GET_PROC(RtlDowncaseUnicodeString);
71 NTDLL_GET_PROC(NtQuerySystemInformation);
72 NTDLL_GET_PROC(NtPowerInformation);
73 NTDLL_GET_PROC(NtQueryInformationProcess);
74 NTDLL_GET_PROC(NtQueryInformationThread);
75 NTDLL_GET_PROC(NtSetInformationProcess);
76 NTDLL_GET_PROC(NtSetInformationThread);
77 NTDLL_GET_PROC(NtReadVirtualMemory);
78 NTDLL_GET_PROC(NtQueryVirtualMemory);
79 NTDLL_GET_PROC(NtClose);
80 NTDLL_GET_PROC(NtCreateSection);
81 NTDLL_GET_PROC(NtMapViewOfSection);
82 NTDLL_GET_PROC(NtUnmapViewOfSection);
83
84 /* not present before XP */
85 pNtGetCurrentProcessorNumber = (void *) GetProcAddress(hntdll, "NtGetCurrentProcessorNumber");
86
87 pIsWow64Process = (void *)GetProcAddress(hkernel32, "IsWow64Process");
88 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
89
90 /* starting with Win7 */
91 pNtQuerySystemInformationEx = (void *) GetProcAddress(hntdll, "NtQuerySystemInformationEx");
92 if (!pNtQuerySystemInformationEx)
93 win_skip("NtQuerySystemInformationEx() is not supported, some tests will be skipped.\n");
94
95 pGetLogicalProcessorInformationEx = (void *) GetProcAddress(hkernel32, "GetLogicalProcessorInformationEx");
96
97 return TRUE;
98 }
99
100 static void test_query_basic(void)
101 {
102 NTSTATUS status;
103 ULONG ReturnLength;
104 SYSTEM_BASIC_INFORMATION sbi;
105
106 /* This test also covers some basic parameter testing that should be the same for
107 * every information class
108 */
109
110 /* Use a nonexistent info class */
111 trace("Check nonexistent info class\n");
112 status = pNtQuerySystemInformation(-1, NULL, 0, NULL);
113 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
114 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status);
115
116 /* Use an existing class but with a zero-length buffer */
117 trace("Check zero-length buffer\n");
118 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, 0, NULL);
119 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
120
121 /* Use an existing class, correct length but no SystemInformation buffer */
122 trace("Check no SystemInformation buffer\n");
123 status = pNtQuerySystemInformation(SystemBasicInformation, NULL, sizeof(sbi), NULL);
124 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER /* vista */,
125 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got %08x\n", status);
126
127 /* Use an existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
128 trace("Check no ReturnLength pointer\n");
129 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
130 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
131
132 /* Check a too large buffer size */
133 trace("Check a too large buffer size\n");
134 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi) * 2, &ReturnLength);
135 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
136
137 /* Finally some correct calls */
138 trace("Check with correct parameters\n");
139 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
140 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
141 ok( sizeof(sbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
142
143 /* Check if we have some return values */
144 trace("Number of Processors : %d\n", sbi.NumberOfProcessors);
145 ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n", sbi.NumberOfProcessors);
146 }
147
148 static void test_query_cpu(void)
149 {
150 DWORD status;
151 ULONG ReturnLength;
152 SYSTEM_CPU_INFORMATION sci;
153
154 status = pNtQuerySystemInformation(SystemCpuInformation, &sci, sizeof(sci), &ReturnLength);
155 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
156 ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
157
158 /* Check if we have some return values */
159 trace("Processor FeatureSet : %08x\n", sci.FeatureSet);
160 ok( sci.FeatureSet != 0, "Expected some features for this processor, got %08x\n", sci.FeatureSet);
161 }
162
163 static void test_query_performance(void)
164 {
165 NTSTATUS status;
166 ULONG ReturnLength;
167 ULONGLONG buffer[sizeof(SYSTEM_PERFORMANCE_INFORMATION)/sizeof(ULONGLONG) + 5];
168 DWORD size = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
169
170 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, 0, &ReturnLength);
171 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
172
173 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
174 if (status == STATUS_INFO_LENGTH_MISMATCH && is_wow64)
175 {
176 /* size is larger on wow64 under w2k8/win7 */
177 size += 16;
178 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
179 }
180 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
181 ok( ReturnLength == size, "Inconsistent length %d\n", ReturnLength);
182
183 status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size + 2, &ReturnLength);
184 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
185 ok( ReturnLength == size || ReturnLength == size + 2,
186 "Inconsistent length %d\n", ReturnLength);
187
188 /* Not return values yet, as struct members are unknown */
189 }
190
191 static void test_query_timeofday(void)
192 {
193 NTSTATUS status;
194 ULONG ReturnLength;
195
196 /* Copy of our winternl.h structure turned into a private one */
197 typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE {
198 LARGE_INTEGER liKeBootTime;
199 LARGE_INTEGER liKeSystemTime;
200 LARGE_INTEGER liExpTimeZoneBias;
201 ULONG uCurrentTimeZoneId;
202 DWORD dwUnknown1[5];
203 } SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE;
204
205 SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti;
206
207 /* The struct size for NT (32 bytes) and Win2K/XP (48 bytes) differ.
208 *
209 * Windows 2000 and XP return STATUS_INFO_LENGTH_MISMATCH if the given buffer size is greater
210 * then 48 and 0 otherwise
211 * Windows NT returns STATUS_INFO_LENGTH_MISMATCH when the given buffer size is not correct
212 * and 0 otherwise
213 *
214 * Windows 2000 and XP copy the given buffer size into the provided buffer, if the return code is STATUS_SUCCESS
215 * NT only fills the buffer if the return code is STATUS_SUCCESS
216 *
217 */
218
219 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
220
221 if (status == STATUS_INFO_LENGTH_MISMATCH)
222 {
223 trace("Windows version is NT, we have to cater for differences with W2K/WinXP\n");
224
225 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
226 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
227 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
228
229 sti.uCurrentTimeZoneId = 0xdeadbeef;
230 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 28, &ReturnLength);
231 ok(status == STATUS_SUCCESS || broken(status == STATUS_INFO_LENGTH_MISMATCH /* NT4 */), "Expected STATUS_SUCCESS, got %08x\n", status);
232 ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
233
234 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
235 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
236 ok( 32 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
237 }
238 else
239 {
240 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
241 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
242 ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
243
244 sti.uCurrentTimeZoneId = 0xdeadbeef;
245 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 24, &ReturnLength);
246 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
247 ok( 24 == ReturnLength, "ReturnLength should be 24, it is (%d)\n", ReturnLength);
248 ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
249
250 sti.uCurrentTimeZoneId = 0xdeadbeef;
251 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
252 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
253 ok( 32 == ReturnLength, "ReturnLength should be 32, it is (%d)\n", ReturnLength);
254 ok( 0xdeadbeef != sti.uCurrentTimeZoneId, "Buffer should have been partially filled\n");
255
256 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 49, &ReturnLength);
257 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
258 ok( ReturnLength == 0 || ReturnLength == sizeof(sti) /* vista */,
259 "ReturnLength should be 0, it is (%d)\n", ReturnLength);
260
261 status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
262 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
263 ok( sizeof(sti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
264 }
265
266 /* Check if we have some return values */
267 trace("uCurrentTimeZoneId : (%d)\n", sti.uCurrentTimeZoneId);
268 }
269
270 static void test_query_process(void)
271 {
272 NTSTATUS status;
273 DWORD last_pid;
274 ULONG ReturnLength;
275 int i = 0, k = 0;
276 BOOL is_nt = FALSE;
277 SYSTEM_BASIC_INFORMATION sbi;
278
279 /* Copy of our winternl.h structure turned into a private one */
280 typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE {
281 ULONG NextEntryOffset;
282 DWORD dwThreadCount;
283 DWORD dwUnknown1[6];
284 FILETIME ftCreationTime;
285 FILETIME ftUserTime;
286 FILETIME ftKernelTime;
287 UNICODE_STRING ProcessName;
288 DWORD dwBasePriority;
289 HANDLE UniqueProcessId;
290 HANDLE ParentProcessId;
291 ULONG HandleCount;
292 DWORD dwUnknown3;
293 DWORD dwUnknown4;
294 VM_COUNTERS vmCounters;
295 IO_COUNTERS ioCounters;
296 SYSTEM_THREAD_INFORMATION ti[1];
297 } SYSTEM_PROCESS_INFORMATION_PRIVATE;
298
299 ULONG SystemInformationLength = sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE);
300 SYSTEM_PROCESS_INFORMATION_PRIVATE *spi, *spi_buf = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
301
302 /* test ReturnLength */
303 ReturnLength = 0;
304 status = pNtQuerySystemInformation(SystemProcessInformation, NULL, 0, &ReturnLength);
305 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH got %08x\n", status);
306 ok( ReturnLength > 0 || broken(ReturnLength == 0) /* NT4, Win2K */,
307 "Expected a ReturnLength to show the needed length\n");
308
309 /* W2K3 and later returns the needed length, the rest returns 0, so we have to loop */
310 for (;;)
311 {
312 status = pNtQuerySystemInformation(SystemProcessInformation, spi_buf, SystemInformationLength, &ReturnLength);
313
314 if (status != STATUS_INFO_LENGTH_MISMATCH) break;
315
316 spi_buf = HeapReAlloc(GetProcessHeap(), 0, spi_buf , SystemInformationLength *= 2);
317 }
318 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
319 spi = spi_buf;
320
321 /* Get the first NextEntryOffset, from this we can deduce the OS version we're running
322 *
323 * W2K/WinXP/W2K3:
324 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
325 * NT:
326 * NextEntryOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
327 * Wine (with every windows version):
328 * NextEntryOffset for a process is 0 if just this test is running
329 * NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) +
330 * ProcessName.MaximumLength
331 * if more wine processes are running
332 *
333 * Note : On windows the first process is in fact the Idle 'process' with a thread for every processor
334 */
335
336 pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
337
338 is_nt = ( spi->NextEntryOffset - (sbi.NumberOfProcessors * sizeof(SYSTEM_THREAD_INFORMATION)) == 136);
339
340 if (is_nt) win_skip("Windows version is NT, we will skip thread tests\n");
341
342 /* Check if we have some return values
343 *
344 * On windows there will be several processes running (Including the always present Idle and System)
345 * On wine we only have one (if this test is the only wine process running)
346 */
347
348 /* Loop through the processes */
349
350 for (;;)
351 {
352 i++;
353
354 last_pid = (DWORD_PTR)spi->UniqueProcessId;
355
356 ok( spi->dwThreadCount > 0, "Expected some threads for this process, got 0\n");
357
358 /* Loop through the threads, skip NT4 for now */
359
360 if (!is_nt)
361 {
362 DWORD j;
363 for ( j = 0; j < spi->dwThreadCount; j++)
364 {
365 k++;
366 ok ( spi->ti[j].ClientId.UniqueProcess == spi->UniqueProcessId,
367 "The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
368 spi->ti[j].ClientId.UniqueProcess, spi->UniqueProcessId);
369 }
370 }
371
372 if (!spi->NextEntryOffset) break;
373
374 one_before_last_pid = last_pid;
375
376 spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->NextEntryOffset);
377 }
378 trace("Total number of running processes : %d\n", i);
379 if (!is_nt) trace("Total number of running threads : %d\n", k);
380
381 if (one_before_last_pid == 0) one_before_last_pid = last_pid;
382
383 HeapFree( GetProcessHeap(), 0, spi_buf);
384 }
385
386 static void test_query_procperf(void)
387 {
388 NTSTATUS status;
389 ULONG ReturnLength;
390 ULONG NeededLength;
391 SYSTEM_BASIC_INFORMATION sbi;
392 SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
393
394 /* Find out the number of processors */
395 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
396 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
397 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
398
399 sppi = HeapAlloc(GetProcessHeap(), 0, NeededLength);
400
401 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, 0, &ReturnLength);
402 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
403
404 /* Try it for 1 processor */
405 sppi->KernelTime.QuadPart = 0xdeaddead;
406 sppi->UserTime.QuadPart = 0xdeaddead;
407 sppi->IdleTime.QuadPart = 0xdeaddead;
408 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi,
409 sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), &ReturnLength);
410 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
411 ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
412 "Inconsistent length %d\n", ReturnLength);
413 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
414 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
415 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
416
417 /* Try it for all processors */
418 sppi->KernelTime.QuadPart = 0xdeaddead;
419 sppi->UserTime.QuadPart = 0xdeaddead;
420 sppi->IdleTime.QuadPart = 0xdeaddead;
421 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength, &ReturnLength);
422 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
423 ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
424 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
425 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
426 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
427
428 /* A too large given buffer size */
429 sppi = HeapReAlloc(GetProcessHeap(), 0, sppi , NeededLength + 2);
430 sppi->KernelTime.QuadPart = 0xdeaddead;
431 sppi->UserTime.QuadPart = 0xdeaddead;
432 sppi->IdleTime.QuadPart = 0xdeaddead;
433 status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength + 2, &ReturnLength);
434 ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH /* vista */,
435 "Expected STATUS_SUCCESS or STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
436 ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
437 if (status == STATUS_SUCCESS)
438 {
439 ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
440 ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
441 ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
442 }
443 else /* vista and 2008 */
444 {
445 ok (sppi->KernelTime.QuadPart == 0xdeaddead, "KernelTime changed\n");
446 ok (sppi->UserTime.QuadPart == 0xdeaddead, "UserTime changed\n");
447 ok (sppi->IdleTime.QuadPart == 0xdeaddead, "IdleTime changed\n");
448 }
449
450 HeapFree( GetProcessHeap(), 0, sppi);
451 }
452
453 static void test_query_module(void)
454 {
455 NTSTATUS status;
456 ULONG ReturnLength;
457 ULONG ModuleCount, i;
458
459 ULONG SystemInformationLength = sizeof(SYSTEM_MODULE_INFORMATION);
460 SYSTEM_MODULE_INFORMATION* smi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
461 SYSTEM_MODULE* sm;
462
463 /* Request the needed length */
464 status = pNtQuerySystemInformation(SystemModuleInformation, smi, 0, &ReturnLength);
465 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
466 ok( ReturnLength > 0, "Expected a ReturnLength to show the needed length\n");
467
468 SystemInformationLength = ReturnLength;
469 smi = HeapReAlloc(GetProcessHeap(), 0, smi , SystemInformationLength);
470 status = pNtQuerySystemInformation(SystemModuleInformation, smi, SystemInformationLength, &ReturnLength);
471 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
472
473 ModuleCount = smi->ModulesCount;
474 sm = &smi->Modules[0];
475 /* our implementation is a stub for now */
476 ok( ModuleCount > 0, "Expected some modules to be loaded\n");
477
478 /* Loop through all the modules/drivers, Wine doesn't get here (yet) */
479 for (i = 0; i < ModuleCount ; i++)
480 {
481 ok( i == sm->Id, "Id (%d) should have matched %u\n", sm->Id, i);
482 sm++;
483 }
484
485 HeapFree( GetProcessHeap(), 0, smi);
486 }
487
488 static void test_query_handle(void)
489 {
490 NTSTATUS status;
491 ULONG ExpectedLength, ReturnLength;
492 ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
493 SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
494 HANDLE EventHandle;
495 BOOL found;
496 INT i;
497
498 EventHandle = CreateEventA(NULL, FALSE, FALSE, NULL);
499 ok( EventHandle != NULL, "CreateEventA failed %u\n", GetLastError() );
500
501 /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
502 ReturnLength = 0xdeadbeef;
503 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
504 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
505 ok( ReturnLength != 0xdeadbeef, "Expected valid ReturnLength\n" );
506
507 SystemInformationLength = ReturnLength;
508 shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
509 memset(shi, 0x55, SystemInformationLength);
510
511 ReturnLength = 0xdeadbeef;
512 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
513 while (status == STATUS_INFO_LENGTH_MISMATCH) /* Vista / 2008 */
514 {
515 SystemInformationLength *= 2;
516 shi = HeapReAlloc(GetProcessHeap(), 0, shi, SystemInformationLength);
517 memset(shi, 0x55, SystemInformationLength);
518 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
519 }
520 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
521 ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handle[shi->Count]);
522 ok( ReturnLength == ExpectedLength || broken(ReturnLength == ExpectedLength - sizeof(DWORD)), /* Vista / 2008 */
523 "Expected length %u, got %u\n", ExpectedLength, ReturnLength );
524 ok( shi->Count > 1, "Expected more than 1 handle, got %u\n", shi->Count );
525 ok( shi->Handle[1].HandleValue != 0x5555 || broken( shi->Handle[1].HandleValue == 0x5555 ), /* Vista / 2008 */
526 "Uninitialized second handle\n" );
527 if (shi->Handle[1].HandleValue == 0x5555)
528 {
529 win_skip("Skipping broken SYSTEM_HANDLE_INFORMATION\n");
530 CloseHandle(EventHandle);
531 goto done;
532 }
533
534 for (i = 0, found = FALSE; i < shi->Count && !found; i++)
535 found = (shi->Handle[i].OwnerPid == GetCurrentProcessId()) &&
536 ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
537 ok( found, "Expected to find event handle %p (pid %x) in handle list\n", EventHandle, GetCurrentProcessId() );
538
539 if (!found)
540 for (i = 0; i < shi->Count; i++)
541 trace( "%d: handle %x pid %x\n", i, shi->Handle[i].HandleValue, shi->Handle[i].OwnerPid );
542
543 CloseHandle(EventHandle);
544
545 ReturnLength = 0xdeadbeef;
546 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
547 while (status == STATUS_INFO_LENGTH_MISMATCH) /* Vista / 2008 */
548 {
549 SystemInformationLength *= 2;
550 shi = HeapReAlloc(GetProcessHeap(), 0, shi, SystemInformationLength);
551 status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
552 }
553 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
554 for (i = 0, found = FALSE; i < shi->Count && !found; i++)
555 found = (shi->Handle[i].OwnerPid == GetCurrentProcessId()) &&
556 ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
557 ok( !found, "Unexpectedly found event handle in handle list\n" );
558
559 status = pNtQuerySystemInformation(SystemHandleInformation, NULL, SystemInformationLength, &ReturnLength);
560 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status );
561
562 done:
563 HeapFree( GetProcessHeap(), 0, shi);
564 }
565
566 static void test_query_handle_ex(void)
567 {
568 NTSTATUS status;
569 ULONG ExpectedLength, ReturnLength;
570 ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION_EX);
571 SYSTEM_HANDLE_INFORMATION_EX* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
572 HANDLE EventHandle;
573 BOOL found;
574 INT i;
575
576 EventHandle = CreateEventA(NULL, FALSE, FALSE, NULL);
577 ok( EventHandle != NULL, "CreateEventA failed %u\n", GetLastError() );
578
579 ReturnLength = 0xdeadbeef;
580 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength);
581 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
582 ok( ReturnLength != 0xdeadbeef, "Expected valid ReturnLength\n" );
583
584 SystemInformationLength = ReturnLength;
585 shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
586 memset(shi, 0x55, SystemInformationLength);
587
588 ReturnLength = 0xdeadbeef;
589 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength);
590 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
591 ExpectedLength = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handle[shi->Count]);
592 ok( ReturnLength == ExpectedLength, "Expected length %u, got %u\n", ExpectedLength, ReturnLength );
593 ok( shi->Count > 1, "Expected more than 1 handle, got %u\n", (DWORD)shi->Count );
594
595 for (i = 0, found = FALSE; i < shi->Count && !found; i++)
596 found = (shi->Handle[i].UniqueProcessId == GetCurrentProcessId()) &&
597 ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
598 ok( found, "Expected to find event handle %p (pid %x) in handle list\n", EventHandle, GetCurrentProcessId() );
599
600 if (!found)
601 {
602 for (i = 0; i < shi->Count; i++)
603 trace( "%d: handle %x pid %x\n", i, (DWORD)shi->Handle[i].HandleValue, (DWORD)shi->Handle[i].UniqueProcessId );
604 }
605
606 CloseHandle(EventHandle);
607
608 ReturnLength = 0xdeadbeef;
609 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, shi, SystemInformationLength, &ReturnLength);
610 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status );
611 for (i = 0, found = FALSE; i < shi->Count && !found; i++)
612 found = (shi->Handle[i].UniqueProcessId == GetCurrentProcessId()) &&
613 ((HANDLE)(ULONG_PTR)shi->Handle[i].HandleValue == EventHandle);
614 ok( !found, "Unexpectedly found event handle in handle list\n" );
615
616 status = pNtQuerySystemInformation(SystemExtendedHandleInformation, NULL, SystemInformationLength, &ReturnLength);
617 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status );
618
619 HeapFree( GetProcessHeap(), 0, shi);
620 }
621
622 static void test_query_cache(void)
623 {
624 NTSTATUS status;
625 ULONG ReturnLength;
626 BYTE buffer[128];
627 SYSTEM_CACHE_INFORMATION *sci = (SYSTEM_CACHE_INFORMATION *) buffer;
628 ULONG expected;
629 INT i;
630
631 /* the large SYSTEM_CACHE_INFORMATION on WIN64 is not documented */
632 expected = sizeof(SYSTEM_CACHE_INFORMATION);
633 for (i = sizeof(buffer); i>= expected; i--)
634 {
635 ReturnLength = 0xdeadbeef;
636 status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
637 ok(!status && (ReturnLength == expected),
638 "%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i, status, ReturnLength, expected);
639 }
640
641 /* buffer too small for the full result.
642 Up to win7, the function succeeds with a partial result. */
643 status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
644 if (!status)
645 {
646 expected = offsetof(SYSTEM_CACHE_INFORMATION, MinimumWorkingSet);
647 for (; i>= expected; i--)
648 {
649 ReturnLength = 0xdeadbeef;
650 status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
651 ok(!status && (ReturnLength == expected),
652 "%d: got 0x%x and %u (expected STATUS_SUCCESS and %u)\n", i, status, ReturnLength, expected);
653 }
654 }
655
656 /* buffer too small for the result, this call will always fail */
657 ReturnLength = 0xdeadbeef;
658 status = pNtQuerySystemInformation(SystemCacheInformation, sci, i, &ReturnLength);
659 ok( status == STATUS_INFO_LENGTH_MISMATCH &&
660 ((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
661 "%d: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", i, status, ReturnLength, expected);
662
663 if (0) {
664 /* this crashes on some vista / win7 machines */
665 ReturnLength = 0xdeadbeef;
666 status = pNtQuerySystemInformation(SystemCacheInformation, sci, 0, &ReturnLength);
667 ok( status == STATUS_INFO_LENGTH_MISMATCH &&
668 ((ReturnLength == expected) || broken(!ReturnLength) || broken(ReturnLength == 0xfffffff0)),
669 "0: got 0x%x and %u (expected STATUS_INFO_LENGTH_MISMATCH and %u)\n", status, ReturnLength, expected);
670 }
671 }
672
673 static void test_query_interrupt(void)
674 {
675 NTSTATUS status;
676 ULONG ReturnLength;
677 ULONG NeededLength;
678 SYSTEM_BASIC_INFORMATION sbi;
679 SYSTEM_INTERRUPT_INFORMATION* sii;
680
681 /* Find out the number of processors */
682 status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
683 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
684 NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
685
686 sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
687
688 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, 0, &ReturnLength);
689 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
690
691 /* Try it for all processors */
692 status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
693 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
694
695 /* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
696 * No test added for this as it's highly unlikely that an app depends on this
697 */
698
699 HeapFree( GetProcessHeap(), 0, sii);
700 }
701
702 static void test_query_kerndebug(void)
703 {
704 NTSTATUS status;
705 ULONG ReturnLength;
706 SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi;
707
708 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, 0, &ReturnLength);
709 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
710
711 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi), &ReturnLength);
712 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
713 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
714
715 status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi) + 2, &ReturnLength);
716 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
717 ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
718 }
719
720 static void test_query_regquota(void)
721 {
722 NTSTATUS status;
723 ULONG ReturnLength;
724 SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
725
726 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, 0, &ReturnLength);
727 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
728
729 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi), &ReturnLength);
730 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
731 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
732
733 status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi) + 2, &ReturnLength);
734 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
735 ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
736 }
737
738 static void test_query_logicalproc(void)
739 {
740 NTSTATUS status;
741 ULONG len, i, proc_no;
742 SYSTEM_LOGICAL_PROCESSOR_INFORMATION *slpi;
743 SYSTEM_INFO si;
744
745 GetSystemInfo(&si);
746
747 status = pNtQuerySystemInformation(SystemLogicalProcessorInformation, NULL, 0, &len);
748 if(status == STATUS_INVALID_INFO_CLASS)
749 {
750 win_skip("SystemLogicalProcessorInformation is not supported\n");
751 return;
752 }
753 if(status == STATUS_NOT_IMPLEMENTED)
754 {
755 todo_wine ok(0, "SystemLogicalProcessorInformation is not implemented\n");
756 return;
757 }
758 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
759 ok(len%sizeof(*slpi) == 0, "Incorrect length %d\n", len);
760
761 slpi = HeapAlloc(GetProcessHeap(), 0, len);
762 status = pNtQuerySystemInformation(SystemLogicalProcessorInformation, slpi, len, &len);
763 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
764
765 proc_no = 0;
766 for(i=0; i<len/sizeof(*slpi); i++) {
767 switch(slpi[i].Relationship) {
768 case RelationProcessorCore:
769 /* Get number of logical processors */
770 for(; slpi[i].ProcessorMask; slpi[i].ProcessorMask /= 2)
771 proc_no += slpi[i].ProcessorMask%2;
772 break;
773 default:
774 break;
775 }
776 }
777 ok(proc_no > 0, "No processors were found\n");
778 if(si.dwNumberOfProcessors <= 32)
779 ok(proc_no == si.dwNumberOfProcessors, "Incorrect number of logical processors: %d, expected %d\n",
780 proc_no, si.dwNumberOfProcessors);
781
782 HeapFree(GetProcessHeap(), 0, slpi);
783 }
784
785 static void test_query_logicalprocex(void)
786 {
787 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *infoex, *infoex2;
788 DWORD relationship, len2, len;
789 NTSTATUS status;
790 BOOL ret;
791
792 if (!pNtQuerySystemInformationEx)
793 return;
794
795 len = 0;
796 relationship = RelationProcessorCore;
797 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len);
798 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08x\n", status);
799 ok(len > 0, "got %u\n", len);
800
801 len = 0;
802 relationship = RelationAll;
803 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), NULL, 0, &len);
804 ok(status == STATUS_INFO_LENGTH_MISMATCH, "got 0x%08x\n", status);
805 ok(len > 0, "got %u\n", len);
806
807 len2 = 0;
808 ret = pGetLogicalProcessorInformationEx(RelationAll, NULL, &len2);
809 ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d, error %d\n", ret, GetLastError());
810 ok(len == len2, "got %u, expected %u\n", len2, len);
811
812 if (len && len == len2) {
813 int j, i;
814
815 infoex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
816 infoex2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
817
818 status = pNtQuerySystemInformationEx(SystemLogicalProcessorInformationEx, &relationship, sizeof(relationship), infoex, len, &len);
819 ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
820
821 ret = pGetLogicalProcessorInformationEx(RelationAll, infoex2, &len2);
822 ok(ret, "got %d, error %d\n", ret, GetLastError());
823 ok(!memcmp(infoex, infoex2, len), "returned info data mismatch\n");
824
825 for(i = 0; status == STATUS_SUCCESS && i < len; ){
826 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *ex = (void*)(((char *)infoex) + i);
827
828 ok(ex->Relationship >= RelationProcessorCore && ex->Relationship <= RelationGroup,
829 "Got invalid relationship value: 0x%x\n", ex->Relationship);
830 if (!ex->Size)
831 {
832 ok(0, "got infoex[%u].Size=0\n", i);
833 break;
834 }
835
836 trace("infoex[%u].Size: %u\n", i, ex->Size);
837 switch(ex->Relationship){
838 case RelationProcessorCore:
839 case RelationProcessorPackage:
840 trace("infoex[%u].Relationship: 0x%x (Core == 0x0 or Package == 0x3)\n", i, ex->Relationship);
841 trace("infoex[%u].Processor.Flags: 0x%x\n", i, ex->Processor.Flags);
842 #ifndef __REACTOS__
843 trace("infoex[%u].Processor.EfficiencyClass: 0x%x\n", i, ex->Processor.EfficiencyClass);
844 #endif
845 trace("infoex[%u].Processor.GroupCount: 0x%x\n", i, ex->Processor.GroupCount);
846 for(j = 0; j < ex->Processor.GroupCount; ++j){
847 trace("infoex[%u].Processor.GroupMask[%u].Mask: 0x%lx\n", i, j, ex->Processor.GroupMask[j].Mask);
848 trace("infoex[%u].Processor.GroupMask[%u].Group: 0x%x\n", i, j, ex->Processor.GroupMask[j].Group);
849 }
850 break;
851 case RelationNumaNode:
852 trace("infoex[%u].Relationship: 0x%x (NumaNode)\n", i, ex->Relationship);
853 trace("infoex[%u].NumaNode.NodeNumber: 0x%x\n", i, ex->NumaNode.NodeNumber);
854 trace("infoex[%u].NumaNode.GroupMask.Mask: 0x%lx\n", i, ex->NumaNode.GroupMask.Mask);
855 trace("infoex[%u].NumaNode.GroupMask.Group: 0x%x\n", i, ex->NumaNode.GroupMask.Group);
856 break;
857 case RelationCache:
858 trace("infoex[%u].Relationship: 0x%x (Cache)\n", i, ex->Relationship);
859 trace("infoex[%u].Cache.Level: 0x%x\n", i, ex->Cache.Level);
860 trace("infoex[%u].Cache.Associativity: 0x%x\n", i, ex->Cache.Associativity);
861 trace("infoex[%u].Cache.LineSize: 0x%x\n", i, ex->Cache.LineSize);
862 trace("infoex[%u].Cache.CacheSize: 0x%x\n", i, ex->Cache.CacheSize);
863 trace("infoex[%u].Cache.Type: 0x%x\n", i, ex->Cache.Type);
864 trace("infoex[%u].Cache.GroupMask.Mask: 0x%lx\n", i, ex->Cache.GroupMask.Mask);
865 trace("infoex[%u].Cache.GroupMask.Group: 0x%x\n", i, ex->Cache.GroupMask.Group);
866 break;
867 case RelationGroup:
868 trace("infoex[%u].Relationship: 0x%x (Group)\n", i, ex->Relationship);
869 trace("infoex[%u].Group.MaximumGroupCount: 0x%x\n", i, ex->Group.MaximumGroupCount);
870 trace("infoex[%u].Group.ActiveGroupCount: 0x%x\n", i, ex->Group.ActiveGroupCount);
871 for(j = 0; j < ex->Group.ActiveGroupCount; ++j){
872 trace("infoex[%u].Group.GroupInfo[%u].MaximumProcessorCount: 0x%x\n", i, j, ex->Group.GroupInfo[j].MaximumProcessorCount);
873 trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorCount: 0x%x\n", i, j, ex->Group.GroupInfo[j].ActiveProcessorCount);
874 trace("infoex[%u].Group.GroupInfo[%u].ActiveProcessorMask: 0x%lx\n", i, j, ex->Group.GroupInfo[j].ActiveProcessorMask);
875 }
876 break;
877 default:
878 break;
879 }
880
881 i += ex->Size;
882 }
883
884 HeapFree(GetProcessHeap(), 0, infoex);
885 HeapFree(GetProcessHeap(), 0, infoex2);
886 }
887 }
888
889 static void test_query_processor_power_info(void)
890 {
891 NTSTATUS status;
892 PROCESSOR_POWER_INFORMATION* ppi;
893 ULONG size;
894 SYSTEM_INFO si;
895 int i;
896
897 GetSystemInfo(&si);
898 size = si.dwNumberOfProcessors * sizeof(PROCESSOR_POWER_INFORMATION);
899 ppi = HeapAlloc(GetProcessHeap(), 0, size);
900
901 /* If size < (sizeof(PROCESSOR_POWER_INFORMATION) * NumberOfProcessors), Win7 returns
902 * STATUS_BUFFER_TOO_SMALL. WinXP returns STATUS_SUCCESS for any value of size. It copies as
903 * many whole PROCESSOR_POWER_INFORMATION structures that there is room for. Even if there is
904 * not enough room for one structure, WinXP still returns STATUS_SUCCESS having done nothing.
905 *
906 * If ppi == NULL, Win7 returns STATUS_INVALID_PARAMETER while WinXP returns STATUS_SUCCESS
907 * and does nothing.
908 *
909 * The same behavior is seen with CallNtPowerInformation (in powrprof.dll).
910 */
911
912 if (si.dwNumberOfProcessors > 1)
913 {
914 for(i = 0; i < si.dwNumberOfProcessors; i++)
915 ppi[i].Number = 0xDEADBEEF;
916
917 /* Call with a buffer size that is large enough to hold at least one but not large
918 * enough to hold them all. This will be STATUS_SUCCESS on WinXP but not on Win7 */
919 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, size - sizeof(PROCESSOR_POWER_INFORMATION));
920 if (status == STATUS_SUCCESS)
921 {
922 /* lax version found on older Windows like WinXP */
923 ok( (ppi[si.dwNumberOfProcessors - 2].Number != 0xDEADBEEF) &&
924 (ppi[si.dwNumberOfProcessors - 1].Number == 0xDEADBEEF),
925 "Expected all but the last record to be overwritten.\n");
926
927 status = pNtPowerInformation(ProcessorInformation, 0, 0, 0, size);
928 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
929
930 for(i = 0; i < si.dwNumberOfProcessors; i++)
931 ppi[i].Number = 0xDEADBEEF;
932 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, sizeof(PROCESSOR_POWER_INFORMATION) - 1);
933 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
934 for(i = 0; i < si.dwNumberOfProcessors; i++)
935 if (ppi[i].Number != 0xDEADBEEF) break;
936 ok( i == si.dwNumberOfProcessors, "Expected untouched buffer\n");
937 }
938 else
939 {
940 /* picky version found on newer Windows like Win7 */
941 ok( ppi[1].Number == 0xDEADBEEF, "Expected untouched buffer.\n");
942 ok( status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status);
943
944 status = pNtPowerInformation(ProcessorInformation, 0, 0, 0, size);
945 ok( status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER, "Got %08x\n", status);
946
947 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, 0);
948 ok( status == STATUS_BUFFER_TOO_SMALL || status == STATUS_INVALID_PARAMETER, "Got %08x\n", status);
949 }
950 }
951 else
952 {
953 skip("Test needs more than one processor.\n");
954 }
955
956 status = pNtPowerInformation(ProcessorInformation, 0, 0, ppi, size);
957 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
958
959 HeapFree(GetProcessHeap(), 0, ppi);
960 }
961
962 static void test_query_process_wow64(void)
963 {
964 NTSTATUS status;
965 ULONG ReturnLength;
966 ULONG_PTR pbi[2], dummy;
967
968 memset(&dummy, 0xcc, sizeof(dummy));
969
970 /* Do not give a handle and buffer */
971 status = pNtQueryInformationProcess(NULL, ProcessWow64Information, NULL, 0, NULL);
972 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
973
974 /* Use a correct info class and buffer size, but still no handle and buffer */
975 status = pNtQueryInformationProcess(NULL, ProcessWow64Information, NULL, sizeof(ULONG_PTR), NULL);
976 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
977 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE, got %08x\n", status);
978
979 /* Use a correct info class, buffer size and handle, but no buffer */
980 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, NULL, sizeof(ULONG_PTR), NULL);
981 ok( status == STATUS_ACCESS_VIOLATION , "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
982
983 /* Use a correct info class, buffer and buffer size, but no handle */
984 pbi[0] = pbi[1] = dummy;
985 status = pNtQueryInformationProcess(NULL, ProcessWow64Information, pbi, sizeof(ULONG_PTR), NULL);
986 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
987 ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
988 ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
989
990 /* Use a greater buffer size */
991 pbi[0] = pbi[1] = dummy;
992 status = pNtQueryInformationProcess(NULL, ProcessWow64Information, pbi, sizeof(ULONG_PTR) + 1, NULL);
993 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
994 ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
995 ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
996
997 /* Use no ReturnLength */
998 pbi[0] = pbi[1] = dummy;
999 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR), NULL);
1000 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1001 trace( "Platform is_wow64 %d, ProcessInformation of ProcessWow64Information %lx\n", is_wow64, pbi[0]);
1002 ok( is_wow64 == (pbi[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64, pbi[0]);
1003 ok( pbi[0] != dummy, "pbi[0] %lx\n", pbi[0]);
1004 ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
1005 /* Test written size on 64 bit by checking high 32 bit buffer */
1006 if (sizeof(ULONG_PTR) > sizeof(DWORD))
1007 {
1008 DWORD *ptr = (DWORD *)pbi;
1009 ok( ptr[1] != (DWORD)dummy, "ptr[1] unchanged!\n");
1010 }
1011
1012 /* Finally some correct calls */
1013 pbi[0] = pbi[1] = dummy;
1014 ReturnLength = 0xdeadbeef;
1015 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR), &ReturnLength);
1016 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1017 ok( is_wow64 == (pbi[0] != 0), "is_wow64 %x, pbi[0] %lx\n", is_wow64, pbi[0]);
1018 ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
1019 ok( ReturnLength == sizeof(ULONG_PTR), "Inconsistent length %d\n", ReturnLength);
1020
1021 /* Everything is correct except a too small buffer size */
1022 pbi[0] = pbi[1] = dummy;
1023 ReturnLength = 0xdeadbeef;
1024 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR) - 1, &ReturnLength);
1025 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1026 ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
1027 ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
1028 todo_wine ok( ReturnLength == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", ReturnLength);
1029
1030 /* Everything is correct except a too large buffer size */
1031 pbi[0] = pbi[1] = dummy;
1032 ReturnLength = 0xdeadbeef;
1033 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessWow64Information, pbi, sizeof(ULONG_PTR) + 1, &ReturnLength);
1034 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1035 ok( pbi[0] == dummy, "pbi[0] changed to %lx\n", pbi[0]);
1036 ok( pbi[1] == dummy, "pbi[1] changed to %lx\n", pbi[1]);
1037 todo_wine ok( ReturnLength == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", ReturnLength);
1038 }
1039
1040 static void test_query_process_basic(void)
1041 {
1042 NTSTATUS status;
1043 ULONG ReturnLength;
1044
1045 typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE {
1046 DWORD_PTR ExitStatus;
1047 PPEB PebBaseAddress;
1048 DWORD_PTR AffinityMask;
1049 DWORD_PTR BasePriority;
1050 ULONG_PTR UniqueProcessId;
1051 ULONG_PTR InheritedFromUniqueProcessId;
1052 } PROCESS_BASIC_INFORMATION_PRIVATE;
1053
1054 PROCESS_BASIC_INFORMATION_PRIVATE pbi;
1055
1056 /* This test also covers some basic parameter testing that should be the same for
1057 * every information class
1058 */
1059
1060 /* Use a nonexistent info class */
1061 trace("Check nonexistent info class\n");
1062 status = pNtQueryInformationProcess(NULL, -1, NULL, 0, NULL);
1063 ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
1064 "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status);
1065
1066 /* Do not give a handle and buffer */
1067 trace("Check NULL handle and buffer and zero-length buffersize\n");
1068 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, 0, NULL);
1069 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1070
1071 /* Use a correct info class and buffer size, but still no handle and buffer */
1072 trace("Check NULL handle and buffer\n");
1073 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, sizeof(pbi), NULL);
1074 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1075 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
1076
1077 /* Use a correct info class and buffer size, but still no handle */
1078 trace("Check NULL handle\n");
1079 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
1080 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1081
1082 /* Use a greater buffer size */
1083 trace("Check NULL handle and too large buffersize\n");
1084 status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi) * 2, NULL);
1085 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1086
1087 /* Use no ReturnLength */
1088 trace("Check NULL ReturnLength\n");
1089 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
1090 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1091
1092 /* Finally some correct calls */
1093 trace("Check with correct parameters\n");
1094 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &ReturnLength);
1095 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1096 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1097
1098 /* Everything is correct except a too large buffersize */
1099 trace("Too large buffersize\n");
1100 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi) * 2, &ReturnLength);
1101 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1102 ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1103
1104 /* Check if we have some return values */
1105 trace("ProcessID : %lx\n", pbi.UniqueProcessId);
1106 ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
1107 }
1108
1109 static void dump_vm_counters(const char *header, const VM_COUNTERS *pvi)
1110 {
1111 trace("%s:\n", header);
1112 trace("PeakVirtualSize : %lu\n", pvi->PeakVirtualSize);
1113 trace("VirtualSize : %lu\n", pvi->VirtualSize);
1114 trace("PageFaultCount : %u\n", pvi->PageFaultCount);
1115 trace("PeakWorkingSetSize : %lu\n", pvi->PeakWorkingSetSize);
1116 trace("WorkingSetSize : %lu\n", pvi->WorkingSetSize);
1117 trace("QuotaPeakPagedPoolUsage : %lu\n", pvi->QuotaPeakPagedPoolUsage);
1118 trace("QuotaPagedPoolUsage : %lu\n", pvi->QuotaPagedPoolUsage);
1119 trace("QuotaPeakNonPagePoolUsage : %lu\n", pvi->QuotaPeakNonPagedPoolUsage);
1120 trace("QuotaNonPagePoolUsage : %lu\n", pvi->QuotaNonPagedPoolUsage);
1121 trace("PagefileUsage : %lu\n", pvi->PagefileUsage);
1122 trace("PeakPagefileUsage : %lu\n", pvi->PeakPagefileUsage);
1123 }
1124
1125 static void test_query_process_vm(void)
1126 {
1127 NTSTATUS status;
1128 ULONG ReturnLength;
1129 VM_COUNTERS pvi;
1130 ULONG old_size = FIELD_OFFSET(VM_COUNTERS,PrivatePageCount);
1131 HANDLE process;
1132 SIZE_T prev_size;
1133 const SIZE_T alloc_size = 16 * 1024 * 1024;
1134 void *ptr;
1135
1136 status = pNtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
1137 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1138 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
1139
1140 status = pNtQueryInformationProcess(NULL, ProcessVmCounters, &pvi, old_size, NULL);
1141 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1142
1143 /* Windows XP and W2K3 will report success for a size of 44 AND 48 !
1144 Windows W2K will only report success for 44.
1145 For now we only care for 44, which is FIELD_OFFSET(VM_COUNTERS,PrivatePageCount))
1146 */
1147
1148 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 24, &ReturnLength);
1149 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1150
1151 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, old_size, &ReturnLength);
1152 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1153 ok( old_size == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1154
1155 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 46, &ReturnLength);
1156 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1157 ok( ReturnLength == old_size || ReturnLength == sizeof(pvi), "Inconsistent length %d\n", ReturnLength);
1158
1159 /* Check if we have some return values */
1160 dump_vm_counters("VM counters for GetCurrentProcess", &pvi);
1161 ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
1162 ok( pvi.PagefileUsage > 0, "Expected a PagefileUsage > 0\n");
1163
1164 process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
1165 status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1166 ok( status == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED, got %08x\n", status);
1167 CloseHandle(process);
1168
1169 process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, GetCurrentProcessId());
1170 status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1171 ok( status == STATUS_SUCCESS || broken(!process) /* XP */, "Expected STATUS_SUCCESS, got %08x\n", status);
1172 CloseHandle(process);
1173
1174 memset(&pvi, 0, sizeof(pvi));
1175 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
1176 status = pNtQueryInformationProcess(process, ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1177 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1178
1179 /* Check if we have some return values */
1180 dump_vm_counters("VM counters for GetCurrentProcessId", &pvi);
1181 ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
1182 ok( pvi.PagefileUsage > 0, "Expected a PagefileUsage > 0\n");
1183
1184 CloseHandle(process);
1185
1186 /* Check if we have real counters */
1187 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1188 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1189 prev_size = pvi.VirtualSize;
1190 if (winetest_debug > 1)
1191 dump_vm_counters("VM counters before VirtualAlloc", &pvi);
1192 ptr = VirtualAlloc(NULL, alloc_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
1193 ok( ptr != NULL, "VirtualAlloc failed, err %u\n", GetLastError());
1194 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1195 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1196 if (winetest_debug > 1)
1197 dump_vm_counters("VM counters after VirtualAlloc", &pvi);
1198 todo_wine ok( pvi.VirtualSize >= prev_size + alloc_size,
1199 "Expected to be greater than %lu, got %lu\n", prev_size + alloc_size, pvi.VirtualSize);
1200 VirtualFree( ptr, 0, MEM_RELEASE);
1201
1202 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1203 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1204 prev_size = pvi.VirtualSize;
1205 if (winetest_debug > 1)
1206 dump_vm_counters("VM counters before VirtualAlloc", &pvi);
1207 ptr = VirtualAlloc(NULL, alloc_size, MEM_RESERVE, PAGE_READWRITE);
1208 ok( ptr != NULL, "VirtualAlloc failed, err %u\n", GetLastError());
1209 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1210 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1211 if (winetest_debug > 1)
1212 dump_vm_counters("VM counters after VirtualAlloc(MEM_RESERVE)", &pvi);
1213 todo_wine ok( pvi.VirtualSize >= prev_size + alloc_size,
1214 "Expected to be greater than %lu, got %lu\n", prev_size + alloc_size, pvi.VirtualSize);
1215 prev_size = pvi.VirtualSize;
1216
1217 ptr = VirtualAlloc(ptr, alloc_size, MEM_COMMIT, PAGE_READWRITE);
1218 ok( ptr != NULL, "VirtualAlloc failed, err %u\n", GetLastError());
1219 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessVmCounters, &pvi, sizeof(pvi), NULL);
1220 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1221 if (winetest_debug > 1)
1222 dump_vm_counters("VM counters after VirtualAlloc(MEM_COMMIT)", &pvi);
1223 ok( pvi.VirtualSize == prev_size,
1224 "Expected to equal to %lu, got %lu\n", prev_size, pvi.VirtualSize);
1225 VirtualFree( ptr, 0, MEM_RELEASE);
1226 }
1227
1228 static void test_query_process_io(void)
1229 {
1230 NTSTATUS status;
1231 ULONG ReturnLength;
1232 IO_COUNTERS pii;
1233
1234 /* NT4 doesn't support this information class, so check for it */
1235 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
1236 if (status == STATUS_NOT_SUPPORTED)
1237 {
1238 win_skip("ProcessIoCounters information class is not supported\n");
1239 return;
1240 }
1241
1242 status = pNtQueryInformationProcess(NULL, ProcessIoCounters, NULL, sizeof(pii), NULL);
1243 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1244 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
1245
1246 status = pNtQueryInformationProcess(NULL, ProcessIoCounters, &pii, sizeof(pii), NULL);
1247 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1248
1249 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, 24, &ReturnLength);
1250 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1251
1252 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
1253 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1254 ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1255
1256 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii) * 2, &ReturnLength);
1257 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1258 ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1259
1260 /* Check if we have some return values */
1261 trace("OtherOperationCount : 0x%s\n", wine_dbgstr_longlong(pii.OtherOperationCount));
1262 todo_wine
1263 {
1264 ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
1265 }
1266 }
1267
1268 static void test_query_process_times(void)
1269 {
1270 NTSTATUS status;
1271 ULONG ReturnLength;
1272 HANDLE process;
1273 SYSTEMTIME UTC, Local;
1274 KERNEL_USER_TIMES spti;
1275
1276 status = pNtQueryInformationProcess(NULL, ProcessTimes, NULL, sizeof(spti), NULL);
1277 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1278 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
1279
1280 status = pNtQueryInformationProcess(NULL, ProcessTimes, &spti, sizeof(spti), NULL);
1281 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1282
1283 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, 24, &ReturnLength);
1284 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1285
1286 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
1287 if (!process)
1288 {
1289 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
1290 process = GetCurrentProcess();
1291 trace("ProcessTimes for current process\n");
1292 }
1293 else
1294 trace("ProcessTimes for process with ID : %d\n", one_before_last_pid);
1295
1296 status = pNtQueryInformationProcess( process, ProcessTimes, &spti, sizeof(spti), &ReturnLength);
1297 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1298 ok( sizeof(spti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1299 CloseHandle(process);
1300
1301 FileTimeToSystemTime((const FILETIME *)&spti.CreateTime, &UTC);
1302 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
1303 trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
1304 Local.wHour, Local.wMinute, Local.wSecond);
1305
1306 FileTimeToSystemTime((const FILETIME *)&spti.ExitTime, &UTC);
1307 SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
1308 trace("ExitTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
1309 Local.wHour, Local.wMinute, Local.wSecond);
1310
1311 FileTimeToSystemTime((const FILETIME *)&spti.KernelTime, &Local);
1312 trace("KernelTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
1313
1314 FileTimeToSystemTime((const FILETIME *)&spti.UserTime, &Local);
1315 trace("UserTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
1316
1317 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, sizeof(spti) * 2, &ReturnLength);
1318 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1319 ok( sizeof(spti) == ReturnLength ||
1320 ReturnLength == 0 /* vista */ ||
1321 broken(is_wow64), /* returns garbage on wow64 */
1322 "Inconsistent length %d\n", ReturnLength);
1323 }
1324
1325 static void test_query_process_debug_port(int argc, char **argv)
1326 {
1327 DWORD_PTR debug_port = 0xdeadbeef;
1328 char cmdline[MAX_PATH];
1329 PROCESS_INFORMATION pi;
1330 STARTUPINFOA si = { 0 };
1331 NTSTATUS status;
1332 BOOL ret;
1333
1334 sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
1335
1336 si.cb = sizeof(si);
1337 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
1338 ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
1339 if (!ret) return;
1340
1341 status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
1342 NULL, 0, NULL);
1343 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
1344
1345 status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
1346 NULL, sizeof(debug_port), NULL);
1347 ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION,
1348 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
1349
1350 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
1351 NULL, sizeof(debug_port), NULL);
1352 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
1353
1354 status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
1355 &debug_port, sizeof(debug_port), NULL);
1356 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
1357
1358 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
1359 &debug_port, sizeof(debug_port) - 1, NULL);
1360 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
1361
1362 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
1363 &debug_port, sizeof(debug_port) + 1, NULL);
1364 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
1365
1366 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
1367 &debug_port, sizeof(debug_port), NULL);
1368 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1369 ok(debug_port == 0, "Expected port 0, got %#lx.\n", debug_port);
1370
1371 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugPort,
1372 &debug_port, sizeof(debug_port), NULL);
1373 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1374 ok(debug_port == ~(DWORD_PTR)0, "Expected port %#lx, got %#lx.\n", ~(DWORD_PTR)0, debug_port);
1375
1376 for (;;)
1377 {
1378 DEBUG_EVENT ev;
1379
1380 ret = WaitForDebugEvent(&ev, INFINITE);
1381 ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1382 if (!ret) break;
1383
1384 if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
1385
1386 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
1387 ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1388 if (!ret) break;
1389 }
1390
1391 ret = CloseHandle(pi.hThread);
1392 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
1393 ret = CloseHandle(pi.hProcess);
1394 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
1395 }
1396
1397 static void test_query_process_priority(void)
1398 {
1399 PROCESS_PRIORITY_CLASS priority[2];
1400 ULONG ReturnLength;
1401 DWORD orig_priority;
1402 NTSTATUS status;
1403 BOOL ret;
1404
1405 status = pNtQueryInformationProcess(NULL, ProcessPriorityClass, NULL, sizeof(priority[0]), NULL);
1406 ok(status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_HANDLE) /* w2k3 */,
1407 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
1408
1409 status = pNtQueryInformationProcess(NULL, ProcessPriorityClass, &priority, sizeof(priority[0]), NULL);
1410 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1411
1412 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, 1, &ReturnLength);
1413 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1414
1415 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, sizeof(priority), &ReturnLength);
1416 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1417
1418 orig_priority = GetPriorityClass(GetCurrentProcess());
1419 ret = SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
1420 ok(ret, "Failed to set priority class: %u\n", GetLastError());
1421
1422 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessPriorityClass, &priority, sizeof(priority[0]), &ReturnLength);
1423 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1424 ok(priority[0].PriorityClass == PROCESS_PRIOCLASS_BELOW_NORMAL,
1425 "Expected PROCESS_PRIOCLASS_BELOW_NORMAL, got %u\n", priority[0].PriorityClass);
1426
1427 ret = SetPriorityClass(GetCurrentProcess(), orig_priority);
1428 ok(ret, "Failed to reset priority class: %u\n", GetLastError());
1429 }
1430
1431 static void test_query_process_handlecount(void)
1432 {
1433 NTSTATUS status;
1434 ULONG ReturnLength;
1435 DWORD handlecount;
1436 BYTE buffer[2 * sizeof(DWORD)];
1437 HANDLE process;
1438
1439 status = pNtQueryInformationProcess(NULL, ProcessHandleCount, NULL, sizeof(handlecount), NULL);
1440 ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
1441 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
1442
1443 status = pNtQueryInformationProcess(NULL, ProcessHandleCount, &handlecount, sizeof(handlecount), NULL);
1444 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1445
1446 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, 2, &ReturnLength);
1447 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1448
1449 process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
1450 if (!process)
1451 {
1452 trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
1453 process = GetCurrentProcess();
1454 trace("ProcessHandleCount for current process\n");
1455 }
1456 else
1457 trace("ProcessHandleCount for process with ID : %d\n", one_before_last_pid);
1458
1459 status = pNtQueryInformationProcess( process, ProcessHandleCount, &handlecount, sizeof(handlecount), &ReturnLength);
1460 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1461 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1462 CloseHandle(process);
1463
1464 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, buffer, sizeof(buffer), &ReturnLength);
1465 ok( status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_SUCCESS,
1466 "Expected STATUS_INFO_LENGTH_MISMATCH or STATUS_SUCCESS, got %08x\n", status);
1467 ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
1468
1469 /* Check if we have some return values */
1470 trace("HandleCount : %d\n", handlecount);
1471 todo_wine
1472 {
1473 ok( handlecount > 0, "Expected some handles, got 0\n");
1474 }
1475 }
1476
1477 static void test_query_process_image_file_name(void)
1478 {
1479 NTSTATUS status;
1480 ULONG ReturnLength;
1481 UNICODE_STRING image_file_name;
1482 void *buffer;
1483 char *file_nameA;
1484 INT len;
1485
1486 status = pNtQueryInformationProcess(NULL, ProcessImageFileName, &image_file_name, sizeof(image_file_name), NULL);
1487 if (status == STATUS_INVALID_INFO_CLASS)
1488 {
1489 win_skip("ProcessImageFileName is not supported\n");
1490 return;
1491 }
1492 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1493
1494 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, 2, &ReturnLength);
1495 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1496
1497 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, sizeof(image_file_name), &ReturnLength);
1498 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1499
1500 buffer = HeapAlloc(GetProcessHeap(), 0, ReturnLength);
1501 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, buffer, ReturnLength, &ReturnLength);
1502 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1503 memcpy(&image_file_name, buffer, sizeof(image_file_name));
1504 len = WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), NULL, 0, NULL, NULL);
1505 file_nameA = HeapAlloc(GetProcessHeap(), 0, len + 1);
1506 WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), file_nameA, len, NULL, NULL);
1507 file_nameA[len] = '\0';
1508 HeapFree(GetProcessHeap(), 0, buffer);
1509 trace("process image file name: %s\n", file_nameA);
1510 todo_wine ok(strncmp(file_nameA, "\\Device\\", 8) == 0, "Process image name should be an NT path beginning with \\Device\\ (is %s)\n", file_nameA);
1511 HeapFree(GetProcessHeap(), 0, file_nameA);
1512 }
1513
1514 static void test_query_process_debug_object_handle(int argc, char **argv)
1515 {
1516 char cmdline[MAX_PATH];
1517 STARTUPINFOA si = {0};
1518 PROCESS_INFORMATION pi;
1519 BOOL ret;
1520 HANDLE debug_object;
1521 NTSTATUS status;
1522
1523 sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
1524
1525 si.cb = sizeof(si);
1526 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL,
1527 NULL, &si, &pi);
1528 ok(ret, "CreateProcess failed with last error %u\n", GetLastError());
1529 if (!ret) return;
1530
1531 status = pNtQueryInformationProcess(NULL, ProcessDebugObjectHandle, NULL,
1532 0, NULL);
1533 if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED)
1534 {
1535 win_skip("ProcessDebugObjectHandle is not supported\n");
1536 return;
1537 }
1538 ok(status == STATUS_INFO_LENGTH_MISMATCH,
1539 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n",
1540 status);
1541
1542 status = pNtQueryInformationProcess(NULL, ProcessDebugObjectHandle, NULL,
1543 sizeof(debug_object), NULL);
1544 ok(status == STATUS_INVALID_HANDLE ||
1545 status == STATUS_ACCESS_VIOLATION, /* XP */
1546 "Expected NtQueryInformationProcess to return STATUS_INVALID_HANDLE, got 0x%08x\n", status);
1547
1548 status = pNtQueryInformationProcess(GetCurrentProcess(),
1549 ProcessDebugObjectHandle, NULL, sizeof(debug_object), NULL);
1550 ok(status == STATUS_ACCESS_VIOLATION,
1551 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status);
1552
1553 status = pNtQueryInformationProcess(NULL, ProcessDebugObjectHandle,
1554 &debug_object, sizeof(debug_object), NULL);
1555 ok(status == STATUS_INVALID_HANDLE,
1556 "Expected NtQueryInformationProcess to return STATUS_ACCESS_VIOLATION, got 0x%08x\n", status);
1557
1558 status = pNtQueryInformationProcess(GetCurrentProcess(),
1559 ProcessDebugObjectHandle, &debug_object,
1560 sizeof(debug_object) - 1, NULL);
1561 ok(status == STATUS_INFO_LENGTH_MISMATCH,
1562 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status);
1563
1564 status = pNtQueryInformationProcess(GetCurrentProcess(),
1565 ProcessDebugObjectHandle, &debug_object,
1566 sizeof(debug_object) + 1, NULL);
1567 ok(status == STATUS_INFO_LENGTH_MISMATCH,
1568 "Expected NtQueryInformationProcess to return STATUS_INFO_LENGTH_MISMATCH, got 0x%08x\n", status);
1569
1570 debug_object = (HANDLE)0xdeadbeef;
1571 status = pNtQueryInformationProcess(GetCurrentProcess(),
1572 ProcessDebugObjectHandle, &debug_object,
1573 sizeof(debug_object), NULL);
1574 ok(status == STATUS_PORT_NOT_SET,
1575 "Expected NtQueryInformationProcess to return STATUS_PORT_NOT_SET, got 0x%08x\n", status);
1576 ok(debug_object == NULL ||
1577 broken(debug_object == (HANDLE)0xdeadbeef), /* Wow64 */
1578 "Expected debug object handle to be NULL, got %p\n", debug_object);
1579
1580 debug_object = (HANDLE)0xdeadbeef;
1581 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugObjectHandle,
1582 &debug_object, sizeof(debug_object), NULL);
1583 todo_wine
1584 ok(status == STATUS_SUCCESS,
1585 "Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08x\n", status);
1586 todo_wine
1587 ok(debug_object != NULL,
1588 "Expected debug object handle to be non-NULL, got %p\n", debug_object);
1589
1590 for (;;)
1591 {
1592 DEBUG_EVENT ev;
1593
1594 ret = WaitForDebugEvent(&ev, INFINITE);
1595 ok(ret, "WaitForDebugEvent failed with last error %u\n", GetLastError());
1596 if (!ret) break;
1597
1598 if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
1599
1600 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
1601 ok(ret, "ContinueDebugEvent failed with last error %u\n", GetLastError());
1602 if (!ret) break;
1603 }
1604
1605 ret = CloseHandle(pi.hThread);
1606 ok(ret, "CloseHandle failed with last error %u\n", GetLastError());
1607 ret = CloseHandle(pi.hProcess);
1608 ok(ret, "CloseHandle failed with last error %u\n", GetLastError());
1609 }
1610
1611 static void test_query_process_debug_flags(int argc, char **argv)
1612 {
1613 static const DWORD test_flags[] = { DEBUG_PROCESS,
1614 DEBUG_ONLY_THIS_PROCESS,
1615 DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS,
1616 CREATE_SUSPENDED };
1617 DWORD debug_flags = 0xdeadbeef;
1618 char cmdline[MAX_PATH];
1619 PROCESS_INFORMATION pi;
1620 STARTUPINFOA si = { 0 };
1621 NTSTATUS status;
1622 DEBUG_EVENT ev;
1623 DWORD result;
1624 BOOL ret;
1625 int i, j;
1626
1627 /* test invalid arguments */
1628 status = pNtQueryInformationProcess(NULL, ProcessDebugFlags, NULL, 0, NULL);
1629 ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
1630 "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
1631
1632 status = pNtQueryInformationProcess(NULL, ProcessDebugFlags, NULL, sizeof(debug_flags), NULL);
1633 ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
1634 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
1635
1636 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
1637 NULL, sizeof(debug_flags), NULL);
1638 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
1639
1640 status = pNtQueryInformationProcess(NULL, ProcessDebugFlags,
1641 &debug_flags, sizeof(debug_flags), NULL);
1642 ok(status == STATUS_INVALID_HANDLE || broken(status == STATUS_INVALID_INFO_CLASS) /* WOW64 */,
1643 "Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
1644
1645 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
1646 &debug_flags, sizeof(debug_flags) - 1, NULL);
1647 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
1648
1649 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
1650 &debug_flags, sizeof(debug_flags) + 1, NULL);
1651 ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
1652
1653 /* test ProcessDebugFlags of current process */
1654 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugFlags,
1655 &debug_flags, sizeof(debug_flags), NULL);
1656 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1657 ok(debug_flags == TRUE, "Expected flag TRUE, got %x.\n", debug_flags);
1658
1659 for (i = 0; i < sizeof(test_flags)/sizeof(test_flags[0]); i++)
1660 {
1661 DWORD expected_flags = !(test_flags[i] & DEBUG_ONLY_THIS_PROCESS);
1662 sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
1663
1664 si.cb = sizeof(si);
1665 ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, test_flags[i], NULL, NULL, &si, &pi);
1666 ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
1667
1668 if (!(test_flags[i] & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)))
1669 {
1670 /* test ProcessDebugFlags before attaching with debugger */
1671 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
1672 &debug_flags, sizeof(debug_flags), NULL);
1673 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1674 ok(debug_flags == TRUE, "Expected flag TRUE, got %x.\n", debug_flags);
1675
1676 ret = DebugActiveProcess(pi.dwProcessId);
1677 ok(ret, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
1678 expected_flags = FALSE;
1679 }
1680
1681 /* test ProcessDebugFlags after attaching with debugger */
1682 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
1683 &debug_flags, sizeof(debug_flags), NULL);
1684 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1685 ok(debug_flags == expected_flags, "Expected flag %x, got %x.\n", expected_flags, debug_flags);
1686
1687 if (!(test_flags[i] & CREATE_SUSPENDED))
1688 {
1689 /* Continue a couple of times to make sure the process is fully initialized,
1690 * otherwise Windows XP deadlocks in the following DebugActiveProcess(). */
1691 for (;;)
1692 {
1693 ret = WaitForDebugEvent(&ev, 1000);
1694 ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1695 if (!ret) break;
1696
1697 if (ev.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) break;
1698
1699 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
1700 ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1701 if (!ret) break;
1702 }
1703
1704 result = SuspendThread(pi.hThread);
1705 ok(result == 0, "Expected 0, got %u.\n", result);
1706 }
1707
1708 ret = DebugActiveProcessStop(pi.dwProcessId);
1709 ok(ret, "DebugActiveProcessStop failed, last error %#x.\n", GetLastError());
1710
1711 /* test ProcessDebugFlags after detaching debugger */
1712 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
1713 &debug_flags, sizeof(debug_flags), NULL);
1714 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1715 ok(debug_flags == expected_flags, "Expected flag %x, got %x.\n", expected_flags, debug_flags);
1716
1717 ret = DebugActiveProcess(pi.dwProcessId);
1718 ok(ret, "DebugActiveProcess failed, last error %#x.\n", GetLastError());
1719
1720 /* test ProcessDebugFlags after re-attaching debugger */
1721 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
1722 &debug_flags, sizeof(debug_flags), NULL);
1723 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1724 ok(debug_flags == FALSE, "Expected flag FALSE, got %x.\n", debug_flags);
1725
1726 result = ResumeThread(pi.hThread);
1727 todo_wine ok(result == 2, "Expected 2, got %u.\n", result);
1728
1729 /* Wait until the process is terminated. On Windows XP the process randomly
1730 * gets stuck in a non-continuable exception, so stop after 100 iterations.
1731 * On Windows 2003, the debugged process disappears (or stops?) without
1732 * any EXIT_PROCESS_DEBUG_EVENT after a couple of events. */
1733 for (j = 0; j < 100; j++)
1734 {
1735 ret = WaitForDebugEvent(&ev, 1000);
1736 ok(ret || broken(GetLastError() == ERROR_SEM_TIMEOUT),
1737 "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
1738 if (!ret) break;
1739
1740 if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
1741
1742 ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
1743 ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
1744 if (!ret) break;
1745 }
1746 ok(j < 100 || broken(j >= 100) /* Win XP */, "Expected less than 100 debug events.\n");
1747
1748 /* test ProcessDebugFlags after process has terminated */
1749 status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugFlags,
1750 &debug_flags, sizeof(debug_flags), NULL);
1751 ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
1752 ok(debug_flags == FALSE, "Expected flag FALSE, got %x.\n", debug_flags);
1753
1754 ret = CloseHandle(pi.hThread);
1755 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
1756 ret = CloseHandle(pi.hProcess);
1757 ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
1758 }
1759 }
1760
1761 static void test_readvirtualmemory(void)
1762 {
1763 HANDLE process;
1764 NTSTATUS status;
1765 SIZE_T readcount;
1766 static const char teststring[] = "test string";
1767 char buffer[12];
1768
1769 process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
1770 ok(process != 0, "Expected to be able to open own process for reading memory\n");
1771
1772 /* normal operation */
1773 status = pNtReadVirtualMemory(process, teststring, buffer, 12, &readcount);
1774 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1775 ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
1776 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
1777
1778 /* no number of bytes */
1779 memset(buffer, 0, 12);
1780 status = pNtReadVirtualMemory(process, teststring, buffer, 12, NULL);
1781 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1782 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
1783
1784 /* illegal remote address */
1785 todo_wine{
1786 status = pNtReadVirtualMemory(process, (void *) 0x1234, buffer, 12, &readcount);
1787 ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_ACCESS_VIOLATION), "Expected STATUS_PARTIAL_COPY, got %08x\n", status);
1788 if (status == STATUS_PARTIAL_COPY)
1789 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
1790 }
1791
1792 /* 0 handle */
1793 status = pNtReadVirtualMemory(0, teststring, buffer, 12, &readcount);
1794 ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
1795 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
1796
1797 /* pseudo handle for current process*/
1798 memset(buffer, 0, 12);
1799 status = pNtReadVirtualMemory((HANDLE)-1, teststring, buffer, 12, &readcount);
1800 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1801 ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
1802 ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
1803
1804 /* illegal local address */
1805 status = pNtReadVirtualMemory(process, teststring, (void *)0x1234, 12, &readcount);
1806 ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
1807 ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
1808
1809 CloseHandle(process);
1810 }
1811
1812 static void test_mapprotection(void)
1813 {
1814 HANDLE h;
1815 void* addr;
1816 MEMORY_BASIC_INFORMATION info;
1817 ULONG oldflags, flagsize, flags = MEM_EXECUTE_OPTION_ENABLE;
1818 LARGE_INTEGER size, offset;
1819 NTSTATUS status;
1820 SIZE_T retlen, count;
1821 void (*f)(void);
1822
1823 if (!pNtClose) {
1824 skip("No NtClose ... Win98\n");
1825 return;
1826 }
1827 /* Switch to being a noexec unaware process */
1828 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof (oldflags), &flagsize);
1829 if (status == STATUS_INVALID_PARAMETER) {
1830 skip("Invalid Parameter on ProcessExecuteFlags query?\n");
1831 return;
1832 }
1833 ok( (status == STATUS_SUCCESS) || (status == STATUS_INVALID_INFO_CLASS), "Expected STATUS_SUCCESS, got %08x\n", status);
1834 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &flags, sizeof(flags) );
1835 ok( (status == STATUS_SUCCESS) || (status == STATUS_INVALID_INFO_CLASS), "Expected STATUS_SUCCESS, got %08x\n", status);
1836
1837 size.u.LowPart = 0x2000;
1838 size.u.HighPart = 0;
1839 status = pNtCreateSection ( &h,
1840 STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
1841 NULL,
1842 &size,
1843 PAGE_READWRITE,
1844 SEC_COMMIT | SEC_NOCACHE,
1845 0
1846 );
1847 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1848
1849 offset.u.LowPart = 0;
1850 offset.u.HighPart = 0;
1851 count = 0x2000;
1852 addr = NULL;
1853 status = pNtMapViewOfSection ( h, GetCurrentProcess(), &addr, 0, 0, &offset, &count, ViewShare, 0, PAGE_READWRITE);
1854 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1855
1856 #if defined(__x86_64__) || defined(__i386__)
1857 *(unsigned char*)addr = 0xc3; /* lret ... in both i386 and x86_64 */
1858 #elif defined(__arm__)
1859 *(unsigned long*)addr = 0xe12fff1e; /* bx lr */
1860 #elif defined(__aarch64__)
1861 *(unsigned long*)addr = 0xd65f03c0; /* ret */
1862 #else
1863 ok(0, "Add a return opcode for your architecture or expect a crash in this test\n");
1864 #endif
1865 trace("trying to execute code in the readwrite only mapped anon file...\n");
1866 f = addr;f();
1867 trace("...done.\n");
1868
1869 status = pNtQueryVirtualMemory( GetCurrentProcess(), addr, MemoryBasicInformation, &info, sizeof(info), &retlen );
1870 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1871 ok( retlen == sizeof(info), "Expected STATUS_SUCCESS, got %08x\n", status);
1872 ok((info.Protect & ~PAGE_NOCACHE) == PAGE_READWRITE, "addr.Protect is not PAGE_READWRITE, but 0x%x\n", info.Protect);
1873
1874 status = pNtUnmapViewOfSection( GetCurrentProcess(), (char *)addr + 0x1050 );
1875 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1876 pNtClose (h);
1877
1878 /* Switch back */
1879 pNtSetInformationProcess( GetCurrentProcess(), ProcessExecuteFlags, &oldflags, sizeof(oldflags) );
1880 }
1881
1882 static void test_queryvirtualmemory(void)
1883 {
1884 NTSTATUS status;
1885 SIZE_T readcount;
1886 static const WCHAR windowsW[] = {'w','i','n','d','o','w','s'};
1887 static const char teststring[] = "test string";
1888 static char datatestbuf[42] = "abc";
1889 static char rwtestbuf[42];
1890 MEMORY_BASIC_INFORMATION mbi;
1891 char stackbuf[42];
1892 HMODULE module;
1893 char buffer_name[sizeof(MEMORY_SECTION_NAME) + MAX_PATH * sizeof(WCHAR)];
1894 #ifndef __REACTOS__
1895 MEMORY_SECTION_NAME *msn = (MEMORY_SECTION_NAME *)buffer_name;
1896 #endif
1897 BOOL found;
1898 int i;
1899 #ifdef __REACTOS__
1900 MEMORY_SECTION_NAME *msn = HeapAlloc(GetProcessHeap(), 0, sizeof(buffer_name));
1901 #endif
1902
1903 module = GetModuleHandleA( "ntdll.dll" );
1904 trace("Check flags of the PE header of NTDLL.DLL at %p\n", module);
1905 status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1906 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1907 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1908 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
1909 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
1910 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
1911 ok (mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_READONLY);
1912 ok (mbi.Type == MEM_IMAGE, "mbi.Type is 0x%x, expected 0x%x\n", mbi.Type, MEM_IMAGE);
1913
1914 trace("Check flags of a function entry in NTDLL.DLL at %p\n", pNtQueryVirtualMemory);
1915 module = GetModuleHandleA( "ntdll.dll" );
1916 status = pNtQueryVirtualMemory(NtCurrentProcess(), pNtQueryVirtualMemory, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1917 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1918 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1919 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
1920 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
1921 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
1922 ok (mbi.Protect == PAGE_EXECUTE_READ, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_EXECUTE_READ);
1923
1924 trace("Check flags of heap at %p\n", GetProcessHeap());
1925 status = pNtQueryVirtualMemory(NtCurrentProcess(), GetProcessHeap(), MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1926 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1927 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1928 ok (mbi.AllocationProtect == PAGE_READWRITE || mbi.AllocationProtect == PAGE_EXECUTE_READWRITE,
1929 "mbi.AllocationProtect is 0x%x\n", mbi.AllocationProtect);
1930 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
1931 ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE,
1932 "mbi.Protect is 0x%x\n", mbi.Protect);
1933
1934 trace("Check flags of stack at %p\n", stackbuf);
1935 status = pNtQueryVirtualMemory(NtCurrentProcess(), stackbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1936 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1937 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1938 ok (mbi.AllocationProtect == PAGE_READWRITE, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_READWRITE);
1939 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%x\n", mbi.State, MEM_COMMIT);
1940 ok (mbi.Protect == PAGE_READWRITE, "mbi.Protect is 0x%x, expected 0x%x\n", mbi.Protect, PAGE_READWRITE);
1941
1942 trace("Check flags of read-only data at %p\n", teststring);
1943 module = GetModuleHandleA( NULL );
1944 status = pNtQueryVirtualMemory(NtCurrentProcess(), teststring, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1945 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1946 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1947 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
1948 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
1949 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
1950 if (mbi.Protect != PAGE_READONLY)
1951 todo_wine ok( mbi.Protect == PAGE_READONLY, "mbi.Protect is 0x%x, expected 0x%X\n", mbi.Protect, PAGE_READONLY);
1952
1953 trace("Check flags of read-write data at %p\n", datatestbuf);
1954 status = pNtQueryVirtualMemory(NtCurrentProcess(), datatestbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1955 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1956 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1957 ok (mbi.AllocationBase == module, "mbi.AllocationBase is 0x%p, expected 0x%p\n", mbi.AllocationBase, module);
1958 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
1959 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
1960 ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_WRITECOPY,
1961 "mbi.Protect is 0x%x\n", mbi.Protect);
1962
1963 trace("Check flags of read-write uninitialized data (.bss) at %p\n", rwtestbuf);
1964 status = pNtQueryVirtualMemory(NtCurrentProcess(), rwtestbuf, MemoryBasicInformation, &mbi, sizeof(MEMORY_BASIC_INFORMATION), &readcount);
1965 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1966 ok( readcount == sizeof(MEMORY_BASIC_INFORMATION), "Expected to read %d bytes, got %ld\n",(int)sizeof(MEMORY_BASIC_INFORMATION),readcount);
1967 if (mbi.AllocationBase == module)
1968 {
1969 ok (mbi.AllocationProtect == PAGE_EXECUTE_WRITECOPY, "mbi.AllocationProtect is 0x%x, expected 0x%x\n", mbi.AllocationProtect, PAGE_EXECUTE_WRITECOPY);
1970 ok (mbi.State == MEM_COMMIT, "mbi.State is 0x%x, expected 0x%X\n", mbi.State, MEM_COMMIT);
1971 ok (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_WRITECOPY,
1972 "mbi.Protect is 0x%x\n", mbi.Protect);
1973 }
1974 else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
1975
1976 /* check error code when addr is higher than working set limit */
1977 status = pNtQueryVirtualMemory(NtCurrentProcess(), (void *)~0, MemoryBasicInformation, &mbi, sizeof(mbi), &readcount);
1978 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1979
1980 trace("Check section name of NTDLL.DLL with invalid size\n");
1981 module = GetModuleHandleA( "ntdll.dll" );
1982 memset(msn, 0, sizeof(*msn));
1983 readcount = 0;
1984 status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn), &readcount);
1985 ok( status == STATUS_BUFFER_OVERFLOW, "Expected STATUS_BUFFER_OVERFLOW, got %08x\n", status);
1986 ok( readcount > 0, "Expected readcount to be > 0\n");
1987
1988 trace("Check section name of NTDLL.DLL with invalid size\n");
1989 module = GetModuleHandleA( "ntdll.dll" );
1990 memset(msn, 0, sizeof(*msn));
1991 readcount = 0;
1992 status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn) - 1, &readcount);
1993 ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
1994 ok( readcount > 0, "Expected readcount to be > 0\n");
1995
1996 trace("Check section name of NTDLL.DLL\n");
1997 module = GetModuleHandleA( "ntdll.dll" );
1998 memset(msn, 0x55, sizeof(*msn));
1999 memset(buffer_name, 0x77, sizeof(buffer_name));
2000 readcount = 0;
2001 status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(buffer_name), &readcount);
2002 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2003 ok( readcount > 0, "Expected readcount to be > 0\n");
2004 trace ("Section Name: %s\n", wine_dbgstr_w(msn->SectionFileName.Buffer));
2005 pRtlDowncaseUnicodeString( &msn->SectionFileName, &msn->SectionFileName, FALSE );
2006 for (found = FALSE, i = (msn->SectionFileName.Length - sizeof(windowsW)) / sizeof(WCHAR); i >= 0; i--)
2007 found |= !memcmp( &msn->SectionFileName.Buffer[i], windowsW, sizeof(windowsW) );
2008 ok( found, "Section name does not contain \"Windows\"\n");
2009
2010 trace("Check section name of non mapped memory\n");
2011 memset(msn, 0, sizeof(buffer_name));
2012 readcount = 0;
2013 status = pNtQueryVirtualMemory(NtCurrentProcess(), &buffer_name, MemorySectionName, msn, sizeof(buffer_name), &readcount);
2014 ok( status == STATUS_INVALID_ADDRESS, "Expected STATUS_INVALID_ADDRESS, got %08x\n", status);
2015 ok( readcount == 0 || broken(readcount != 0) /* wow64 */, "Expected readcount to be 0\n");
2016
2017 #ifdef __REACTOS__
2018 HeapFree(GetProcessHeap(), 0, msn);
2019 #endif
2020 }
2021
2022 static void test_affinity(void)
2023 {
2024 NTSTATUS status;
2025 PROCESS_BASIC_INFORMATION pbi;
2026 DWORD_PTR proc_affinity, thread_affinity;
2027 THREAD_BASIC_INFORMATION tbi;
2028 SYSTEM_INFO si;
2029
2030 GetSystemInfo(&si);
2031 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
2032 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2033 proc_affinity = pbi.AffinityMask;
2034 ok( proc_affinity == (1 << si.dwNumberOfProcessors) - 1, "Unexpected process affinity\n" );
2035 proc_affinity = 1 << si.dwNumberOfProcessors;
2036 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
2037 ok( status == STATUS_INVALID_PARAMETER,
2038 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
2039
2040 proc_affinity = 0;
2041 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
2042 ok( status == STATUS_INVALID_PARAMETER,
2043 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
2044
2045 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
2046 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2047 ok( tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1, "Unexpected thread affinity\n" );
2048 thread_affinity = 1 << si.dwNumberOfProcessors;
2049 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
2050 ok( status == STATUS_INVALID_PARAMETER,
2051 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
2052 thread_affinity = 0;
2053 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
2054 ok( status == STATUS_INVALID_PARAMETER,
2055 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
2056
2057 thread_affinity = 1;
2058 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
2059 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2060 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
2061 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2062 ok( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
2063
2064 /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
2065 thread_affinity = ~(DWORD_PTR)0;
2066 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
2067 ok( broken(status == STATUS_INVALID_PARAMETER) || status == STATUS_SUCCESS,
2068 "Expected STATUS_SUCCESS, got %08x\n", status);
2069
2070 if (si.dwNumberOfProcessors <= 1)
2071 {
2072 skip("only one processor, skipping affinity testing\n");
2073 return;
2074 }
2075
2076 /* Test thread affinity mask resulting from "all processors" flag */
2077 if (status == STATUS_SUCCESS)
2078 {
2079 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
2080 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2081 ok( broken(tbi.AffinityMask == 1) || tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
2082 "Unexpected thread affinity\n" );
2083 }
2084 else
2085 skip("Cannot test thread affinity mask for 'all processors' flag\n");
2086
2087 proc_affinity = 2;
2088 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
2089 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2090 status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
2091 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2092 proc_affinity = pbi.AffinityMask;
2093 ok( proc_affinity == 2, "Unexpected process affinity\n" );
2094 /* Setting the process affinity changes the thread affinity to match */
2095 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
2096 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2097 ok( tbi.AffinityMask == 2, "Unexpected thread affinity\n" );
2098 /* The thread affinity is restricted to the process affinity */
2099 thread_affinity = 1;
2100 status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
2101 ok( status == STATUS_INVALID_PARAMETER,
2102 "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
2103
2104 proc_affinity = (1 << si.dwNumberOfProcessors) - 1;
2105 status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
2106 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2107 /* Resetting the process affinity also resets the thread affinity */
2108 status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
2109 ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2110 ok( tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
2111 "Unexpected thread affinity\n" );
2112 }
2113
2114 static void test_NtGetCurrentProcessorNumber(void)
2115 {
2116 NTSTATUS status;
2117 SYSTEM_INFO si;
2118 PROCESS_BASIC_INFORMATION pbi;
2119 THREAD_BASIC_INFORMATION tbi;
2120 DWORD_PTR old_process_mask;
2121 DWORD_PTR old_thread_mask;
2122 DWORD_PTR new_mask;
2123 ULONG current_cpu;
2124 ULONG i;
2125
2126 if (!pNtGetCurrentProcessorNumber) {
2127 win_skip("NtGetCurrentProcessorNumber not available\n");
2128 return;
2129 }
2130
2131 GetSystemInfo(&si);
2132 current_cpu = pNtGetCurrentProcessorNumber();
2133 trace("dwNumberOfProcessors: %d, current processor: %d\n", si.dwNumberOfProcessors, current_cpu);
2134
2135 status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
2136 old_process_mask = pbi.AffinityMask;
2137 ok(status == STATUS_SUCCESS, "got 0x%x (expected STATUS_SUCCESS)\n", status);
2138
2139 status = pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
2140 old_thread_mask = tbi.AffinityMask;
2141 ok(status == STATUS_SUCCESS, "got 0x%x (expected STATUS_SUCCESS)\n", status);
2142
2143 /* allow the test to run on all processors */
2144 new_mask = (1 << si.dwNumberOfProcessors) - 1;
2145 status = pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask, &new_mask, sizeof(new_mask));
2146 ok(status == STATUS_SUCCESS, "got 0x%x (expected STATUS_SUCCESS)\n", status);
2147
2148 for (i = 0; i < si.dwNumberOfProcessors; i++)
2149 {
2150 new_mask = 1 << i;
2151 status = pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask, &new_mask, sizeof(new_mask));
2152 ok(status == STATUS_SUCCESS, "%d: got 0x%x (expected STATUS_SUCCESS)\n", i, status);
2153
2154 status = pNtQueryInformationThread(GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL);
2155 ok(status == STATUS_SUCCESS, "%d: got 0x%x (expected STATUS_SUCCESS)\n", i, status);
2156
2157 current_cpu = pNtGetCurrentProcessorNumber();
2158 ok((current_cpu == i), "%d (new_mask 0x%lx): running on processor %d (AffinityMask: 0x%lx)\n",
2159 i, new_mask, current_cpu, tbi.AffinityMask);
2160 }
2161
2162 /* restore old values */
2163 status = pNtSetInformationProcess(GetCurrentProcess(), ProcessAffinityMask, &old_process_mask, sizeof(old_process_mask));
2164 ok(status == STATUS_SUCCESS, "got 0x%x (expected STATUS_SUCCESS)\n", status);
2165
2166 status = pNtSetInformationThread(GetCurrentThread(), ThreadAffinityMask, &old_thread_mask, sizeof(old_thread_mask));
2167 ok(status == STATUS_SUCCESS, "got 0x%x (expected STATUS_SUCCESS)\n", status);
2168 }
2169
2170 static DWORD WINAPI start_address_thread(void *arg)
2171 {
2172 PRTL_THREAD_START_ROUTINE entry;
2173 NTSTATUS status;
2174 DWORD ret;
2175
2176 entry = NULL;
2177 ret = 0xdeadbeef;
2178 status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
2179 &entry, sizeof(entry), &ret);
2180 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
2181 ok(ret == sizeof(entry), "NtQueryInformationThread returned %u bytes\n", ret);
2182 ok(entry == (void *)start_address_thread, "expected %p, got %p\n", start_address_thread, entry);
2183 return 0;
2184 }
2185
2186 static void test_thread_start_address(void)
2187 {
2188 PRTL_THREAD_START_ROUTINE entry, expected_entry;
2189 IMAGE_NT_HEADERS *nt;
2190 NTSTATUS status;
2191 HANDLE thread;
2192 void *module;
2193 DWORD ret;
2194
2195 module = GetModuleHandleA(0);
2196 ok(module != NULL, "expected non-NULL address for module\n");
2197 nt = RtlImageNtHeader(module);
2198 ok(nt != NULL, "expected non-NULL address for NT header\n");
2199
2200 entry = NULL;
2201 ret = 0xdeadbeef;
2202 status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
2203 &entry, sizeof(entry), &ret);
2204 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
2205 ok(ret == sizeof(entry), "NtQueryInformationThread returned %u bytes\n", ret);
2206 expected_entry = (void *)((char *)module + nt->OptionalHeader.AddressOfEntryPoint);
2207 ok(entry == expected_entry, "expected %p, got %p\n", expected_entry, entry);
2208
2209 entry = (void *)0xdeadbeef;
2210 status = pNtSetInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
2211 &entry, sizeof(entry));
2212 ok(status == STATUS_SUCCESS || status == STATUS_INVALID_PARAMETER, /* >= Vista */
2213 "expected STATUS_SUCCESS or STATUS_INVALID_PARAMETER, got %08x\n", status);
2214
2215 if (status == STATUS_SUCCESS)
2216 {
2217 entry = NULL;
2218 ret = 0xdeadbeef;
2219 status = pNtQueryInformationThread(GetCurrentThread(), ThreadQuerySetWin32StartAddress,
2220 &entry, sizeof(entry), &ret);
2221 ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
2222 ok(ret == sizeof(entry), "NtQueryInformationThread returned %u bytes\n", ret);
2223 ok(entry == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", entry);
2224 }
2225
2226 thread = CreateThread(NULL, 0, start_address_thread, NULL, 0, NULL);
2227 ok(thread != INVALID_HANDLE_VALUE, "CreateThread failed with %d\n", GetLastError());
2228 ret = WaitForSingleObject(thread, 1000);
2229 ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
2230 CloseHandle(thread);
2231 }
2232
2233 static void test_query_data_alignment(void)
2234 {
2235 ULONG ReturnLength;
2236 NTSTATUS status;
2237 DWORD value;
2238
2239 value = 0xdeadbeef;
2240 status = pNtQuerySystemInformation(SystemRecommendedSharedDataAlignment, &value, sizeof(value), &ReturnLength);
2241 ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
2242 ok(sizeof(value) == ReturnLength, "Inconsistent length %u\n", ReturnLength);
2243 ok(value == 64, "Expected 64, got %u\n", value);
2244 }
2245
2246 START_TEST(info)
2247 {
2248 char **argv;
2249 int argc;
2250
2251 if(!InitFunctionPtrs())
2252 return;
2253
2254 argc = winetest_get_mainargs(&argv);
2255 if (argc >= 3) return; /* Child */
2256
2257 /* NtQuerySystemInformation */
2258
2259 /* 0x0 SystemBasicInformation */
2260 trace("Starting test_query_basic()\n");
2261 test_query_basic();
2262
2263 /* 0x1 SystemCpuInformation */
2264 trace("Starting test_query_cpu()\n");
2265 test_query_cpu();
2266
2267 /* 0x2 SystemPerformanceInformation */
2268 trace("Starting test_query_performance()\n");
2269 test_query_performance();
2270
2271 /* 0x3 SystemTimeOfDayInformation */
2272 trace("Starting test_query_timeofday()\n");
2273 test_query_timeofday();
2274
2275 /* 0x5 SystemProcessInformation */
2276 trace("Starting test_query_process()\n");
2277 test_query_process();
2278
2279 /* 0x8 SystemProcessorPerformanceInformation */
2280 trace("Starting test_query_procperf()\n");
2281 test_query_procperf();
2282
2283 /* 0xb SystemModuleInformation */
2284 trace("Starting test_query_module()\n");
2285 test_query_module();
2286
2287 /* 0x10 SystemHandleInformation */
2288 trace("Starting test_query_handle()\n");
2289 test_query_handle();
2290
2291 /* 0x40 SystemHandleInformation */
2292 trace("Starting test_query_handle_ex()\n");
2293 test_query_handle_ex();
2294
2295 /* 0x15 SystemCacheInformation */
2296 trace("Starting test_query_cache()\n");
2297 test_query_cache();
2298
2299 /* 0x17 SystemInterruptInformation */
2300 trace("Starting test_query_interrupt()\n");
2301 test_query_interrupt();
2302
2303 /* 0x23 SystemKernelDebuggerInformation */
2304 trace("Starting test_query_kerndebug()\n");
2305 test_query_kerndebug();
2306
2307 /* 0x25 SystemRegistryQuotaInformation */
2308 trace("Starting test_query_regquota()\n");
2309 test_query_regquota();
2310
2311 /* 0x49 SystemLogicalProcessorInformation */
2312 trace("Starting test_query_logicalproc()\n");
2313 test_query_logicalproc();
2314 test_query_logicalprocex();
2315
2316 /* NtPowerInformation */
2317
2318 /* 0xb ProcessorInformation */
2319 trace("Starting test_query_processor_power_info()\n");
2320 test_query_processor_power_info();
2321
2322 /* NtQueryInformationProcess */
2323
2324 /* 0x0 ProcessBasicInformation */
2325 trace("Starting test_query_process_basic()\n");
2326 test_query_process_basic();
2327
2328 /* 0x2 ProcessIoCounters */
2329 trace("Starting test_query_process_io()\n");
2330 test_query_process_io();
2331
2332 /* 0x3 ProcessVmCounters */
2333 trace("Starting test_query_process_vm()\n");
2334 test_query_process_vm();
2335
2336 /* 0x4 ProcessTimes */
2337 trace("Starting test_query_process_times()\n");
2338 test_query_process_times();
2339
2340 /* 0x7 ProcessDebugPort */
2341 trace("Starting test_process_debug_port()\n");
2342 test_query_process_debug_port(argc, argv);
2343
2344 /* 0x12 ProcessPriorityClass */
2345 trace("Starting test_query_process_priority()\n");
2346 test_query_process_priority();
2347
2348 /* 0x14 ProcessHandleCount */
2349 trace("Starting test_query_process_handlecount()\n");
2350 test_query_process_handlecount();
2351
2352 /* 0x1A ProcessWow64Information */
2353 trace("Starting test_query_process_wow64()\n");
2354 test_query_process_wow64();
2355
2356 /* 0x1B ProcessImageFileName */
2357 trace("Starting test_query_process_image_file_name()\n");
2358 test_query_process_image_file_name();
2359
2360 /* 0x1E ProcessDebugObjectHandle */
2361 trace("Starting test_query_process_debug_object_handle()\n");
2362 test_query_process_debug_object_handle(argc, argv);
2363
2364 /* 0x1F ProcessDebugFlags */
2365 trace("Starting test_process_debug_flags()\n");
2366 test_query_process_debug_flags(argc, argv);
2367
2368 /* belongs to its own file */
2369 trace("Starting test_readvirtualmemory()\n");
2370 test_readvirtualmemory();
2371
2372 trace("Starting test_queryvirtualmemory()\n");
2373 test_queryvirtualmemory();
2374
2375 trace("Starting test_mapprotection()\n");
2376 test_mapprotection();
2377
2378 trace("Starting test_affinity()\n");
2379 test_affinity();
2380
2381 trace("Starting test_NtGetCurrentProcessorNumber()\n");
2382 test_NtGetCurrentProcessorNumber();
2383
2384 trace("Starting test_thread_start_address()\n");
2385 test_thread_start_address();
2386
2387 trace("Starting test_query_data_alignment()\n");
2388 test_query_data_alignment();
2389 }