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