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