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