ntdll/tests: Fix a number of test failures on Wow64.
[wine] / dlls / ntdll / tests / info.c
1 /* Unit test suite for *Information* Registry API functions
2  *
3  * Copyright 2005 Paul Vriens
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  */
20
21 #include "ntdll_test.h"
22 #include <winnls.h>
23 #include <stdio.h>
24
25 static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
26 static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
27 static NTSTATUS (WINAPI * pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
28 static NTSTATUS (WINAPI * pNtSetInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG);
29 static NTSTATUS (WINAPI * pNtSetInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG);
30 static NTSTATUS (WINAPI * pNtReadVirtualMemory)(HANDLE, const void*, void*, SIZE_T, SIZE_T*);
31 static BOOL     (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
32
33 static BOOL is_wow64;
34
35 /* one_before_last_pid is used to be able to compare values of a still running process
36    with the output of the test_query_process_times and test_query_process_handlecount tests.
37 */
38 static DWORD one_before_last_pid = 0;
39
40 #define NTDLL_GET_PROC(func) do {                     \
41     p ## func = (void*)GetProcAddress(hntdll, #func); \
42     if(!p ## func) { \
43       trace("GetProcAddress(%s) failed\n", #func); \
44       return FALSE; \
45     } \
46   } while(0)
47
48 static BOOL InitFunctionPtrs(void)
49 {
50     /* All needed functions are NT based, so using GetModuleHandle is a good check */
51     HMODULE hntdll = GetModuleHandle("ntdll");
52     if (!hntdll)
53     {
54         win_skip("Not running on NT\n");
55         return FALSE;
56     }
57
58     NTDLL_GET_PROC(NtQuerySystemInformation);
59     NTDLL_GET_PROC(NtQueryInformationProcess);
60     NTDLL_GET_PROC(NtQueryInformationThread);
61     NTDLL_GET_PROC(NtSetInformationProcess);
62     NTDLL_GET_PROC(NtSetInformationThread);
63     NTDLL_GET_PROC(NtReadVirtualMemory);
64
65     pIsWow64Process = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "IsWow64Process");
66     if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
67     return TRUE;
68 }
69
70 static void test_query_basic(void)
71 {
72     NTSTATUS status;
73     ULONG ReturnLength;
74     SYSTEM_BASIC_INFORMATION sbi;
75
76     /* This test also covers some basic parameter testing that should be the same for 
77      * every information class
78     */
79
80     /* Use a nonexistent info class */
81     trace("Check nonexistent info class\n");
82     status = pNtQuerySystemInformation(-1, NULL, 0, NULL);
83     ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
84         "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status);
85
86     /* Use an existing class but with a zero-length buffer */
87     trace("Check zero-length buffer\n");
88     status = pNtQuerySystemInformation(SystemBasicInformation, NULL, 0, NULL);
89     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
90
91     /* Use an existing class, correct length but no SystemInformation buffer */
92     trace("Check no SystemInformation buffer\n");
93     status = pNtQuerySystemInformation(SystemBasicInformation, NULL, sizeof(sbi), NULL);
94     ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER /* vista */,
95         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got %08x\n", status);
96
97     /* Use a existing class, correct length, a pointer to a buffer but no ReturnLength pointer */
98     trace("Check no ReturnLength pointer\n");
99     status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), NULL);
100     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
101
102     /* Check a too large buffer size */
103     trace("Check a too large buffer size\n");
104     status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi) * 2, &ReturnLength);
105     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
106
107     /* Finally some correct calls */
108     trace("Check with correct parameters\n");
109     status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
110     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
111     ok( sizeof(sbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
112
113     /* Check if we have some return values */
114     trace("Number of Processors : %d\n", sbi.NumberOfProcessors);
115     ok( sbi.NumberOfProcessors > 0, "Expected more than 0 processors, got %d\n", sbi.NumberOfProcessors);
116 }
117
118 static void test_query_cpu(void)
119 {
120     DWORD status;
121     ULONG ReturnLength;
122     SYSTEM_CPU_INFORMATION sci;
123
124     status = pNtQuerySystemInformation(SystemCpuInformation, &sci, sizeof(sci), &ReturnLength);
125     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
126     ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
127
128     /* Check if we have some return values */
129     trace("Processor FeatureSet : %08x\n", sci.FeatureSet);
130     ok( sci.FeatureSet != 0, "Expected some features for this processor, got %08x\n", sci.FeatureSet);
131 }
132
133 static void test_query_performance(void)
134 {
135     NTSTATUS status;
136     ULONG ReturnLength;
137     ULONGLONG buffer[sizeof(SYSTEM_PERFORMANCE_INFORMATION)/sizeof(ULONGLONG) + 5];
138     DWORD size = sizeof(SYSTEM_PERFORMANCE_INFORMATION);
139
140     status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, 0, &ReturnLength);
141     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
142
143     status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
144     if (status == STATUS_INFO_LENGTH_MISMATCH && is_wow64)
145     {
146         /* size is larger on wow64 under w2k8/win7 */
147         size += 16;
148         status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size, &ReturnLength);
149     }
150     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
151     ok( ReturnLength == size, "Inconsistent length %d\n", ReturnLength);
152
153     status = pNtQuerySystemInformation(SystemPerformanceInformation, buffer, size + 2, &ReturnLength);
154     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
155     ok( ReturnLength == size || ReturnLength == size + 2,
156         "Inconsistent length %d\n", ReturnLength);
157
158     /* Not return values yet, as struct members are unknown */
159 }
160
161 static void test_query_timeofday(void)
162 {
163     NTSTATUS status;
164     ULONG ReturnLength;
165
166     /* Copy of our winternl.h structure turned into a private one */
167     typedef struct _SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE {
168         LARGE_INTEGER liKeBootTime;
169         LARGE_INTEGER liKeSystemTime;
170         LARGE_INTEGER liExpTimeZoneBias;
171         ULONG uCurrentTimeZoneId;
172         DWORD dwUnknown1[5];
173     } SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE, *PSYSTEM_TIMEOFDAY_INFORMATION_PRIVATE;
174
175     SYSTEM_TIMEOFDAY_INFORMATION_PRIVATE sti;
176   
177     /*  The struct size for NT (32 bytes) and Win2K/XP (48 bytes) differ.
178      *
179      *  Windows 2000 and XP return STATUS_INFO_LENGTH_MISMATCH if the given buffer size is greater
180      *  then 48 and 0 otherwise
181      *  Windows NT returns STATUS_INFO_LENGTH_MISMATCH when the given buffer size is not correct
182      *  and 0 otherwise
183      *
184      *  Windows 2000 and XP copy the given buffer size into the provided buffer, if the return code is STATUS_SUCCESS
185      *  NT only fills the buffer if the return code is STATUS_SUCCESS
186      *
187     */
188
189     status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
190
191     if (status == STATUS_INFO_LENGTH_MISMATCH)
192     {
193         trace("Windows version is NT, we have to cater for differences with W2K/WinXP\n");
194  
195         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
196         ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
197         ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
198
199         sti.uCurrentTimeZoneId = 0xdeadbeef;
200         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 28, &ReturnLength);
201         ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
202
203         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
204         ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
205         ok( 32 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
206     }
207     else
208     {
209         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 0, &ReturnLength);
210         ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
211         ok( 0 == ReturnLength, "ReturnLength should be 0, it is (%d)\n", ReturnLength);
212
213         sti.uCurrentTimeZoneId = 0xdeadbeef;
214         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 24, &ReturnLength);
215         ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
216         ok( 24 == ReturnLength, "ReturnLength should be 24, it is (%d)\n", ReturnLength);
217         ok( 0xdeadbeef == sti.uCurrentTimeZoneId, "This part of the buffer should not have been filled\n");
218     
219         sti.uCurrentTimeZoneId = 0xdeadbeef;
220         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 32, &ReturnLength);
221         ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
222         ok( 32 == ReturnLength, "ReturnLength should be 32, it is (%d)\n", ReturnLength);
223         ok( 0xdeadbeef != sti.uCurrentTimeZoneId, "Buffer should have been partially filled\n");
224     
225         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, 49, &ReturnLength);
226         ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
227         ok( ReturnLength == 0 || ReturnLength == sizeof(sti) /* vista */,
228             "ReturnLength should be 0, it is (%d)\n", ReturnLength);
229     
230         status = pNtQuerySystemInformation(SystemTimeOfDayInformation, &sti, sizeof(sti), &ReturnLength);
231         ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
232         ok( sizeof(sti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
233     }
234
235     /* Check if we have some return values */
236     trace("uCurrentTimeZoneId : (%d)\n", sti.uCurrentTimeZoneId);
237 }
238
239 static void test_query_process(void)
240 {
241     NTSTATUS status;
242     DWORD last_pid;
243     ULONG ReturnLength;
244     int i = 0, k = 0;
245     int is_nt = 0;
246     SYSTEM_BASIC_INFORMATION sbi;
247
248     /* Copy of our winternl.h structure turned into a private one */
249     typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE {
250         ULONG NextEntryOffset;
251         DWORD dwThreadCount;
252         DWORD dwUnknown1[6];
253         FILETIME ftCreationTime;
254         FILETIME ftUserTime;
255         FILETIME ftKernelTime;
256         UNICODE_STRING ProcessName;
257         DWORD dwBasePriority;
258         HANDLE UniqueProcessId;
259         HANDLE ParentProcessId;
260         ULONG HandleCount;
261         DWORD dwUnknown3;
262         DWORD dwUnknown4;
263         VM_COUNTERS vmCounters;
264         IO_COUNTERS ioCounters;
265         SYSTEM_THREAD_INFORMATION ti[1];
266     } SYSTEM_PROCESS_INFORMATION_PRIVATE, *PSYSTEM_PROCESS_INFORMATION_PRIVATE;
267
268     ULONG SystemInformationLength = sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE);
269     SYSTEM_PROCESS_INFORMATION_PRIVATE *spi, *spi_buf = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
270
271     /* Only W2K3 returns the needed length, the rest returns 0, so we have to loop */
272
273     for (;;)
274     {
275         status = pNtQuerySystemInformation(SystemProcessInformation, spi_buf, SystemInformationLength, &ReturnLength);
276
277         if (status != STATUS_INFO_LENGTH_MISMATCH) break;
278         
279         spi_buf = HeapReAlloc(GetProcessHeap(), 0, spi_buf , SystemInformationLength *= 2);
280     }
281     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
282     spi = spi_buf;
283
284     /* Get the first NextEntryOffset, from this we can deduce the OS version we're running
285      *
286      * W2K/WinXP/W2K3:
287      *   NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
288      * NT:
289      *   NextEntryOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION)
290      * Wine (with every windows version):
291      *   NextEntryOffset for a process is 0 if just this test is running
292      *   NextEntryOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) +
293      *                             ProcessName.MaximumLength
294      *     if more wine processes are running
295      *
296      * Note : On windows the first process is in fact the Idle 'process' with a thread for every processor
297     */
298
299     pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
300
301     is_nt = ( spi->NextEntryOffset - (sbi.NumberOfProcessors * sizeof(SYSTEM_THREAD_INFORMATION)) == 136);
302
303     if (is_nt) win_skip("Windows version is NT, we will skip thread tests\n");
304
305     /* Check if we have some return values
306      * 
307      * On windows there will be several processes running (Including the always present Idle and System)
308      * On wine we only have one (if this test is the only wine process running)
309     */
310     
311     /* Loop through the processes */
312
313     for (;;)
314     {
315         i++;
316
317         last_pid = (DWORD_PTR)spi->UniqueProcessId;
318
319         ok( spi->dwThreadCount > 0, "Expected some threads for this process, got 0\n");
320
321         /* Loop through the threads, skip NT4 for now */
322         
323         if (!is_nt)
324         {
325             DWORD j;
326             for ( j = 0; j < spi->dwThreadCount; j++) 
327             {
328                 k++;
329                 ok ( spi->ti[j].ClientId.UniqueProcess == spi->UniqueProcessId,
330                      "The owning pid of the thread (%p) doesn't equal the pid (%p) of the process\n",
331                      spi->ti[j].ClientId.UniqueProcess, spi->UniqueProcessId);
332             }
333         }
334
335         if (!spi->NextEntryOffset) break;
336
337         one_before_last_pid = last_pid;
338
339         spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->NextEntryOffset);
340     }
341     trace("Total number of running processes : %d\n", i);
342     if (!is_nt) trace("Total number of running threads   : %d\n", k);
343
344     if (one_before_last_pid == 0) one_before_last_pid = last_pid;
345
346     HeapFree( GetProcessHeap(), 0, spi_buf);
347 }
348
349 static void test_query_procperf(void)
350 {
351     NTSTATUS status;
352     ULONG ReturnLength;
353     ULONG NeededLength;
354     SYSTEM_BASIC_INFORMATION sbi;
355     SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi;
356
357     /* Find out the number of processors */
358     status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
359     NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
360
361     sppi = HeapAlloc(GetProcessHeap(), 0, NeededLength);
362
363     status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, 0, &ReturnLength);
364     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
365
366     /* Try it for 1 processor */
367     sppi->KernelTime.QuadPart = 0xdeaddead;
368     sppi->UserTime.QuadPart = 0xdeaddead;
369     sppi->IdleTime.QuadPart = 0xdeaddead;
370     status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi,
371                                        sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), &ReturnLength);
372     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
373     ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
374         "Inconsistent length %d\n", ReturnLength);
375     ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
376     ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
377     ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
378
379     /* Try it for all processors */
380     sppi->KernelTime.QuadPart = 0xdeaddead;
381     sppi->UserTime.QuadPart = 0xdeaddead;
382     sppi->IdleTime.QuadPart = 0xdeaddead;
383     status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength, &ReturnLength);
384     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
385     ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
386     ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
387     ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
388     ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
389
390     /* A too large given buffer size */
391     sppi = HeapReAlloc(GetProcessHeap(), 0, sppi , NeededLength + 2);
392     sppi->KernelTime.QuadPart = 0xdeaddead;
393     sppi->UserTime.QuadPart = 0xdeaddead;
394     sppi->IdleTime.QuadPart = 0xdeaddead;
395     status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength + 2, &ReturnLength);
396     ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH /* vista */,
397         "Expected STATUS_SUCCESS or STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
398     ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
399     if (status == STATUS_SUCCESS)
400     {
401         ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
402         ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
403         ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
404     }
405     else /* vista and 2008 */
406     {
407         ok (sppi->KernelTime.QuadPart == 0xdeaddead, "KernelTime changed\n");
408         ok (sppi->UserTime.QuadPart == 0xdeaddead, "UserTime changed\n");
409         ok (sppi->IdleTime.QuadPart == 0xdeaddead, "IdleTime changed\n");
410     }
411
412     HeapFree( GetProcessHeap(), 0, sppi);
413 }
414
415 static void test_query_module(void)
416 {
417     NTSTATUS status;
418     ULONG ReturnLength;
419     ULONG ModuleCount, i;
420
421     ULONG SystemInformationLength = sizeof(SYSTEM_MODULE_INFORMATION);
422     SYSTEM_MODULE_INFORMATION* smi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength); 
423     SYSTEM_MODULE* sm;
424
425     /* Request the needed length */
426     status = pNtQuerySystemInformation(SystemModuleInformation, smi, 0, &ReturnLength);
427     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
428     ok( ReturnLength > 0, "Expected a ReturnLength to show the needed length\n");
429
430     SystemInformationLength = ReturnLength;
431     smi = HeapReAlloc(GetProcessHeap(), 0, smi , SystemInformationLength);
432     status = pNtQuerySystemInformation(SystemModuleInformation, smi, SystemInformationLength, &ReturnLength);
433     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
434
435     ModuleCount = smi->ModulesCount;
436     sm = &smi->Modules[0];
437     /* our implementation is a stub for now */
438     ok( ModuleCount > 0, "Expected some modules to be loaded\n");
439
440     /* Loop through all the modules/drivers, Wine doesn't get here (yet) */
441     for (i = 0; i < ModuleCount ; i++)
442     {
443         ok( i == sm->Id, "Id (%d) should have matched %u\n", sm->Id, i);
444         sm++;
445     }
446
447     HeapFree( GetProcessHeap(), 0, smi);
448 }
449
450 static void test_query_handle(void)
451 {
452     NTSTATUS status;
453     ULONG ReturnLength;
454     ULONG SystemInformationLength = sizeof(SYSTEM_HANDLE_INFORMATION);
455     SYSTEM_HANDLE_INFORMATION* shi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength);
456
457     /* Request the needed length : a SystemInformationLength greater than one struct sets ReturnLength */
458     status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
459     todo_wine ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
460
461     SystemInformationLength = ReturnLength;
462     shi = HeapReAlloc(GetProcessHeap(), 0, shi , SystemInformationLength);
463     status = pNtQuerySystemInformation(SystemHandleInformation, shi, SystemInformationLength, &ReturnLength);
464     if (status != STATUS_INFO_LENGTH_MISMATCH) /* vista */
465     {
466         ok( status == STATUS_SUCCESS,
467             "Expected STATUS_SUCCESS, got %08x\n", status);
468
469         /* Check if we have some return values */
470         trace("Number of Handles : %d\n", shi->Count);
471         todo_wine
472         {
473             /* our implementation is a stub for now */
474             ok( shi->Count > 1, "Expected more than 1 handles, got (%d)\n", shi->Count);
475         }
476     }
477     HeapFree( GetProcessHeap(), 0, shi);
478 }
479
480 static void test_query_cache(void)
481 {
482     NTSTATUS status;
483     ULONG ReturnLength;
484     SYSTEM_CACHE_INFORMATION sci;
485
486     status = pNtQuerySystemInformation(SystemCacheInformation, &sci, 0, &ReturnLength);
487     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
488
489     status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci), &ReturnLength);
490     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
491     ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
492
493     status = pNtQuerySystemInformation(SystemCacheInformation, &sci, sizeof(sci) + 2, &ReturnLength);
494     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
495     ok( sizeof(sci) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
496 }
497
498 static void test_query_interrupt(void)
499 {
500     NTSTATUS status;
501     ULONG ReturnLength;
502     ULONG NeededLength;
503     SYSTEM_BASIC_INFORMATION sbi;
504     SYSTEM_INTERRUPT_INFORMATION* sii;
505
506     /* Find out the number of processors */
507     status = pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength);
508     NeededLength = sbi.NumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION);
509
510     sii = HeapAlloc(GetProcessHeap(), 0, NeededLength);
511
512     status = pNtQuerySystemInformation(SystemInterruptInformation, sii, 0, &ReturnLength);
513     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
514
515     /* Try it for all processors */
516     status = pNtQuerySystemInformation(SystemInterruptInformation, sii, NeededLength, &ReturnLength);
517     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
518
519     /* Windows XP and W2K3 (and others?) always return 0 for the ReturnLength
520      * No test added for this as it's highly unlikely that an app depends on this
521     */
522
523     HeapFree( GetProcessHeap(), 0, sii);
524 }
525
526 static void test_query_kerndebug(void)
527 {
528     NTSTATUS status;
529     ULONG ReturnLength;
530     SYSTEM_KERNEL_DEBUGGER_INFORMATION skdi;
531
532     status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, 0, &ReturnLength);
533     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
534
535     status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi), &ReturnLength);
536     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
537     ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
538
539     status = pNtQuerySystemInformation(SystemKernelDebuggerInformation, &skdi, sizeof(skdi) + 2, &ReturnLength);
540     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
541     ok( sizeof(skdi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
542 }
543
544 static void test_query_regquota(void)
545 {
546     NTSTATUS status;
547     ULONG ReturnLength;
548     SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
549
550     status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, 0, &ReturnLength);
551     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
552
553     status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi), &ReturnLength);
554     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
555     ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
556
557     status = pNtQuerySystemInformation(SystemRegistryQuotaInformation, &srqi, sizeof(srqi) + 2, &ReturnLength);
558     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
559     ok( sizeof(srqi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
560 }
561
562 static void test_query_process_basic(void)
563 {
564     NTSTATUS status;
565     ULONG ReturnLength;
566
567     typedef struct _PROCESS_BASIC_INFORMATION_PRIVATE {
568         DWORD_PTR ExitStatus;
569         PPEB      PebBaseAddress;
570         DWORD_PTR AffinityMask;
571         DWORD_PTR BasePriority;
572         ULONG_PTR UniqueProcessId;
573         ULONG_PTR InheritedFromUniqueProcessId;
574     } PROCESS_BASIC_INFORMATION_PRIVATE, *PPROCESS_BASIC_INFORMATION_PRIVATE;
575
576     PROCESS_BASIC_INFORMATION_PRIVATE pbi;
577
578     /* This test also covers some basic parameter testing that should be the same for
579      * every information class
580     */
581
582     /* Use a nonexistent info class */
583     trace("Check nonexistent info class\n");
584     status = pNtQueryInformationProcess(NULL, -1, NULL, 0, NULL);
585     ok( status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED /* vista */,
586         "Expected STATUS_INVALID_INFO_CLASS or STATUS_NOT_IMPLEMENTED, got %08x\n", status);
587
588     /* Do not give a handle and buffer */
589     trace("Check NULL handle and buffer and zero-length buffersize\n");
590     status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, 0, NULL);
591     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
592
593     /* Use a correct info class and buffer size, but still no handle and buffer */
594     trace("Check NULL handle and buffer\n");
595     status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, NULL, sizeof(pbi), NULL);
596     ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
597         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
598
599     /* Use a correct info class and buffer size, but still no handle */
600     trace("Check NULL handle\n");
601     status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
602     ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
603
604     /* Use a greater buffer size */
605     trace("Check NULL handle and too large buffersize\n");
606     status = pNtQueryInformationProcess(NULL, ProcessBasicInformation, &pbi, sizeof(pbi) * 2, NULL);
607     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
608
609     /* Use no ReturnLength */
610     trace("Check NULL ReturnLength\n");
611     status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
612     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
613
614     /* Finally some correct calls */
615     trace("Check with correct parameters\n");
616     status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), &ReturnLength);
617     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
618     ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
619
620     /* Everything is correct except a too large buffersize */
621     trace("Too large buffersize\n");
622     status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi) * 2, &ReturnLength);
623     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
624     ok( sizeof(pbi) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
625                                                                                                                                                
626     /* Check if we have some return values */
627     trace("ProcessID : %lx\n", pbi.UniqueProcessId);
628     ok( pbi.UniqueProcessId > 0, "Expected a ProcessID > 0, got 0\n");
629 }
630
631 static void test_query_process_vm(void)
632 {
633     NTSTATUS status;
634     ULONG ReturnLength;
635     VM_COUNTERS pvi;
636     ULONG old_size = FIELD_OFFSET(VM_COUNTERS,PrivatePageCount);
637
638     status = pNtQueryInformationProcess(NULL, ProcessVmCounters, NULL, sizeof(pvi), NULL);
639     ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
640         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
641
642     status = pNtQueryInformationProcess(NULL, ProcessVmCounters, &pvi, old_size, NULL);
643     ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
644
645     /* Windows XP and W2K3 will report success for a size of 44 AND 48 !
646        Windows W2K will only report success for 44.
647        For now we only care for 44, which is FIELD_OFFSET(VM_COUNTERS,PrivatePageCount))
648     */
649
650     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 24, &ReturnLength);
651     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
652
653     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, old_size, &ReturnLength);
654     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
655     ok( old_size == ReturnLength, "Inconsistent length %d\n", ReturnLength);
656
657     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessVmCounters, &pvi, 46, &ReturnLength);
658     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
659     ok( ReturnLength == old_size || ReturnLength == sizeof(pvi), "Inconsistent length %d\n", ReturnLength);
660
661     /* Check if we have some return values */
662     trace("WorkingSetSize : %ld\n", pvi.WorkingSetSize);
663     todo_wine
664     {
665         ok( pvi.WorkingSetSize > 0, "Expected a WorkingSetSize > 0\n");
666     }
667 }
668
669 static void test_query_process_io(void)
670 {
671     NTSTATUS status;
672     ULONG ReturnLength;
673     IO_COUNTERS pii;
674
675     /* NT4 doesn't support this information class, so check for it */
676     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
677     if (status == STATUS_NOT_SUPPORTED)
678     {
679         win_skip("ProcessIoCounters information class is not supported\n");
680         return;
681     }
682  
683     status = pNtQueryInformationProcess(NULL, ProcessIoCounters, NULL, sizeof(pii), NULL);
684     ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
685         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
686
687     status = pNtQueryInformationProcess(NULL, ProcessIoCounters, &pii, sizeof(pii), NULL);
688     ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
689
690     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, 24, &ReturnLength);
691     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
692
693     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii), &ReturnLength);
694     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
695     ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
696
697     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessIoCounters, &pii, sizeof(pii) * 2, &ReturnLength);
698     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
699     ok( sizeof(pii) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
700
701     /* Check if we have some return values */
702     trace("OtherOperationCount : 0x%x%08x\n", (DWORD)(pii.OtherOperationCount >> 32), (DWORD)pii.OtherOperationCount);
703     todo_wine
704     {
705         ok( pii.OtherOperationCount > 0, "Expected an OtherOperationCount > 0\n");
706     }
707 }
708
709 static void test_query_process_times(void)
710 {
711     NTSTATUS status;
712     ULONG ReturnLength;
713     HANDLE process;
714     SYSTEMTIME UTC, Local;
715     KERNEL_USER_TIMES spti;
716
717     status = pNtQueryInformationProcess(NULL, ProcessTimes, NULL, sizeof(spti), NULL);
718     ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
719         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
720
721     status = pNtQueryInformationProcess(NULL, ProcessTimes, &spti, sizeof(spti), NULL);
722     ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
723
724     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, 24, &ReturnLength);
725     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
726
727     process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
728     if (!process)
729     {
730         trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
731         process = GetCurrentProcess();
732         trace("ProcessTimes for current process\n");
733     }
734     else
735         trace("ProcessTimes for process with ID : %d\n", one_before_last_pid);
736
737     status = pNtQueryInformationProcess( process, ProcessTimes, &spti, sizeof(spti), &ReturnLength);
738     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
739     ok( sizeof(spti) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
740     CloseHandle(process);
741
742     FileTimeToSystemTime((const FILETIME *)&spti.CreateTime, &UTC);
743     SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
744     trace("CreateTime : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
745            Local.wHour, Local.wMinute, Local.wSecond);
746
747     FileTimeToSystemTime((const FILETIME *)&spti.ExitTime, &UTC);
748     SystemTimeToTzSpecificLocalTime(NULL, &UTC, &Local);
749     trace("ExitTime   : %02d/%02d/%04d %02d:%02d:%02d\n", Local.wMonth, Local.wDay, Local.wYear,
750            Local.wHour, Local.wMinute, Local.wSecond);
751
752     FileTimeToSystemTime((const FILETIME *)&spti.KernelTime, &Local);
753     trace("KernelTime : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
754
755     FileTimeToSystemTime((const FILETIME *)&spti.UserTime, &Local);
756     trace("UserTime   : %02d:%02d:%02d.%03d\n", Local.wHour, Local.wMinute, Local.wSecond, Local.wMilliseconds);
757
758     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessTimes, &spti, sizeof(spti) * 2, &ReturnLength);
759     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
760     ok( sizeof(spti) == ReturnLength ||
761         ReturnLength == 0 /* vista */ ||
762         broken(is_wow64),  /* returns garbage on wow64 */
763         "Inconsistent length %d\n", ReturnLength);
764 }
765
766 static void test_query_process_debug_port(int argc, char **argv)
767 {
768     DWORD_PTR debug_port = 0xdeadbeef;
769     char cmdline[MAX_PATH];
770     PROCESS_INFORMATION pi;
771     STARTUPINFO si = { 0 };
772     NTSTATUS status;
773     BOOL ret;
774
775     sprintf(cmdline, "%s %s %s", argv[0], argv[1], "debuggee");
776
777     si.cb = sizeof(si);
778     ret = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &si, &pi);
779     ok(ret, "CreateProcess failed, last error %#x.\n", GetLastError());
780     if (!ret) return;
781
782     status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
783             NULL, 0, NULL);
784     ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
785
786     status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
787             NULL, sizeof(debug_port), NULL);
788     ok(status == STATUS_INVALID_HANDLE || status == STATUS_ACCESS_VIOLATION,
789             "Expected STATUS_INVALID_HANDLE, got %#x.\n", status);
790
791     status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
792             NULL, sizeof(debug_port), NULL);
793     ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
794
795     status = pNtQueryInformationProcess(NULL, ProcessDebugPort,
796             &debug_port, sizeof(debug_port), NULL);
797     ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_ACCESS_VIOLATION, got %#x.\n", status);
798
799     status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
800             &debug_port, sizeof(debug_port) - 1, NULL);
801     ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
802
803     status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
804             &debug_port, sizeof(debug_port) + 1, NULL);
805     ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %#x.\n", status);
806
807     status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort,
808             &debug_port, sizeof(debug_port), NULL);
809     ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
810     ok(debug_port == 0, "Expected port 0, got %#lx.\n", debug_port);
811
812     status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugPort,
813             &debug_port, sizeof(debug_port), NULL);
814     ok(!status, "NtQueryInformationProcess failed, status %#x.\n", status);
815     ok(debug_port == ~(DWORD_PTR)0, "Expected port %#lx, got %#lx.\n", ~(DWORD_PTR)0, debug_port);
816
817     for (;;)
818     {
819         DEBUG_EVENT ev;
820
821         ret = WaitForDebugEvent(&ev, INFINITE);
822         ok(ret, "WaitForDebugEvent failed, last error %#x.\n", GetLastError());
823         if (!ret) break;
824
825         if (ev.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break;
826
827         ret = ContinueDebugEvent(ev.dwProcessId, ev.dwThreadId, DBG_CONTINUE);
828         ok(ret, "ContinueDebugEvent failed, last error %#x.\n", GetLastError());
829         if (!ret) break;
830     }
831
832     ret = CloseHandle(pi.hThread);
833     ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
834     ret = CloseHandle(pi.hProcess);
835     ok(ret, "CloseHandle failed, last error %#x.\n", GetLastError());
836 }
837
838 static void test_query_process_handlecount(void)
839 {
840     NTSTATUS status;
841     ULONG ReturnLength;
842     DWORD handlecount;
843     BYTE buffer[2 * sizeof(DWORD)];
844     HANDLE process;
845
846     status = pNtQueryInformationProcess(NULL, ProcessHandleCount, NULL, sizeof(handlecount), NULL);
847     ok( status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_HANDLE,
848         "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_HANDLE(W2K3), got %08x\n", status);
849
850     status = pNtQueryInformationProcess(NULL, ProcessHandleCount, &handlecount, sizeof(handlecount), NULL);
851     ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
852
853     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, &handlecount, 2, &ReturnLength);
854     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
855
856     process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, one_before_last_pid);
857     if (!process)
858     {
859         trace("Could not open process with ID : %d, error : %u. Going to use current one.\n", one_before_last_pid, GetLastError());
860         process = GetCurrentProcess();
861         trace("ProcessHandleCount for current process\n");
862     }
863     else
864         trace("ProcessHandleCount for process with ID : %d\n", one_before_last_pid);
865
866     status = pNtQueryInformationProcess( process, ProcessHandleCount, &handlecount, sizeof(handlecount), &ReturnLength);
867     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
868     ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
869     CloseHandle(process);
870
871     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessHandleCount, buffer, sizeof(buffer), &ReturnLength);
872     ok( status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_SUCCESS,
873         "Expected STATUS_INFO_LENGTH_MISMATCH or STATUS_SUCCESS, got %08x\n", status);
874     ok( sizeof(handlecount) == ReturnLength, "Inconsistent length %d\n", ReturnLength);
875
876     /* Check if we have some return values */
877     trace("HandleCount : %d\n", handlecount);
878     todo_wine
879     {
880         ok( handlecount > 0, "Expected some handles, got 0\n");
881     }
882 }
883
884 static void test_query_process_image_file_name(void)
885 {
886     NTSTATUS status;
887     ULONG ReturnLength;
888     UNICODE_STRING image_file_name;
889     void *buffer;
890     char *file_nameA;
891     INT len;
892
893     status = pNtQueryInformationProcess(NULL, ProcessImageFileName, &image_file_name, sizeof(image_file_name), NULL);
894     if (status == STATUS_INVALID_INFO_CLASS)
895     {
896         win_skip("ProcessImageFileName is not supported\n");
897         return;
898     }
899     ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
900
901     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, 2, &ReturnLength);
902     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
903
904     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, &image_file_name, sizeof(image_file_name), &ReturnLength);
905     ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
906
907     buffer = HeapAlloc(GetProcessHeap(), 0, ReturnLength);
908     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessImageFileName, buffer, ReturnLength, &ReturnLength);
909     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
910     memcpy(&image_file_name, buffer, sizeof(image_file_name));
911     len = WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), NULL, 0, NULL, NULL);
912     file_nameA = HeapAlloc(GetProcessHeap(), 0, len + 1);
913     WideCharToMultiByte(CP_ACP, 0, image_file_name.Buffer, image_file_name.Length/sizeof(WCHAR), file_nameA, len, NULL, NULL);
914     file_nameA[len] = '\0';
915     HeapFree(GetProcessHeap(), 0, buffer);
916     trace("process image file name: %s\n", file_nameA);
917     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);
918     HeapFree(GetProcessHeap(), 0, file_nameA);
919 }
920
921
922 static void test_readvirtualmemory(void)
923 {
924     HANDLE process;
925     NTSTATUS status;
926     SIZE_T readcount;
927     static const char teststring[] = "test string";
928     char buffer[12];
929
930     process = OpenProcess(PROCESS_VM_READ, FALSE, GetCurrentProcessId());
931     ok(process != 0, "Expected to be able to open own process for reading memory\n");
932
933     /* normal operation */
934     status = pNtReadVirtualMemory(process, teststring, buffer, 12, &readcount);
935     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
936     ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
937     ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
938
939     /* no number of bytes */
940     memset(buffer, 0, 12);
941     status = pNtReadVirtualMemory(process, teststring, buffer, 12, NULL);
942     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
943     ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
944
945     /* illegal remote address */
946     todo_wine{
947     status = pNtReadVirtualMemory(process, (void *) 0x1234, buffer, 12, &readcount);
948     ok( status == STATUS_PARTIAL_COPY || broken(status == STATUS_ACCESS_VIOLATION), "Expected STATUS_PARTIAL_COPY, got %08x\n", status);
949     if (status == STATUS_PARTIAL_COPY)
950         ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
951     }
952
953     /* 0 handle */
954     status = pNtReadVirtualMemory(0, teststring, buffer, 12, &readcount);
955     ok( status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got %08x\n", status);
956     ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
957
958     /* pseudo handle for current process*/
959     memset(buffer, 0, 12);
960     status = pNtReadVirtualMemory((HANDLE)-1, teststring, buffer, 12, &readcount);
961     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
962     ok( readcount == 12, "Expected to read 12 bytes, got %ld\n",readcount);
963     ok( strcmp(teststring, buffer) == 0, "Expected read memory to be the same as original memory\n");
964
965     /* illegal local address */
966     status = pNtReadVirtualMemory(process, teststring, (void *)0x1234, 12, &readcount);
967     ok( status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got %08x\n", status);
968     ok( readcount == 0, "Expected to read 0 bytes, got %ld\n",readcount);
969
970     CloseHandle(process);
971 }
972
973 static void test_affinity(void)
974 {
975     NTSTATUS status;
976     PROCESS_BASIC_INFORMATION pbi;
977     DWORD_PTR proc_affinity, thread_affinity;
978     THREAD_BASIC_INFORMATION tbi;
979     SYSTEM_INFO si;
980
981     GetSystemInfo(&si);
982     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
983     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
984     proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
985     ok( proc_affinity == (1 << si.dwNumberOfProcessors) - 1, "Unexpected process affinity\n" );
986     proc_affinity = 1 << si.dwNumberOfProcessors;
987     status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
988     ok( status == STATUS_INVALID_PARAMETER,
989         "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
990
991     proc_affinity = 0;
992     status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
993     ok( status == STATUS_INVALID_PARAMETER,
994         "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
995
996     status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
997     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
998     ok( tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1, "Unexpected thread affinity\n" );
999     thread_affinity = 1 << si.dwNumberOfProcessors;
1000     status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1001     ok( status == STATUS_INVALID_PARAMETER,
1002         "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1003     thread_affinity = 0;
1004     status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1005     ok( status == STATUS_INVALID_PARAMETER,
1006         "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1007
1008     thread_affinity = 1;
1009     status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1010     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1011     status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1012     ok( tbi.AffinityMask == 1, "Unexpected thread affinity\n" );
1013
1014     /* NOTE: Pre-Vista does not recognize the "all processors" flag (all bits set) */
1015     thread_affinity = ~(DWORD_PTR)0;
1016     status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1017     ok( broken(status == STATUS_INVALID_PARAMETER) || status == STATUS_SUCCESS,
1018         "Expected STATUS_SUCCESS, got %08x\n", status);
1019
1020     if (si.dwNumberOfProcessors <= 1)
1021     {
1022         skip("only one processor, skipping affinity testing\n");
1023         return;
1024     }
1025
1026     /* Test thread affinity mask resulting from "all processors" flag */
1027     if (status == STATUS_SUCCESS)
1028     {
1029         status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1030         ok( broken(tbi.AffinityMask == 1) || tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
1031             "Unexpected thread affinity\n" );
1032     }
1033     else
1034         skip("Cannot test thread affinity mask for 'all processors' flag\n");
1035
1036     proc_affinity = 2;
1037     status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
1038     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1039     status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL );
1040     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1041     proc_affinity = (DWORD_PTR)pbi.Reserved2[0];
1042     ok( proc_affinity == 2, "Unexpected process affinity\n" );
1043     /* Setting the process affinity changes the thread affinity to match */
1044     status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1045     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1046     ok( tbi.AffinityMask == 2, "Unexpected thread affinity\n" );
1047     /* The thread affinity is restricted to the process affinity */
1048     thread_affinity = 1;
1049     status = pNtSetInformationThread( GetCurrentThread(), ThreadAffinityMask, &thread_affinity, sizeof(thread_affinity) );
1050     ok( status == STATUS_INVALID_PARAMETER,
1051         "Expected STATUS_INVALID_PARAMETER, got %08x\n", status);
1052
1053     proc_affinity = (1 << si.dwNumberOfProcessors) - 1;
1054     status = pNtSetInformationProcess( GetCurrentProcess(), ProcessAffinityMask, &proc_affinity, sizeof(proc_affinity) );
1055     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1056     /* Resetting the process affinity also resets the thread affinity */
1057     status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL );
1058     ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
1059     ok( tbi.AffinityMask == (1 << si.dwNumberOfProcessors) - 1,
1060         "Unexpected thread affinity\n" );
1061 }
1062
1063 START_TEST(info)
1064 {
1065     char **argv;
1066     int argc;
1067
1068     if(!InitFunctionPtrs())
1069         return;
1070
1071     argc = winetest_get_mainargs(&argv);
1072     if (argc >= 3) return; /* Child */
1073
1074     /* NtQuerySystemInformation */
1075
1076     /* 0x0 SystemBasicInformation */
1077     trace("Starting test_query_basic()\n");
1078     test_query_basic();
1079
1080     /* 0x1 SystemCpuInformation */
1081     trace("Starting test_query_cpu()\n");
1082     test_query_cpu();
1083
1084     /* 0x2 SystemPerformanceInformation */
1085     trace("Starting test_query_performance()\n");
1086     test_query_performance();
1087
1088     /* 0x3 SystemTimeOfDayInformation */
1089     trace("Starting test_query_timeofday()\n");
1090     test_query_timeofday();
1091
1092     /* 0x5 SystemProcessInformation */
1093     trace("Starting test_query_process()\n");
1094     test_query_process();
1095
1096     /* 0x8 SystemProcessorPerformanceInformation */
1097     trace("Starting test_query_procperf()\n");
1098     test_query_procperf();
1099
1100     /* 0xb SystemModuleInformation */
1101     trace("Starting test_query_module()\n");
1102     test_query_module();
1103
1104     /* 0x10 SystemHandleInformation */
1105     trace("Starting test_query_handle()\n");
1106     test_query_handle();
1107
1108     /* 0x15 SystemCacheInformation */
1109     trace("Starting test_query_cache()\n");
1110     test_query_cache();
1111
1112     /* 0x17 SystemInterruptInformation */
1113     trace("Starting test_query_interrupt()\n");
1114     test_query_interrupt();
1115
1116     /* 0x23 SystemKernelDebuggerInformation */
1117     trace("Starting test_query_kerndebug()\n");
1118     test_query_kerndebug();
1119
1120     /* 0x25 SystemRegistryQuotaInformation */
1121     trace("Starting test_query_regquota()\n");
1122     test_query_regquota();
1123
1124     /* NtQueryInformationProcess */
1125
1126     /* 0x0 ProcessBasicInformation */
1127     trace("Starting test_query_process_basic()\n");
1128     test_query_process_basic();
1129
1130     /* 0x2 ProcessIoCounters */
1131     trace("Starting test_query_process_io()\n");
1132     test_query_process_io();
1133
1134     /* 0x3 ProcessVmCounters */
1135     trace("Starting test_query_process_vm()\n");
1136     test_query_process_vm();
1137
1138     /* 0x4 ProcessTimes */
1139     trace("Starting test_query_process_times()\n");
1140     test_query_process_times();
1141
1142     /* 0x7 ProcessDebugPort */
1143     trace("Starting test_process_debug_port()\n");
1144     test_query_process_debug_port(argc, argv);
1145
1146     /* 0x14 ProcessHandleCount */
1147     trace("Starting test_query_process_handlecount()\n");
1148     test_query_process_handlecount();
1149
1150     /* 27 ProcessImageFileName */
1151     trace("Starting test_query_process_image_file_name()\n");
1152     test_query_process_image_file_name();
1153
1154     /* belongs into it's own file */
1155     trace("Starting test_readvirtualmemory()\n");
1156     test_readvirtualmemory();
1157
1158     trace("Starting test_affinity()\n");
1159     test_affinity();
1160 }